home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
FMI Superhry 1
/
Superhry-I.bin
/
bonus
/
doom
/
programs
/
dmijum
/
wadfile.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-04-03
|
43KB
|
1,094 lines
/*
* WADFILE.C
*
* Version 1.0.0
*
* Abstract:
* This module contains all the WADFILE processing routines for the
* WadLib library.
*
* History:
* 1.0.0 (March 31, 1994)
*
* Author:
* Michael McMahon
*
****************************************************************************
* Wadfile Function Directory
*---------------------------------------------------------------------------
*Index: Name : Description
*---------------------------------------------------------------------------
* #1 : WadfileAddLump : Add a lump to a Wadfile being created.
* #2 : WadfileClose : Close file, flush cache, update WAD directory
* #3 : WadfileCopyEntry : Copies a lump from one Wadfile to another.
* #4 : WadfileCopyMap : Copies a map from one Wadfile to another.
* #5 : WadfileCreate : Create WAD file and initialize Wadfile struct.
* #6 : WadfileGetDirInfo : Read directory info into Wadfile structure.
* #7 : WadfileGetNextDirInfo : Move to next directory entry and read it in.
* #8 : WadfileGetPrevDirInfo : Move to last directory entry and read it in.
* #9 : WadfileInitialize : One-time call, set up memory allocators.
* #10 : WadfileLumpClose : Close lump inside WAD file, free its memory.
* #11 : WadfileLumpCopy : Copy lump file from one Wadfile to another.
* #12 : WadfileLumpOpen : Open lump at current directory position.
* #13 : WadfileOpen : Open a WAD file and initialize Wadfile struct.
* #14 : WadfileSeek : Find first dir entry with a search string.
* #15 : WadfileSeekMap : Find map given episode and map. ExMy
****************************************************************************
*
* WADLIB SOFTWARE LICENSE AGREEMENT
*
* 1. GRANT OF LICENSE. Michael McMahon and his affiliations (collectively
* the "AUTHOR") grant you (either an individual or an entity) the
* non-exclusive, royalty-free right to use this library source code,
* documentation, and sample code (collectively, the "SOFTWARE") for
* any lawful purpose subject to the terms of this license. By using the
* SOFTWARE you are agreeing to be bound to all the terms of this license.
*
* 2. COPYRIGHT. The SOFTWARE is Copyright (c) 1994, Michael McMahon,
* PO Box 14807, San Luis Nabisco, CA 93406-4807 USA. All Rights Reserved
* Worldwide. You may not use, modify, or distribute the SOFTWARE except
* as otherwise provided herein.
*
* 3. DECLARATION OF PUBLIC DOMAIN DISTRIBUTION AND USE. The distribution
* and use of the SOFTWARE is hereby designated PUBLIC DOMAIN by the
* the AUTHOR. You may not sell, rent, or lease this SOFTWARE. The
* SOFTWARE may be reproduced verbatim in part or in full by any
* reproduction means for any lawful purpose, and may also be subject to
* the following agreement.
*
* 4. AGREEMENT FOR USE OF SOFTWARE. The AUTHOR grants you a non-exclusive,
* royalty-free right to incorporate the SOFTWARE into any production for
* any legal purpose as long as you agree
* (a) to indemnify, hold harmless, and defend the AUTHOR from and against
* any claims or lawsuits, including attorneys' fees, that arise or
* result from the use or distribution of your software production; and
* (b) no matter how much the SOFTWARE is modified, the AUTHOR owns the
* copyright and this original, unmodified copyright notice remains
* intact in the source code; and,
* (c) the AUTHOR is not held responsible for fixing bugs or making
* enhancements or changes to the SOFTWARE for any reason; and,
* (d) the SOFTWARE is not redistributed if it is modified in any way; and,
* (e) otherwise comply with the terms of this agreement; and,
* (f) the AUTHOR is forgiven for making so many demands.
*
* THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. THE
* AUTHOR FURTHER DISCLAIMS ALL IMPLIED WARRANTIES, INCLUDING WITHOUT
* LIMITATION ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR OF FITNESS
* FOR A PARTICULAR PURPOSE. THE ENTIRE RISK ARISING OUT OF THE USE
* OR PERFORMANCE OF THE SOFTWARE REMAINS WITH YOU.
*
* The author can be reached at:
* Michael McMahon
* P.O. Box 14807
* San Luis Nabisco, CA 93406-4807 USA
* Internet: mmcmahon@oboe.calpoly.edu
* [Bug reports, suggestions, success stories, etc. are welcome; tech
* support, and other unnecessary two-way mail, is not]
*/
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <mem.h>
#include "general.h"
#include "wadfile.h"
/* Private wadfile variables */
static int wadfileInitialized=FALSE; /* Module doesn't work unless TRUE */
static WadfileMalloc wadfileMalloc; /* User's allocate memory routine */
static WadfileFree wadfileFree; /* User's free memory routine */
static int wadfileNumAllocations; /* Keeps track of the malloc's */
/*------------------------- Private routines ------------------------------*/
/**[ Internal 1 of 2 ]****************************************************
* *
* wf_malloc *
* *
* Desc: *
* This calls the user's memory allocation routine and updates *
* the 'wadfileNumAllocations' variable. *
* *
* Def: *
* static void * wf_malloc(unsigned long size); *
* *
* Parm: *
* size Number of bytes to allocate. *
* *
* Retn: *
* Pointer to allocated memory, or NULL if not enough memory. *
* *
* Notes: *
* This is the gateway for the WADFILE routines to access the user's *
* memory allocation routine. Don't call 'wadfileMalloc()' directly. *
* *
*************************************************************************/
static void * wf_malloc(unsigned long size)
{
void * result;
/* Sanity check */
assert(wadfileMalloc != NULL);
/* Allocate memory and bump wadfileNumAllocations if successful */
result = wadfileMalloc(size);
if (result != NULL)
wadfileNumAllocations++;
return result;
}
/**[ Internal 2 of 2 ]****************************************************
* *
* wf_free *
* *
* Desc: *
* This calls the user's memory de-allocation routine and updates *
* the 'wadfileNumAllocations' variable. *
* *
* Def: *
* static void wf_free(void * ptr); *
* *
* Parm: *
* ptr Valid memory pointer that was allocated with wf_malloc. *
* *
* Retn: *
* None *
* *
* Notes: *
* This is the gateway for the WADFILE routines to access the user's *
* memory deallocation routine. Don't call 'wadfileFree()' directly. *
* *
*************************************************************************/
static void wf_free(void * ptr)
{
/* Sanity check */
assert(wadfileFree != NULL);
/* Bounds check -- wf_malloc doesn't change wadfileNumAllocations
with a NULL value, so wf_free behaves the same way with NULL. */
if (ptr == NULL) return;
/* Free the memory and update counter */
wadfileFree(ptr);
wadfileNumAllocations--;
}
/*-------------------------- Public routines ------------------------------*/
/**[ #1 ]*****************************************************************
* *
* WadfileAddLump *
* *
* Desc: *
* This writes a lump to a Wadfile being created, and adds a *
* directory entry associated with the lump. *
* *
* Def: *
* int WadfileAddLump(Wadfile * wad, unsigned long size, *
* char * name, char * data); *
* *
* Parm: *
* wad Wadfile to add the lump data to. *
* size Size of lump data in bytes. *
* name Directory name of lump. IT MUST BE 8 CHARACTERS! *
* data Pointer to lump data. *
* *
* Retn: *
* TRUE if the data is added successfully, FALSE otherwise. *
* *
* Notes: *
* If compiling for a 16-bit target, the maximum lump size is 64k. *
* *
* 'name' should consist of capital letters, numbers, and the under- *
* score character. If the text is less than eight characters, it *
* must be padded with zeroes. For example: "E1M1\0\0\0\0" is correct.*
* *
*************************************************************************/
int WadfileAddLump(Wadfile * wad, unsigned long size, char * name, char * data)
{
unsigned long location;
char * ptr;
/* Make sure WadfileInitialize has been called */
assert(wadfileInitialized);
/* Bounds check */
if (!(wad->flags & FLAG_WADFILE_OPEN)) return FALSE;
if (!(wad->flags & FLAG_WADFILE_WRITEONLY)) return FALSE;
/* Bump up 'entryIndex' */
if (wad->entryIndex == INVALID_ENTRY)
wad->entryIndex = 0;
else
wad->entryIndex++;
if (wad->entryIndex >= wad->dirNumEntries) return FALSE;
/* Copy data to 'dirCache' */
location = ftell(wad->wf);
ptr = &wad->dirCache[wad->entryIndex*SIZEOF_WAD_DIR_ENTRY];
memcpy(ptr, &location, SIZEOF_WAD_DIR_LOCATION);
ptr += SIZEOF_WAD_DIR_LOCATION;
memcpy(ptr, &size, SIZEOF_WAD_DIR_SIZE);
ptr += SIZEOF_WAD_DIR_SIZE;
memcpy(ptr, name, SIZEOF_WAD_DIR_NAME);
/* Write data to Wadfile on disk */
if (size != 0)
fwrite(data, size, 1, wad->wf);
return TRUE;
}
/**[ #2 ]*****************************************************************
* *
* WadfileClose *
* *
* Desc: *
* This closes a Wadfile and flushes its disk cache. If the lump is *
* open, it is closed and the lump memory is released. If the *
* Wadfile is being created, the directory is written to disk and *
* the file header is updated before the Wadfile is closed. *
* *
* Def: *
* void WadfileClose(Wadfile * wad); *
* *
* Parm: *
* wad The Wadfile to close. *
* *
* Retn: *
* None. *
* *
*************************************************************************/
void WadfileClose(Wadfile * wad)
{
uint32 size, location;
/* Make sure WadfileInitialize has been called */
assert(wadfileInitialized);
/* If the file is open, flush caches, close file and clear the open flag */
if (wad->flags & FLAG_WADFILE_OPEN)
{
/* If creating a file, write directory entries and fix header */
if (wad->flags & FLAG_WADFILE_WRITEONLY)
{
if (wad->entryIndex != INVALID_ENTRY)
{
/* Initialize variables */
size = wad->entryIndex + 1;
location = ftell(wad->wf);
/* Write directory to disk */
fwrite(wad->dirCache, SIZEOF_WAD_DIR_ENTRY, size, wad->wf);
/* Fix WAD header */
fseek(wad->wf, SIZEOF_WAD_SIGNATURE, SEEK_SET);
fwrite(&size, sizeof(size), 1, wad->wf);
fwrite(&location, sizeof(location), 1, wad->wf);
}
else
{
/* Invalid Wad file, so destroy WAD Signature */
fseek(wad->wf, 0L, SEEK_SET);
size = 0;
fwrite(&size, SIZEOF_WAD_SIGNATURE, 1, wad->wf);
}
}
/* Flush 'dirCache' */
if (wad->flags & FLAG_WADFILE_DIRCACHED)
{
wf_free(wad->dirCache);
wad->flags ^= FLAG_WADFILE_DIRCACHED;
}
if (wad->flags & FLAG_LUMP_OPEN)
WadfileLumpClose(wad);
/* Close file */
fclose(wad->wf);
wad->flags ^= FLAG_WADFILE_OPEN;
}
}
/**[ #3 ]*****************************************************************
* *
* WadfileCopyEntry *
* *
* Desc: *
* This copies an arbitrary lump from an open Wadfile to a Wadfile *
* that is being created. Do not use 'WadfileLumpOpen' or *
* 'WadfileLumpClose' to initialize and release the lump data; this *
* routine is self-contained and opens, copies, and closes the lump *
* data in one fell swoop. *
* *
* Def: *
* int WadfileCopyEntry(Wadfile * dest, char * destName, *
* Wadfile * src, char * srcName) *
* *
* Parm: *
* dest A Wadfile that is being created. *
* destName The directory entry name for the new lump. *
* src An existing Wadfile. *
* srcName The directory entry name to search for and copy. *
* *
* Retn: *
* TRUE if lump is copied succesfully; FALSE otherwise. *
* *
* Notes: *
* On a 16-bit platform, this successfully copies lumps larger *
* than 64k. *
* *
*************************************************************************/
int WadfileCopyEntry(Wadfile * dest, char * destName,
Wadfile * src, char * srcName)
{
/* Sequentially search WAD directory for 'srcName' */
if (!WadfileSeek(src, srcName)) return FALSE;
/* Copy lump from source to destination */
if (!WadfileLumpCopy(dest, destName, src)) return FALSE;
return TRUE;
}
/**[ #4 ]*****************************************************************
* *
* WadfileCopyMap *
* *
* Desc: *
* This copies an arbitrary map from an open Wadfile to a Wadfile *
* that is being created. Do not use 'WadfileLumpOpen' or *
* 'WadfileLumpClose' to initialize and release the lump data; this *
* routine is self-contained and opens, copies, and closes the lump *
* data in one fell swoop. *
* *
* Def: *
* int WadfileCopyMap(Wadfile * dest, int destEpisode, int destMap, *
* Wadfile * src, int srcEpisode, int srcMap) *
* *
* Parm: *
* dest A Wadfile that is being created. *
* destEpisode The new episode number for the map data. *
* destMap The new map number for the map data. *
* src An existing Wadfile. *
* srcEpisode The old episode number for the map data. *
* srcMap The old map number for the map data. *
* *
* Retn: *
* TRUE if map is copied succesfully; FALSE otherwise. *
* *
* Notes: *
* On a 16-bit platform, this successfully copies lumps larger *
* than 64k. *
* *
*************************************************************************/
int WadfileCopyMap(Wadfile * dest, int destEpisode, int destMap,
Wadfile * src, int srcEpisode, int srcMap)
{
int i;
char targetName[SIZEOF_WAD_DIR_NAME];
/* Seek to map location, if possible */
if (!WadfileSeekMap(src, srcEpisode, srcMap)) return FALSE;
/* Copy the source map to destination map */
if (!WadfileLumpOpen(src)) return FALSE;
sprintf(targetName, "E%dM%d\0\0\0\0", destEpisode, destMap);
if (!WadfileAddLump(dest, src->lumpSize, targetName, src->lumpData))
return FALSE;
if (!WadfileLumpClose(src)) return FALSE;
/* Now that this is copied, go to next entry */
WadfileGetNextDirInfo(src);
/* Write out all other sections of the map */
for (i=0; i<NUM_ENTRIES_PER_MAP-1; i++)
{
/* Copy lump from source to destination */
if (!WadfileLumpCopy(dest, src->entryName, src))
return FALSE;
/* Go to next entry in the directory */
WadfileGetNextDirInfo(src);
}
return TRUE;
}
/**[ #5 ]*****************************************************************
* *
* WadfileCreate *
* *
* Desc: *
* This initializes a Wadfile structure, and creates a WAD file on *
* disk. This file can be either an IWAD or a PWAD file. *
* *
* Def: *
* int WadfileCreate(Wadfile * wad, char * filename, *
* int type, int maxEntries); *
* *
* Parm: *
* wad The Wadfile to create. *
* filename The filename (with path) to use. *
* type The file type, either IWAD or PWAD: *
* TYPE_IWAD Create an IWAD file. *
* TYPE_PWAD Create a PWAD file. *
* maxEntries The maximum number of directory entries that can be *
* used in this Wadfile. *
* *
* Retn: *
* TRUE if the Wadfile is created successfully, FALSE otherwise. *
* *
* Notes: *
* If 'filename' exists on disk, the function fails. YOU must delete *
* the file before calling this function. *
* *
* 'filename' should have a ".WAD" extension. *
* *
* There is no reason to create an IWAD file. You should always *
* create a PWAD file. *
* *
* Be liberal when choosing 'maxEntries'. You have less RAM is you *
* choose too high, the program crashes if you choose too low. Each *
* entry takes 16 bytes of RAM. The registered DOOM has just over *
* 2000 entries. *
* *
*************************************************************************/
int WadfileCreate(Wadfile * wad, char * filename, int type, int maxEntries)
{
uint32 longint;
char s[SIZEOF_WAD_SIGNATURE+1];
/* Make sure WadfileInitialize has been called */
assert(wadfileInitialized);
/* Bounds check */
if (filename == NULL) return FALSE;
if ((type != TYPE_IWAD) && (type != TYPE_PWAD)) return FALSE;
if (maxEntries <= 0) return FALSE;
/* Make sure the memory allocation routines exist */
if (wadfileMalloc == NULL) return FALSE;
/* Initialize WAD structure */
wad->flags = 0;
wad->dirNumEntries = maxEntries;
wad->entryIndex = INVALID_ENTRY;
wad->entryName[SIZEOF_WAD_DIR_NAME] = 0; /* Permanent end of string mark */
wad->dirCache = NULL;
/* Make sure the file doesn't already exist */
wad->wf = fopen(filename, "rb");
if (wad->wf!=NULL) return FALSE;
/* Create the file, return if error */
wad->wf = fopen(filename, "wb");
if (wad->wf==NULL) return FALSE;
wad->flags ^= FLAG_WADFILE_OPEN;
wad->flags ^= FLAG_WADFILE_WRITEONLY;
/* Write signature to the Wadfile */
if (type==TYPE_IWAD)
strcpy(s, IWAD_SIGNATURE);
else
strcpy(s, PWAD_SIGNATURE);
s[SIZEOF_WAD_SIGNATURE] = 0;
fwrite(s, SIZEOF_WAD_SIGNATURE, 1, wad->wf);
/* Write out dummy values for dir location and size as placeholders */
longint=0;
fwrite(&longint, sizeof(longint), 1, wad->wf);
fwrite(&longint, sizeof(longint), 1, wad->wf);
/* Create the directory with 'maxEntries' number of entries */
wad->dirCache = wf_malloc(maxEntries*SIZEOF_WAD_DIR_ENTRY);
if (wad->dirCache == NULL)
{
WadfileClose(wad);
return FALSE;
}
wad->flags |= FLAG_WADFILE_DIRCACHED;
return TRUE;
}
/**[ #6 ]*****************************************************************
* *
* WadfileGetDirInfo *
* *
* Desc: *
* This loads a specific Wadfile directory entry into a Wadfile *
* structure. *
* *
* Def: *
* int WadfileGetDirInfo(Wadfile * wad, int entryIndex); *
* *
* Parm: *
* wad The Wadfile structure to process. *
* entryIndex Directory index to load in. *
* *
* Retn: *
* TRUE if entry found and loaded succesfully; FALSE otherwise. *
* *
*************************************************************************/
int WadfileGetDirInfo(Wadfile * wad, int entryIndex)
{
/* Make sure WadfileInitialize has been called */
assert(wadfileInitialized);
/* Bounds check */
if (entryIndex < 0) return FALSE;
if (!(wad->flags & FLAG_WADFILE_OPEN)) return FALSE;
if (entryIndex > wad->dirNumEntries) return FALSE;
/* Copy info from memory or disk */
if (wad->flags & FLAG_WADFILE_DIRCACHED)
{
/* From memory cache */
memcpy(&wad->entryLocation, &wad->dirCache[entryIndex*SIZEOF_WAD_DIR_ENTRY], SIZEOF_WAD_DIR_ENTRY);
}
else
{
/* Seek to the correct directory entry and read it in from disk */
fseek(wad->wf, wad->dirLocation + SIZEOF_WAD_DIR_ENTRY*entryIndex, SEEK_SET);
fread(&wad->entryLocation, SIZEOF_WAD_DIR_ENTRY, 1, wad->wf);
}
/* Update WAD structure */
wad->entryIndex = entryIndex;
return TRUE;
}
/**[ #7 ]*****************************************************************
* *
* WadfileGetNextDirInfo *
* *
* Desc: *
* This loads the next Wadfile directory entry into a Wadfile *
* structure. *
* *
* Def: *
* int WadfileGetNextDirInfo(Wadfile * wad); *
* *
* Parm: *
* wad The Wadfile structure to process. *
* *
* Retn: *
* TRUE if entry loaded succesfully; FALSE otherwise. *
* *
* Notes: *
* This routine fails if you haven't called 'WadfileGetDirInfo' at *
* least once with this Wadfile variable. *
* *
*************************************************************************/
int WadfileGetNextDirInfo(Wadfile * wad)
{
/* Make sure WadfileInitialize has been called */
assert(wadfileInitialized);
return WadfileGetDirInfo(wad, wad->entryIndex+1);
}
/**[ #8 ]*****************************************************************
* *
* WadfileGetPrevDirInfo *
* *
* Desc: *
* This loads the previous Wadfile directory entry into a Wadfile *
* structure. *
* *
* Def: *
* int WadfileGetPrevDirInfo(Wadfile * wad); *
* *
* Parm: *
* wad The Wadfile structure to process. *
* *
* Retn: *
* TRUE if entry loaded succesfully; FALSE otherwise. *
* *
* Notes: *
* This routine fails if you haven't called 'WadfileGetDirInfo' at *
* least once with this Wadfile variable. *
* *
*************************************************************************/
int WadfileGetPrevDirInfo(Wadfile * wad)
{
/* Make sure WadfileInitialize has been called */
assert(wadfileInitialized);
return WadfileGetDirInfo(wad, wad->entryIndex-1);
}
/**[ #9 ]*****************************************************************
* *
* WadfileInitialize *
* *
* Desc: *
* This initializes the Wadfile support and must be called before *
* any other Wadfile routines are called. *
* *
* Def: *
* int WadfileInitialize(WadfileMalloc * wfm, WadfileFree * wff); *
* *
* Parm: *
* wfm Malloc routine for Wadfile routines (can be NULL) *
* wff Free memory routine for Wadfile routines (can be NULL) *
* *
* Retn: *
* TRUE if the memory routines are operational, FALSE otherwise. *
* *
* Notes: *
* Either both of the parameters are NULL or not. It is a fatal error *
* to specify one routine and not the other. *
* *
* Any time you want to specify different memory allocation routines *
* for the Wadfile library, just call this routine again. If there *
* are lingering allocations, the function will fail. *
* *
*************************************************************************/
int WadfileInitialize(WadfileMalloc wfm, WadfileFree wff)
{
/* Bounds check--vital enough to be asserts */
assert(((wfm==NULL) && (wff==NULL))||
((wfm!=NULL) && (wff!=NULL)));
/* See if we're getting re-initialized */
if (wadfileInitialized)
{
/* Any lingering allocations? */
if (wadfileNumAllocations)
wadfileInitialized = FALSE;
else
{
/* No? Re-initialize. */
wadfileMalloc = wfm;
wadfileFree = wff;
}
}
else
{
/* Make sure the compiler understands the code */
assert(sizeof(int16) == 2);
assert(sizeof(uint16) == 2);
assert(sizeof(int32) == 4);
assert(sizeof(uint32) == 4);
/* Initialize the memory handlers */
wadfileNumAllocations = 0;
wadfileMalloc = wfm;
wadfileFree = wff;
wadfileInitialized = TRUE;
}
return wadfileInitialized;
}
/**[ #10 ]****************************************************************
* *
* WadfileLumpClose *
* *
* Desc: *
* This releases the memory allocated to the lump that is stored *
* in a Wadfile structure. This memory is allocated and filled *
* by the 'WadfileLumpOpen' routine. *
* *
* Def: *
* int WadfileLumpClose(Wadfile * wad); *
* *
* Parm: *
* wad The Wadfile structure to process. *
* *
* Retn: *
* TRUE if lump memory freed succesfully; FALSE otherwise. *
* *
*************************************************************************/
int WadfileLumpClose(Wadfile * wad)
{
/* Make sure WadfileInitialize has been called */
assert(wadfileInitialized);
/* Bounds check */
if (wadfileMalloc==NULL) return FALSE;
if (!(wad->flags & FLAG_LUMP_OPEN)) return FALSE;
/* Deallocate the LUMP data */
if (wad->lumpSize != 0)
wf_free(wad->lumpData);
/* Update Wadfile structure */
wad->flags ^= FLAG_LUMP_OPEN;
return TRUE;
}
/**[ #11 ]****************************************************************
* *
* WadfileLumpCopy *
* *
* Desc: *
* This copies the lump data from an open Wadfile to a Wadfile that *
* is being created. Do not use 'WadfileLumpOpen' or *
* 'WadfileLumpClose' to initialize and release the lump data; this *
* routine is self-contained and opens, copies, and closes the lump *
* data in one fell swoop. *
* *
* Def: *
* int WadfileLumpCopy(Wadfile * dest, char * destName, Wadfile * src); *
* *
* Parm: *
* dest A Wadfile that is being created. *
* destName The directory entry name for the new lump. *
* src An existing Wadfile. *
* *
* Retn: *
* TRUE if lump is copied succesfully; FALSE otherwise. *
* *
* Notes: *
* On a 16-bit platform, this successfully copies lumps larger *
* than 64k. *
* *
*************************************************************************/
int WadfileLumpCopy(Wadfile * dest, char * destName, Wadfile * src)
{
unsigned long allocSize;
unsigned long lumpCopySize;
unsigned long location;
char * ptr;
/* Make sure WadfileInitialize has been called */
assert(wadfileInitialized);
/* Bounds check */
if (wadfileMalloc==NULL) return FALSE;
if (!(dest->flags & FLAG_WADFILE_OPEN)) return FALSE;
if (!(src->flags & FLAG_WADFILE_OPEN)) return FALSE;
if (!(dest->flags & FLAG_WADFILE_WRITEONLY)) return FALSE;
if (src->flags & FLAG_WADFILE_WRITEONLY) return FALSE;
if (dest->flags & FLAG_LUMP_OPEN) return FALSE;
if (src->entryIndex == INVALID_ENTRY) return FALSE;
if (destName == NULL) return FALSE;
/* Set LUMP variables */
dest->lumpLocation = src->entryLocation;
dest->lumpSize = src->entrySize;
memcpy(dest->lumpName, destName, SIZEOF_WAD_DIR_NAME);
location = ftell(dest->wf);
/* Seek to start of data to be read */
fseek(src->wf, src->entryLocation, SEEK_SET);
/* Set up loop control variable */
lumpCopySize = dest->lumpSize;
/* Do the copy */
while (lumpCopySize != 0)
{
/* Allocate a buffer */
if (lumpCopySize >= MALLOC_MAX)
allocSize = MALLOC_MAX;
else
allocSize = lumpCopySize;
dest->lumpData = wf_malloc(allocSize);
if (dest->lumpData == NULL) return FALSE;
/* Read LUMP data from 'src' and write to 'dest' */
fread(dest->lumpData, allocSize, 1, src->wf);
fwrite(dest->lumpData, allocSize, 1, dest->wf);
/* Free the buffer */
wf_free(dest->lumpData);
/* Update our byte count */
lumpCopySize -= allocSize;
} /* while */
/* Bump up 'entryIndex' */
if (dest->entryIndex == INVALID_ENTRY)
dest->entryIndex = 0;
else
dest->entryIndex++;
if (dest->entryIndex >= dest->dirNumEntries) return FALSE;
/* Copy data to 'dirCache' */
ptr = &dest->dirCache[dest->entryIndex*SIZEOF_WAD_DIR_ENTRY];
memcpy(ptr, &location, SIZEOF_WAD_DIR_LOCATION);
ptr += SIZEOF_WAD_DIR_LOCATION;
memcpy(ptr, &dest->lumpSize, SIZEOF_WAD_DIR_SIZE);
ptr += SIZEOF_WAD_DIR_SIZE;
memcpy(ptr, dest->lumpName, SIZEOF_WAD_DIR_NAME);
return TRUE;
}
/**[ #12 ]****************************************************************
* *
* WadfileLumpOpen *
* *
* Desc: *
* This allocates memory and reads in the lump associated with the *
* current directory entry in the Wadfile structure. The memory *
* is released later on by using the 'WadfileLumpClose' routine. *
* *
* Def: *
* int WadfileLumpOpen(Wadfile * wad); *
* *
* Parm: *
* wad The Wadfile structure to process. *
* *
* Retn: *
* TRUE if lump allocated and read in succesfully; FALSE otherwise. *
* *
* Notes: *
* This routine fails if you haven't called 'WadfileGetDirInfo' at *
* least once with this Wadfile variable. *
* *
* If you're using a 16-bit compiler, the maximum lump size is 64k. *
* This function fails if the lump is too big. Only 1 lump out of *
* 2045 in the registered version of DOOM is >64kb. (E2M7 SIDEDEFS) *
* Use 'WadfileLumpCopy' to work around the 64k limitation. *
* *
*************************************************************************/
int WadfileLumpOpen(Wadfile * wad)
{
/* Make sure WadfileInitialize has been called */
assert(wadfileInitialized);
/* Bounds check */
if (wadfileMalloc==NULL) return FALSE;
if (!(wad->flags & FLAG_WADFILE_OPEN)) return FALSE;
if (wad->flags & FLAG_WADFILE_WRITEONLY) return FALSE;
if (wad->flags & FLAG_LUMP_OPEN) return FALSE;
if (wad->entryIndex == INVALID_ENTRY) return FALSE;
/* Allocate memory for LUMP */
if (wad->entrySize != 0)
{
wad->lumpData = wf_malloc(wad->entrySize);
if (wad->lumpData == NULL) return FALSE;
}
/* Set LUMP variables */
wad->lumpLocation = wad->entryLocation;
wad->lumpSize = wad->entrySize;
memcpy(wad->lumpName, wad->entryName, SIZEOF_WAD_DIR_NAME);
/* Read LUMP data from disk */
if (wad->lumpSize != 0)
{
fseek(wad->wf, wad->entryLocation, SEEK_SET);
fread(wad->lumpData, wad->lumpSize, 1, wad->wf);
}
/* Update Wadfile structure */
wad->flags |= FLAG_LUMP_OPEN;
return TRUE;
}
/**[ #13 ]****************************************************************
* *
* WadfileOpen *
* *
* Desc: *
* This opens a WAD file and initializes a Wadfile context. *
* *
* Def: *
* int WadfileOpen(Wadfile * wad, char * filename, int type); *
* *
* Parm: *
* wad The Wadfile context *
* filename The file name (including path) of the WAD file. *
* type The type of WAD file to open: *
* WANTIWAD accept only IWAD files. *
* WANTPWAD accept only PWAD files. *
* IWADPWAD accept either IWAD or PWAD files. *
* *
* Retn: *
* TRUE if the file exists and is open, FALSE otherwise. *
* *
*************************************************************************/
int WadfileOpen(Wadfile * wad, char * filename, int type)
{
uint32 longint;
char s[SIZEOF_WAD_SIGNATURE+1];
/* Make sure WadfileInitialize has been called */
assert(wadfileInitialized);
/* Initialize WAD structure */
wad->flags = 0;
wad->entryIndex = INVALID_ENTRY;
wad->entryName[SIZEOF_WAD_DIR_NAME] = 0; /* Permanent end of string mark */
wad->dirCache = NULL;
/* Open the file, return if error */
wad->wf = fopen(filename, "rb");
if (wad->wf==NULL) return FALSE;
wad->flags ^= FLAG_WADFILE_OPEN;
/* Read in and check the WAD file signature */
fread(s, SIZEOF_WAD_SIGNATURE, 1, wad->wf);
s[SIZEOF_WAD_SIGNATURE] = 0;
if (strcmp(s, IWAD_SIGNATURE) == 0)
wad->flags |= FLAG_WADFILE_IWAD;
else
if (strcmp(s, PWAD_SIGNATURE) != 0)
goto Exit_Error;
/* Read in directory location and size */
fread(&longint, sizeof(longint), 1, wad->wf);
wad->dirNumEntries = longint;
fread(&longint, sizeof(longint), 1, wad->wf);
wad->dirLocation = longint;
/* Make sure the file type matches what the caller is asking for */
if (((type == WANTPWAD)&&(wad->flags & FLAG_WADFILE_IWAD)) ||
((type == WANTIWAD)&&(!(wad->flags & FLAG_WADFILE_IWAD))))
{
Exit_Error:
WadfileClose(wad);
return FALSE;
}
/* If memory allocation is available, try to cache the directory */
if (wadfileMalloc != NULL)
{
wad->dirCache = wf_malloc(wad->dirNumEntries*SIZEOF_WAD_DIR_ENTRY);
if (wad->dirCache != NULL)
{
wad->flags |= FLAG_WADFILE_DIRCACHED;
fseek(wad->wf, wad->dirLocation, SEEK_SET);
fread(wad->dirCache, wad->dirNumEntries*SIZEOF_WAD_DIR_ENTRY,
1,wad->wf);
}
}
return TRUE;
}
/**[ #14 ]****************************************************************
* *
* WadfileSeek *
* *
* Desc: *
* This routine does a linear search through the Wadfile's directory *
* starting with the first directory entry and searching until it *
* finds its target or hits the end of the directory. *
* *
* Def: *
* int WadfileSeek(Wadfile * wad, char * targetName); *
* *
* Parm: *
* wad The Wadfile structure to process. *
* targetName The name of the target directory entry. *
* *
* Retn: *
* TRUE if target was found succesfully; FALSE otherwise. *
* If TRUE, then the Wadfile's 'entryIndex', 'entryName', *
* 'entrySize', and 'entryLocation' contain meaningful values. *
* *
* Notes: *
* 'targetName' can be less than 8 characters; that is, you do not *
* have to pad it with zeroes, like in 'WadfileAddLump'. *
* *
* See also 'WadfileSeekMap' if you are looking for a specific map. *
* *
*************************************************************************/
int WadfileSeek(Wadfile * wad, char * targetName)
{
int i;
char targetString[SIZEOF_WAD_DIR_NAME+1];
/* Make sure WadfileInitialize has been called */
assert(wadfileInitialized);
/* Convert target name to a null-terminated string */
strncpy(targetString, targetName, SIZEOF_WAD_DIR_NAME);
targetString[SIZEOF_WAD_DIR_NAME] = '\0';
/* Bounds Check */
if (!(wad->flags & FLAG_WADFILE_OPEN)) return FALSE;
if (targetString == NULL) return FALSE; /* Too small */
if (strlen(targetString)>SIZEOF_WAD_DIR_NAME) return FALSE; /* Too big */
/* Begin linear search of the WAD directory */
i=0;
while ((i<wad->dirNumEntries)&&(strcmp(wad->entryName, targetString) !=0))
{
WadfileGetDirInfo(wad, i);
i++;
}
return (i<wad->dirNumEntries);
}
/**[ #15 ]****************************************************************
* *
* WadfileSeekMap *
* *
* Desc: *
* This routine does a linear search through the Wadfile's directory *
* starting with the first directory entry and searching until it *
* finds its target map or hits the end of the directory. *
* *
* Def: *
* int WadfileSeekMap(Wadfile * wad, int episodeNum, int mapNum); *
* *
* Parm: *
* wad The Wadfile structure to process. *
* episodeNum Episode to find. Valid range is 1...DOOM_LASTEPISODE. *
* mapNum Map to find. Valid range is 1...DOOM_LASTMAP. *
* *
* Retn: *
* TRUE if target was found succesfully; FALSE otherwise. *
* If TRUE, then the Wadfile's 'entryIndex', 'entryName', *
* 'entrySize', and 'entryLocation' contain meaningful values. *
* *
* Notes: *
* This routine uses 'WadfileSeek' as its search engine. When you *
* aren't looking for maps, use 'WadfileSeek'. *
* *
*************************************************************************/
int WadfileSeekMap(Wadfile * wad, int episodeNum, int mapNum)
{
char targetName[5];
/* Make sure WadfileInitialize has been called */
assert(wadfileInitialized);
/* Bounds Check */
if ((episodeNum < 0) || (episodeNum > DOOM_LASTEPISODE)) return FALSE;
if ((mapNum < 0) || (mapNum > DOOM_LASTMAP)) return FALSE;
/* Compose directory name */
sprintf(targetName, "E%dM%d",episodeNum, mapNum);
/* Sequentially search WAD directory for ExMy */
return WadfileSeek(wad, targetName);
}