858 lines
19 KiB
C++
858 lines
19 KiB
C++
/*
|
|
This file is part of Warzone 2100.
|
|
Copyright (C) 1999-2004 Eidos Interactive
|
|
Copyright (C) 2005-2013 Warzone 2100 Project
|
|
|
|
Warzone 2100 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.
|
|
|
|
Warzone 2100 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 Warzone 2100; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
/**
|
|
* @file data.c
|
|
*
|
|
* Data loading functions used by the framework resource module.
|
|
*
|
|
*/
|
|
|
|
#include <physfs.h>
|
|
|
|
#include "lib/framework/frame.h"
|
|
#include "lib/framework/frameresource.h"
|
|
#include "lib/framework/strres.h"
|
|
#include "lib/framework/crc.h"
|
|
#include "lib/framework/resly.h"
|
|
#include "lib/gamelib/parser.h"
|
|
#include "lib/ivis_opengl/bitimage.h"
|
|
#include "lib/ivis_opengl/png_util.h"
|
|
#include "lib/script/script.h"
|
|
#include "lib/sound/audio.h"
|
|
|
|
#include "qtscript.h"
|
|
#include "data.h"
|
|
#include "droid.h"
|
|
#include "feature.h"
|
|
#include "mechanics.h"
|
|
#include "message.h"
|
|
#include "multiplay.h"
|
|
#include "research.h"
|
|
#include "scriptvals.h"
|
|
#include "stats.h"
|
|
#include "template.h"
|
|
#include "text.h"
|
|
#include "texture.h"
|
|
|
|
// whether a save game is currently being loaded
|
|
static bool saveFlag = false;
|
|
|
|
uint32_t DataHash[DATA_MAXDATA]= {0};
|
|
|
|
/**
|
|
* hashBuffer()
|
|
* \param pData pointer to our buffer (always a text file)
|
|
* \param size the size of the buffer
|
|
* \return hash calculated from the buffer.
|
|
*
|
|
* Note, this is obviously not a very complex hash routine. This most likely has many collisions possible.
|
|
* This is almost the same routine that Pumpkin had, minus the ugly bug :)
|
|
* And minus the old algorithm and debugging trace, replaced with a simple CRC...
|
|
*/
|
|
static UDWORD hashBuffer(uint8_t *pData, uint32_t size)
|
|
{
|
|
char nl = '\n';
|
|
uint32_t crc = 0;
|
|
uint32_t i, j;
|
|
uint32_t lines = 0;
|
|
uint32_t bytes = 0;
|
|
for (i = 0; i < size; i = j + 1)
|
|
{
|
|
for (j = i; j < size && pData[j] != '\n' && pData[j] != '\r'; ++j)
|
|
{}
|
|
|
|
if (i != j) // CRC non-empty lines only.
|
|
{
|
|
crc = crcSum(crc, pData + i, j - i); // CRC the line.
|
|
crc = crcSum(crc, &nl, 1); // CRC the line ending.
|
|
|
|
++lines;
|
|
bytes += j - i + 1;
|
|
}
|
|
}
|
|
debug(LOG_NET, "The size of the old buffer (%u bytes - %d stripped), New buffer size of %u bytes, %u non-empty lines.", size, size - bytes, bytes, lines);
|
|
|
|
return ~crc;
|
|
}
|
|
|
|
// create the hash for that data block.
|
|
// Data should be converted to Network byte order
|
|
static void calcDataHash(uint8_t *pBuffer, uint32_t size, uint32_t index)
|
|
{
|
|
const uint32_t oldHash = DataHash[index];
|
|
|
|
if (!bMultiPlayer)
|
|
{
|
|
return;
|
|
}
|
|
|
|
DataHash[index] += hashBuffer(pBuffer, size);
|
|
|
|
if (!DataHash[index] && oldHash)
|
|
{
|
|
debug(LOG_NET, "The new hash is 0, the old hash was %u. We added the negated value!", oldHash);
|
|
}
|
|
|
|
debug(LOG_NET, "DataHash[%2u] = %08x", index, DataHash[index]);
|
|
|
|
return;
|
|
}
|
|
|
|
void resetDataHash(void)
|
|
{
|
|
UDWORD i;
|
|
for (i = 0; i < DATA_MAXDATA; i++)
|
|
{
|
|
DataHash[i] = 0;
|
|
}
|
|
debug(LOG_NET, "== Hash is reset ==");
|
|
}
|
|
|
|
/**********************************************************/
|
|
|
|
|
|
void dataSetSaveFlag(void)
|
|
{
|
|
saveFlag = true;
|
|
}
|
|
void dataClearSaveFlag(void)
|
|
{
|
|
saveFlag = false;
|
|
}
|
|
|
|
/* Load the body stats */
|
|
static bool bufferSBODYLoad(const char* fileName, void** ppData)
|
|
{
|
|
if (!loadBodyStats(fileName) || !allocComponentList(COMP_BODY, numBodyStats))
|
|
{
|
|
return false;
|
|
}
|
|
*ppData = (void *)1;
|
|
return true;
|
|
}
|
|
|
|
static void dataReleaseStats(WZ_DECL_UNUSED void *pData)
|
|
{
|
|
// FIXME, huge hack, is called many times!
|
|
freeComponentLists();
|
|
statsShutDown();
|
|
}
|
|
|
|
|
|
/* Load the weapon stats */
|
|
static bool bufferSWEAPONLoad(const char *fileName, void **ppData)
|
|
{
|
|
if (!loadWeaponStats(fileName)
|
|
|| !allocComponentList(COMP_WEAPON, numWeaponStats))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// not interested in this value
|
|
*ppData = NULL;
|
|
return true;
|
|
}
|
|
|
|
/* Load the constructor stats */
|
|
static bool bufferSCONSTRLoad(const char *fileName, void **ppData)
|
|
{
|
|
if (!loadConstructStats(fileName)
|
|
|| !allocComponentList(COMP_CONSTRUCT, numConstructStats))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
//not interested in this value
|
|
*ppData = NULL;
|
|
return true;
|
|
}
|
|
|
|
/* Load the ECM stats */
|
|
static bool bufferSECMLoad(const char *fileName, void **ppData)
|
|
{
|
|
if (!loadECMStats(fileName)
|
|
|| !allocComponentList(COMP_ECM, numECMStats))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
//not interested in this value
|
|
*ppData = NULL;
|
|
return true;
|
|
}
|
|
|
|
/* Load the Propulsion stats */
|
|
static bool bufferSPROPLoad(const char* fileName, void** ppData)
|
|
{
|
|
if (!loadPropulsionStats(fileName) || !allocComponentList(COMP_PROPULSION, numPropulsionStats))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
//not interested in this value
|
|
*ppData = (void *)1;
|
|
return true;
|
|
}
|
|
|
|
static bool bufferSSENSORLoad(const char *fileName, void **ppData)
|
|
{
|
|
if (!loadSensorStats(fileName)
|
|
|| !allocComponentList(COMP_SENSOR, numSensorStats))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
//not interested in this value
|
|
*ppData = NULL;
|
|
return true;
|
|
}
|
|
|
|
/* Load the Repair stats */
|
|
static bool bufferSREPAIRLoad(const char *fileName, void **ppData)
|
|
{
|
|
if (!loadRepairStats(fileName) || !allocComponentList(COMP_REPAIRUNIT, numRepairStats))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
//not interested in this value
|
|
*ppData = NULL;
|
|
return true;
|
|
}
|
|
|
|
/* Load the Brain stats */
|
|
static bool bufferSBRAINLoad(const char *fileName, void **ppData)
|
|
{
|
|
if (!loadBrainStats(fileName) || !allocComponentList(COMP_BRAIN, numBrainStats))
|
|
{
|
|
return false;
|
|
}
|
|
//not interested in this value
|
|
*ppData = NULL;
|
|
return true;
|
|
}
|
|
|
|
/* Load the PropulsionType stats */
|
|
static bool bufferSPROPTYPESLoad(const char *fileName, void **ppData)
|
|
{
|
|
if (!loadPropulsionTypes(fileName))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
|
|
//not interested in this value
|
|
*ppData = NULL;
|
|
return true;
|
|
}
|
|
|
|
/* Load the propulsion type sound stats */
|
|
static bool bufferSPROPSNDLoad(const char *fileName, void **ppData)
|
|
{
|
|
if (!loadPropulsionSounds(fileName))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
//not interested in this value
|
|
*ppData = NULL;
|
|
return true;
|
|
}
|
|
|
|
/* Load the STERRTABLE stats */
|
|
static bool bufferSTERRTABLELoad(const char *fileName, void **ppData)
|
|
{
|
|
if (!loadTerrainTable(fileName))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
//not interested in this value
|
|
*ppData = NULL;
|
|
return true;
|
|
}
|
|
|
|
/* Load the body/propulsion IMDs stats */
|
|
static bool bufferSBPIMDLoad(const char *fileName, void **ppData)
|
|
{
|
|
if (!loadBodyPropulsionIMDs(fileName))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
//not interested in this value
|
|
*ppData = NULL;
|
|
return true;
|
|
}
|
|
|
|
/* Load the Weapon Effect modifier stats */
|
|
static bool bufferSWEAPMODLoad(const char *fileName, void **ppData)
|
|
{
|
|
if (!loadWeaponModifiers(fileName))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
//not interested in this value
|
|
*ppData = NULL;
|
|
return true;
|
|
}
|
|
|
|
|
|
/* Load the Template stats */
|
|
static bool bufferSTEMPLLoad(const char *fileName, void **ppData)
|
|
{
|
|
if (!loadDroidTemplates(fileName))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// set a dummy value so the release function gets called
|
|
*ppData = (void *)1;
|
|
return true;
|
|
}
|
|
|
|
// release the templates
|
|
static void dataSTEMPLRelease(WZ_DECL_UNUSED void *pData)
|
|
{
|
|
//free the storage allocated to the droid templates
|
|
droidTemplateShutDown();
|
|
}
|
|
|
|
/* Load the Structure stats */
|
|
static bool bufferSSTRUCTLoad(const char *fileName, void **ppData)
|
|
{
|
|
if (!loadStructureStats(QString(fileName)))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (!allocStructLists())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// set a dummy value so the release function gets called
|
|
*ppData = (void *)1;
|
|
return true;
|
|
}
|
|
|
|
// release the structure stats
|
|
static void dataSSTRUCTRelease(WZ_DECL_UNUSED void *pData)
|
|
{
|
|
freeStructureLists();
|
|
structureStatsShutDown();
|
|
}
|
|
|
|
/* Load the Structure strength modifier stats */
|
|
static bool bufferSSTRMODLoad(const char *fileName, void **ppData)
|
|
{
|
|
if (!loadStructureStrengthModifiers(fileName))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
//not interested in this value
|
|
*ppData = NULL;
|
|
return true;
|
|
}
|
|
|
|
/* Load the Feature stats */
|
|
static bool bufferSFEATLoad(const char *fileName, void **ppData)
|
|
{
|
|
if (!loadFeatureStats(fileName))
|
|
{
|
|
return false;
|
|
}
|
|
// set a dummy value so the release function gets called
|
|
*ppData = (void *)1;
|
|
return true;
|
|
}
|
|
|
|
// free the feature stats
|
|
static void dataSFEATRelease(WZ_DECL_UNUSED void *pData)
|
|
{
|
|
featureStatsShutDown();
|
|
}
|
|
|
|
// release the research stats
|
|
static void dataRESCHRelease(WZ_DECL_UNUSED void *pData)
|
|
{
|
|
//free the storage allocated to the stats
|
|
ResearchShutDown();
|
|
}
|
|
|
|
/* Load the Research stats */
|
|
static bool bufferRESCHLoad(const char *fileName, void **ppData)
|
|
{
|
|
//calcDataHash((uint8_t *)pBuffer, size, DATA_RESCH);
|
|
|
|
//check to see if already loaded
|
|
if (!asResearch.empty())
|
|
{
|
|
//release previous data before loading in the new
|
|
dataRESCHRelease(NULL);
|
|
}
|
|
|
|
if(!loadResearch(QString(fileName)))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/* Load the message viewdata */
|
|
static bool bufferSMSGLoad(const char *pBuffer, UDWORD size, void **ppData)
|
|
{
|
|
const char *ptr;
|
|
|
|
ptr = loadViewData(pBuffer, size);
|
|
if (!ptr)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// set the pointer so the release function gets called with it
|
|
*ppData = (void *)ptr;
|
|
return true;
|
|
}
|
|
|
|
/* Load research message viewdata */
|
|
static bool dataResearchMsgLoad(const char* fileName, void** ppData)
|
|
{
|
|
const char *ptr = loadResearchViewData(fileName);
|
|
if (!ptr)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// set the pointer so the release function gets called with it
|
|
*ppData = (void *)ptr;
|
|
return true;
|
|
}
|
|
|
|
// release the message viewdata
|
|
static void dataSMSGRelease(void *pData)
|
|
{
|
|
viewDataShutDown((const char *)pData);
|
|
}
|
|
|
|
/*!
|
|
* Load an image from file
|
|
*/
|
|
static bool dataImageLoad(const char *fileName, void **ppData)
|
|
{
|
|
iV_Image *psSprite = (iV_Image *)malloc(sizeof(iV_Image));
|
|
if (!psSprite)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (!iV_loadImage_PNG(fileName, psSprite))
|
|
{
|
|
debug( LOG_ERROR, "IMGPAGE load failed" );
|
|
free(psSprite);
|
|
return false;
|
|
}
|
|
|
|
*ppData = psSprite;
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
// Tertiles (terrain tiles) loader.
|
|
static bool dataTERTILESLoad(const char *fileName, void **ppData)
|
|
{
|
|
bool status;
|
|
|
|
status = texLoad(fileName);
|
|
ASSERT_OR_RETURN(false, status, "Error loading tertiles!");
|
|
debug(LOG_TEXTURE, "HW Tiles loaded");
|
|
|
|
*ppData = NULL; // don't bother calling cleanup
|
|
|
|
return true;
|
|
}
|
|
|
|
static bool dataIMGLoad(const char *fileName, void **ppData)
|
|
{
|
|
*ppData = iV_LoadImageFile(fileName);
|
|
if(*ppData == NULL)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
static void dataIMGRelease(void *pData)
|
|
{
|
|
iV_FreeImageFile((IMAGEFILE*)pData);
|
|
}
|
|
|
|
/*!
|
|
* Release an Image
|
|
*/
|
|
static void dataImageRelease(void *pData)
|
|
{
|
|
iV_Image *psSprite = (iV_Image*) pData;
|
|
|
|
if( psSprite )
|
|
{
|
|
free(psSprite);
|
|
}
|
|
}
|
|
|
|
|
|
/* Load an audio file */
|
|
static bool dataAudioLoad(const char* fileName, void **ppData)
|
|
{
|
|
if ( audio_Disabled() == true )
|
|
{
|
|
*ppData = NULL;
|
|
// No error occurred (sound is just disabled), so we return true
|
|
return true;
|
|
}
|
|
|
|
// Load the track from a file
|
|
*ppData = sound_LoadTrackFromFile( fileName );
|
|
|
|
return *ppData != NULL;
|
|
}
|
|
|
|
/* Load an audio file */
|
|
static bool dataAudioCfgLoad(const char* fileName, void **ppData)
|
|
{
|
|
bool success;
|
|
PHYSFS_file* fileHandle;
|
|
|
|
*ppData = NULL;
|
|
|
|
if (audio_Disabled())
|
|
{
|
|
return true;
|
|
}
|
|
debug(LOG_WZ, "Reading...[directory: %s] %s", PHYSFS_getRealDir(fileName), fileName);
|
|
fileHandle = PHYSFS_openRead(fileName);
|
|
|
|
if (fileHandle == NULL)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
success = ParseResourceFile(fileHandle);
|
|
|
|
PHYSFS_close(fileHandle);
|
|
|
|
return success;
|
|
}
|
|
|
|
/* Load an anim file */
|
|
static bool dataAnimLoad(const char *fileName, void **ppData)
|
|
{
|
|
PHYSFS_file* fileHandle = PHYSFS_openRead(fileName);
|
|
debug(LOG_WZ, "Reading...[directory: %s] %s", PHYSFS_getRealDir(fileName), fileName);
|
|
if (fileHandle == NULL)
|
|
{
|
|
*ppData = NULL;
|
|
return false;
|
|
}
|
|
|
|
*ppData = anim_LoadFromFile(fileHandle);
|
|
|
|
PHYSFS_close(fileHandle);
|
|
|
|
return *ppData != NULL;
|
|
}
|
|
|
|
/* Load an audio config file */
|
|
static bool dataAnimCfgLoad(const char *fileName, void **ppData)
|
|
{
|
|
bool success;
|
|
PHYSFS_file* fileHandle = PHYSFS_openRead(fileName);
|
|
*ppData = NULL;
|
|
|
|
debug(LOG_WZ, "Reading...[directory: %s] %s", PHYSFS_getRealDir(fileName), fileName);
|
|
if (fileHandle == NULL)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
success = ParseResourceFile(fileHandle);
|
|
|
|
PHYSFS_close(fileHandle);
|
|
|
|
return success;
|
|
}
|
|
|
|
|
|
static void dataAnimRelease( void *pData )
|
|
{
|
|
anim_ReleaseAnim((BASEANIM*)pData);
|
|
}
|
|
|
|
/* Load a string resource file */
|
|
static bool dataStrResLoad(const char* fileName, void** ppData)
|
|
{
|
|
// recreate the string resource if it was freed by a WRF release
|
|
if (psStringRes == NULL)
|
|
{
|
|
if (!stringsInitialise())
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if (!strresLoad(psStringRes, fileName))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
*ppData = psStringRes;
|
|
return true;
|
|
}
|
|
|
|
static void dataStrResRelease(WZ_DECL_UNUSED void *pData)
|
|
{
|
|
if (psStringRes != NULL)
|
|
{
|
|
strresDestroy(psStringRes);
|
|
psStringRes = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
/* Load a script file */
|
|
// All scripts, binary or otherwise are now passed through this routine
|
|
static bool dataScriptLoad(const char* fileName, void **ppData)
|
|
{
|
|
static const bool printHack = false;
|
|
SCRIPT_CODE** psProg = (SCRIPT_CODE**)ppData;
|
|
PHYSFS_file* fileHandle;
|
|
uint8_t *pBuffer;
|
|
PHYSFS_sint64 fileSize = 0;
|
|
|
|
debug(LOG_WZ, "COMPILING SCRIPT ...%s", GetLastResourceFilename());
|
|
|
|
fileHandle = PHYSFS_openRead(fileName);
|
|
debug(LOG_WZ, "Reading...[directory: %s] %s", PHYSFS_getRealDir(fileName), fileName);
|
|
if (fileHandle == NULL)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// due to the changes in r2531 we must do this routine a bit different.
|
|
fileSize = PHYSFS_fileLength(fileHandle);
|
|
|
|
pBuffer = (uint8_t *)malloc(fileSize * sizeof(uint8_t));
|
|
ASSERT_OR_RETURN(false, pBuffer, "Out of memory");
|
|
|
|
PHYSFS_read(fileHandle, pBuffer, 1, fileSize);
|
|
|
|
calcDataHash(pBuffer, fileSize, DATA_SCRIPT);
|
|
|
|
free(pBuffer);
|
|
|
|
PHYSFS_seek(fileHandle, 0); //reset position
|
|
|
|
*psProg = scriptCompile(fileHandle, SCRIPTTYPE);
|
|
|
|
PHYSFS_close(fileHandle);
|
|
|
|
if (!*psProg) // see script.h
|
|
{
|
|
debug(LOG_ERROR, "Script %s did not compile", GetLastResourceFilename());
|
|
return false;
|
|
}
|
|
|
|
if (printHack)
|
|
{
|
|
cpPrintProgram(*psProg);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
static void dataScriptRelease(void *pData)
|
|
{
|
|
SCRIPT_CODE *psCode = (SCRIPT_CODE *)pData;
|
|
scriptFreeCode(psCode);
|
|
}
|
|
|
|
static bool jsLoad(const char *fileName, void **ppData)
|
|
{
|
|
debug(LOG_WZ, "jsload: %s", fileName);
|
|
*ppData = NULL;
|
|
return loadGlobalScript(fileName);
|
|
}
|
|
|
|
// Load a script variable values file
|
|
static bool dataScriptLoadVals(const char* fileName, void **ppData)
|
|
{
|
|
bool success;
|
|
PHYSFS_file* fileHandle;
|
|
uint8_t *pBuffer;
|
|
PHYSFS_sint64 fileSize = 0;
|
|
|
|
*ppData = NULL;
|
|
|
|
// don't load anything if a saved game is being loaded
|
|
if (saveFlag)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
debug(LOG_WZ, "Loading script data %s", GetLastResourceFilename());
|
|
|
|
fileHandle = PHYSFS_openRead(fileName);
|
|
debug(LOG_WZ, "Reading...[directory: %s] %s", PHYSFS_getRealDir(fileName), fileName);
|
|
if (fileHandle == NULL)
|
|
{
|
|
return false;
|
|
}
|
|
// due to the changes in r2532 we must do this routine a bit different.
|
|
fileSize = PHYSFS_fileLength(fileHandle);
|
|
|
|
pBuffer = (uint8_t *)malloc(fileSize * sizeof(uint8_t));
|
|
ASSERT_OR_RETURN(false, pBuffer, "Out of memory");
|
|
|
|
PHYSFS_read(fileHandle, pBuffer, 1, fileSize);
|
|
|
|
calcDataHash(pBuffer, fileSize, DATA_SCRIPTVAL);
|
|
|
|
free(pBuffer);
|
|
|
|
PHYSFS_seek(fileHandle, 0); //reset position
|
|
|
|
success = scrvLoad(fileHandle);
|
|
|
|
if (!success)
|
|
debug(LOG_FATAL, "Script %s did not compile", GetLastResourceFilename());
|
|
|
|
PHYSFS_close(fileHandle);
|
|
|
|
return success;
|
|
}
|
|
|
|
// New reduced resource type ... specially for PSX
|
|
// These are statically defined in data.c
|
|
// this is also defined in frameresource.c - needs moving to a .h file
|
|
// This basically matches the argument list of resAddBufferLoad in frameresource.c
|
|
struct RES_TYPE_MIN_BUF
|
|
{
|
|
const char *aType; ///< points to the string defining the type (e.g. SCRIPT) - NULL indicates end of list
|
|
RES_BUFFERLOAD buffLoad; ///< routine to process the data for this type
|
|
RES_FREE release; ///< routine to release the data (NULL indicates none)
|
|
};
|
|
|
|
static const RES_TYPE_MIN_BUF BufferResourceTypes[] =
|
|
{
|
|
{"SMSG", bufferSMSGLoad, dataSMSGRelease},
|
|
{"IMD", NULL, NULL}, // ignored
|
|
};
|
|
|
|
struct RES_TYPE_MIN_FILE
|
|
{
|
|
const char *aType; ///< points to the string defining the type (e.g. SCRIPT) - NULL indicates end of list
|
|
RES_FILELOAD fileLoad; ///< routine to process the data for this type
|
|
RES_FREE release; ///< routine to release the data (NULL indicates none)
|
|
};
|
|
|
|
static const RES_TYPE_MIN_FILE FileResourceTypes[] =
|
|
{
|
|
{"SFEAT", bufferSFEATLoad, dataSFEATRelease}, //feature stats file
|
|
{"STEMPL", bufferSTEMPLLoad, dataSTEMPLRelease}, //template and associated files
|
|
{"WAV", dataAudioLoad, (RES_FREE)sound_ReleaseTrack},
|
|
{"SWEAPON", bufferSWEAPONLoad, dataReleaseStats},
|
|
{"SBPIMD", bufferSBPIMDLoad, dataReleaseStats},
|
|
{"SBRAIN", bufferSBRAINLoad, dataReleaseStats},
|
|
{"SSENSOR", bufferSSENSORLoad, dataReleaseStats},
|
|
{"SECM", bufferSECMLoad, dataReleaseStats},
|
|
{"SREPAIR", bufferSREPAIRLoad, dataReleaseStats},
|
|
{"SCONSTR", bufferSCONSTRLoad, dataReleaseStats},
|
|
{"SPROP", bufferSPROPLoad, dataReleaseStats},
|
|
{"SPROPTYPES", bufferSPROPTYPESLoad, dataReleaseStats},
|
|
{"STERRTABLE", bufferSTERRTABLELoad, dataReleaseStats},
|
|
{"SBODY", bufferSBODYLoad, dataReleaseStats},
|
|
{"SWEAPMOD", bufferSWEAPMODLoad, dataReleaseStats},
|
|
{"SPROPSND", bufferSPROPSNDLoad, dataReleaseStats},
|
|
{"AUDIOCFG", dataAudioCfgLoad, NULL},
|
|
{"ANI", dataAnimLoad, dataAnimRelease},
|
|
{"ANIMCFG", dataAnimCfgLoad, NULL},
|
|
{"IMGPAGE", dataImageLoad, dataImageRelease},
|
|
{"TERTILES", dataTERTILESLoad, NULL},
|
|
{"IMG", dataIMGLoad, dataIMGRelease},
|
|
{"TEXPAGE", NULL, NULL}, // ignored
|
|
{"TCMASK", NULL, NULL}, // ignored
|
|
{"SCRIPT", dataScriptLoad, dataScriptRelease},
|
|
{"SCRIPTVAL", dataScriptLoadVals, NULL},
|
|
{"STR_RES", dataStrResLoad, dataStrResRelease},
|
|
{"RESEARCHMSG", dataResearchMsgLoad, dataSMSGRelease },
|
|
{"SSTRMOD", bufferSSTRMODLoad, NULL},
|
|
{"JAVASCRIPT", jsLoad, NULL},
|
|
{"SSTRUCT", bufferSSTRUCTLoad, dataSSTRUCTRelease}, //structure stats and associated files
|
|
{"RESCH", bufferRESCHLoad, dataRESCHRelease}, //research stats files
|
|
};
|
|
|
|
/* Pass all the data loading functions to the framework library */
|
|
bool dataInitLoadFuncs(void)
|
|
{
|
|
// init the data integrity hash;
|
|
resetDataHash();
|
|
// Using iterator style: begin iterator (ResourceTypes),
|
|
// end iterator (EndType), and current iterator (CurrentType)
|
|
|
|
// iterate through buffer load functions
|
|
{
|
|
const RES_TYPE_MIN_BUF *CurrentType;
|
|
// Points just past the last item in the list
|
|
const RES_TYPE_MIN_BUF * const EndType = &BufferResourceTypes[sizeof(BufferResourceTypes) / sizeof(RES_TYPE_MIN_BUF)];
|
|
|
|
for (CurrentType = BufferResourceTypes; CurrentType != EndType; ++CurrentType)
|
|
{
|
|
if(!resAddBufferLoad(CurrentType->aType, CurrentType->buffLoad, CurrentType->release))
|
|
{
|
|
return false; // error whilst adding a buffer load
|
|
}
|
|
}
|
|
}
|
|
|
|
// iterate through file load functions
|
|
{
|
|
const RES_TYPE_MIN_FILE *CurrentType;
|
|
// Points just past the last item in the list
|
|
const RES_TYPE_MIN_FILE * const EndType = &FileResourceTypes[sizeof(FileResourceTypes) / sizeof(RES_TYPE_MIN_BUF)];
|
|
|
|
for (CurrentType = FileResourceTypes; CurrentType != EndType; ++CurrentType)
|
|
{
|
|
if(!resAddFileLoad(CurrentType->aType, CurrentType->fileLoad, CurrentType->release))
|
|
{
|
|
return false; // error whilst adding a file load
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|