/*=========================================================================== * * DFBlocks.CPP - Dave Humphrey (uesp@m0use.net), 14 November 2000 * *=========================================================================*/ /* Undefine to remove all statistics from file */ //#define DOSTATS /* Include Files */ #include "dfblocks.h" #include "dfcommon.h" DEF_STAT_REC(RMBNumRecords1) DEF_STAT_REC(RMBNumRecords2) DEF_STAT_REC(RMBNumRecords3) DEF_STAT_REC(RMBNumSec1Rec) DEF_STAT_REC(RMBNumSec2Rec) DEF_STAT_REC(RMBNumSec3Rec) DEF_STAT_REC(RMBNumSec4Rec) DEF_STAT_REC(RMBNumSec5Rec) DEF_STAT_ARR(RMBHeaderUnknowns, 6) DEF_STAT_VAR(RMBSec1U1) DEF_STAT_VAR(RMBSec1U2) DEF_STAT_VAR(RMBSec1U3) DEF_STAT_VAR(RMBSec1U4) DEF_STAT_VAR(RMBSec1U5) DEF_STAT_VAR(RMBSec1U6) DEF_STAT_VAR(RMBSec1U7) DEF_STAT_VAR(RMBSec1U8) DEF_STAT_VAR(RMBSec1X1) DEF_STAT_VAR(RMBSec1Y1) DEF_STAT_VAR(RMBSec1Z1) DEF_STAT_VAR(RMBSec1X2) DEF_STAT_VAR(RMBSec1Y2) DEF_STAT_VAR(RMBSec1Z2) DEF_STAT_VAR(RMBSec2U1) DEF_STAT_VAR(RMBSec2U2) DEF_STAT_VAR(RMBSec2U3) DEF_STAT_VAR(RMBSec3U1) DEF_STAT_VAR(RMBSec3U2) DEF_STAT_VAR(RMBSec3U3) DEF_STAT_VAR(RMBSec4U1) DEF_STAT_VAR(RMBSec4U2) DEF_STAT_VAR(RMBSec4U3) DEF_STAT_VAR(RMBSec5U1) DEF_STAT_VAR(RMBSec5U2) DEF_STAT_VAR(RMBSec5U3) DEF_STAT_VAR(RMBSec5U4) #undef __FUNC__ #define __FUNC__ "CDFRMBRecord::CDFRMBRecord()" /*=========================================================================== * * Class CDFRMBRecord Constructor * *=========================================================================*/ CDFRMBRecord::CDFRMBRecord() { /* Initialize array pointers */ p3DObjectRecords = NULL; pFlatObjectRecords = NULL; pSection3Records = NULL; pPeopleRecords = NULL; pDoorRecords = NULL; ExtraByte = 0; HasExtraByte = FALSE; /* Initialize header data */ memset(&Header, 0, sizeof(dfblk_rmb_header_t)); } /*=========================================================================== * End of Class CDFRMBRecord Constructor *=========================================================================*/ #undef __FUNC__ #define __FUNC__ "CDFRMBRecord::Destroy()" /*=========================================================================== * * Class CDFRMBRecord Destructor * *=========================================================================*/ void CDFRMBRecord::Destroy (void) { /* Unallocate memory */ DestroyPointerArray(p3DObjectRecords); DestroyPointerArray(pFlatObjectRecords); DestroyPointerArray(pSection3Records); DestroyPointerArray(pPeopleRecords); DestroyPointerArray(pDoorRecords); ExtraByte = 0; HasExtraByte = FALSE; /* Clear header data */ memset(&Header, 0, sizeof(dfblk_rmb_header_t)); } /*=========================================================================== * End of Class CDFRMBRecord Destructor *=========================================================================*/ #undef __FUNC__ #define __FUNC__ "CDFRMBRecord::Read()" /*=========================================================================== * * Class CDFRMBRecord Method - boolean Read (pFileHandle); * * Attempts to read the record from the current position in the file stream. * Returns FALSE on any error. * *=========================================================================*/ boolean CDFRMBRecord::Read (FILE* pFileHandle) { boolean Result; /* Ensure valid input */ if (pFileHandle == NULL) { SET_EXT_ERROR2(ERR_NULL, "Received invalid NULL file handle!"); return (FALSE); } /* Attempt to read in all the record data */ Result = ReadHeader(pFileHandle); if (Result) Result = Read3DObjects (pFileHandle); if (Result) Result = ReadFlatObjects (pFileHandle); if (Result) Result = ReadSection3 (pFileHandle); if (Result) Result = ReadPeople (pFileHandle); if (Result) Result = ReadDoors (pFileHandle); return (Result); } /*=========================================================================== * End of Class Method CDFRMBRecord::Read() *=========================================================================*/ #undef __FUNC__ #define __FUNC__ "CDFRMBRecord::ReadHeader()" /*=========================================================================== * * Class CDFRMBRecord Method - boolean ReadHeader (pFileHandle); * * Attempts to read the record header from the current position in the * file stream. Returns FALSE on any error. Protected class method. * *=========================================================================*/ boolean CDFRMBRecord::ReadHeader (FILE* pFileHandle) { int Result; /* Attempt to read the header all at once */ Result = fread (&Header, 1, sizeof(dfblk_rmb_header_t), pFileHandle); if (Result != sizeof(dfblk_rmb_header_t)) { SET_EXT_ERROR2(ERR_READ, "Failed to read RMB header from file!"); return (FALSE); } /* Do optional statistics on success */ DO_STAT_REC2(RMBNumSec1Rec, Header.Num3DObjectRecords); DO_STAT_REC2(RMBNumSec2Rec, Header.NumFlatObjectRecords); DO_STAT_REC2(RMBNumSec3Rec, Header.NumSection3Records); DO_STAT_REC2(RMBNumSec4Rec, Header.NumPeopleRecords); DO_STAT_REC2(RMBNumSec5Rec, Header.NumDoorRecords); DO_STAT_ARR(RMBHeaderUnknowns, Header.Unknowns, 6) return (TRUE); } /*=========================================================================== * End of Class Method CDFRMBRecord::ReadHeader() *=========================================================================*/ #undef __FUNC__ #define __FUNC__ "CDFRMBRecord::Read3DObjects()" /*=========================================================================== * * Class CDFRMBRecord Method - boolean Read3DObjects (pFileHandle); * * Attempts to read the record 3D Object data from the current position in the * file stream. Returns FALSE on any error. Protected class method. * *=========================================================================*/ boolean CDFRMBRecord::Read3DObjects (FILE* pFileHandle) { int Result; /* Ignore if nothing to do */ if (Header.Num3DObjectRecords == 0) return (TRUE); /* Allocate pointer array */ CreatePointerArray(p3DObjectRecords, dfblk_rmb_3dobject_t, Header.Num3DObjectRecords); /* Attempt to read the data all at once */ Result = fread (p3DObjectRecords, sizeof(dfblk_rmb_3dobject_t), Header.Num3DObjectRecords, pFileHandle); if (Result != Header.Num3DObjectRecords) { SET_EXT_ERROR2(ERR_READ, "Failed to read RMB 3D Object Data from file!"); return (FALSE); } /* Do optional statistics on success */ #ifdef DOSTATS int LoopCounter; for (LoopCounter = 0; LoopCounter < Header.Num3DObjectRecords; LoopCounter++) { DO_STAT_VAR(RMBSec1U1, p3DObjectRecords[LoopCounter].Unknown1) DO_STAT_VAR(RMBSec1U2, p3DObjectRecords[LoopCounter].Unknown2) DO_STAT_VAR(RMBSec1U3, p3DObjectRecords[LoopCounter].Unknown3) DO_STAT_VAR(RMBSec1U4, p3DObjectRecords[LoopCounter].Unknown4) DO_STAT_VAR(RMBSec1U5, p3DObjectRecords[LoopCounter].Unknown5) DO_STAT_VAR(RMBSec1U6, p3DObjectRecords[LoopCounter].Unknown6) DO_STAT_VAR(RMBSec1U7, p3DObjectRecords[LoopCounter].Unknown7) DO_STAT_VAR(RMBSec1U8, p3DObjectRecords[LoopCounter].Unknown8) DO_STAT_VAR(RMBSec1X1, p3DObjectRecords[LoopCounter].XPos1) DO_STAT_VAR(RMBSec1Y1, p3DObjectRecords[LoopCounter].YPos1) DO_STAT_VAR(RMBSec1Z1, p3DObjectRecords[LoopCounter].ZPos1) DO_STAT_VAR(RMBSec1X2, p3DObjectRecords[LoopCounter].XPos2) DO_STAT_VAR(RMBSec1Y2, p3DObjectRecords[LoopCounter].YPos2) DO_STAT_VAR(RMBSec1Z2, p3DObjectRecords[LoopCounter].ZPos2) // if (pSection1Records[LoopCounter].Unknown8 != 0) // SystemLog.Printf ("Sec1YU8: 0x%08lX", pSection1Records[LoopCounter].Unknown8); } #endif return (TRUE); } /*=========================================================================== * End of Class Method CDFRMBRecord::Read3DObjects() *=========================================================================*/ #undef __FUNC__ #define __FUNC__ "CDFRMBRecord::ReadFlatObjects()" /*=========================================================================== * * Class CDFRMBRecord Method - boolean ReadFlatObjects (pFileHandle); * * Attempts to read the record section2 data from the current position in the * file stream. Returns FALSE on any error. Protected class method. * *=========================================================================*/ boolean CDFRMBRecord::ReadFlatObjects (FILE* pFileHandle) { int Result; /* Ignore if nothing to do */ if (Header.NumFlatObjectRecords == 0) return (TRUE); /* Allocate pointer array */ CreatePointerArray(pFlatObjectRecords, dfblk_rmb_flatobject_t, Header.NumFlatObjectRecords); /* Attempt to read the data all at once */ Result = fread (pFlatObjectRecords, sizeof(dfblk_rmb_flatobject_t), Header.NumFlatObjectRecords, pFileHandle); if (Result != Header.NumFlatObjectRecords) { SET_EXT_ERROR2(ERR_READ, "Failed to read RMB Flat Object Data from file!"); return (FALSE); } /* Do optional statistics on success */ #ifdef DOSTATS int LoopCounter; for (LoopCounter = 0; LoopCounter < Header.NumFlatObjectRecords; LoopCounter++) { DO_STAT_VAR(RMBSec2U1, pFlatObjectRecords[LoopCounter].Unknown1) DO_STAT_VAR(RMBSec2U2, pFlatObjectRecords[LoopCounter].Unknown2) DO_STAT_VAR(RMBSec2U3, pFlatObjectRecords[LoopCounter].Unknown3) } #endif return (TRUE); } /*=========================================================================== * End of Class Method CDFRMBRecord::ReadFlatObjects() *=========================================================================*/ #undef __FUNC__ #define __FUNC__ "CDFRMBRecord::ReadSection2()" /*=========================================================================== * * Class CDFRMBRecord Method - boolean ReadSection3 (pFileHandle); * * Attempts to read the record section3 data from the current position in the * file stream. Returns FALSE on any error. Protected class method. * *=========================================================================*/ boolean CDFRMBRecord::ReadSection3 (FILE* pFileHandle) { int Result; /* Ignore if nothing to do */ if (Header.NumSection3Records == 0) return (TRUE); /* Allocate pointer array */ CreatePointerArray(pSection3Records, dfblk_rmb_section3_t, Header.NumSection3Records); /* Attempt to read the data all at once */ Result = fread (pSection3Records, sizeof(dfblk_rmb_section3_t), Header.NumSection3Records, pFileHandle); if (Result != Header.NumSection3Records) { SET_EXT_ERROR2(ERR_READ, "Failed to read RMB Section3 Data from file!"); return (FALSE); } /* Do optional statistics on success */ #ifdef DOSTATS int LoopCounter; for (LoopCounter = 0; LoopCounter < Header.NumSection3Records; LoopCounter++) { DO_STAT_VAR(RMBSec3U1, pSection3Records[LoopCounter].Unknown1) DO_STAT_VAR(RMBSec3U2, pSection3Records[LoopCounter].Unknown2) DO_STAT_VAR(RMBSec3U3, pSection3Records[LoopCounter].Unknown3) if (pSection3Records[LoopCounter].Unknown1 != 0) { SystemLog.Printf ("\tSec3U1: 0x%02X", pSection3Records[LoopCounter].Unknown1); } if (pSection3Records[LoopCounter].Unknown3 != 0) { SystemLog.Printf ("\tSec3U3: \t\t0x%02X", pSection3Records[LoopCounter].Unknown3); } } #endif return (TRUE); } /*=========================================================================== * End of Class Method CDFRMBRecord::ReadSection3() *=========================================================================*/ #undef __FUNC__ #define __FUNC__ "CDFRMBRecord::ReadPeople()" /*=========================================================================== * * Class CDFRMBRecord Method - boolean ReadPeople (pFileHandle); * * Attempts to read the record section4 data from the current position in the * file stream. Returns FALSE on any error. Protected class method. * *=========================================================================*/ boolean CDFRMBRecord::ReadPeople (FILE* pFileHandle) { int Result; /* Ignore if nothing to do */ if (Header.NumPeopleRecords == 0) return (TRUE); /* Allocate pointer array */ CreatePointerArray(pPeopleRecords, dfblk_rmb_people_t, Header.NumPeopleRecords); /* Attempt to read the data all at once */ Result = fread (pPeopleRecords, sizeof(dfblk_rmb_people_t), Header.NumPeopleRecords, pFileHandle); if (Result != Header.NumPeopleRecords) { SET_EXT_ERROR2(ERR_READ, "Failed to read RMB People Data from file!"); return (FALSE); } /* Do optional statistics on success */ #ifdef DOSTATS int LoopCounter; for (LoopCounter = 0; LoopCounter < Header.NumPeopleRecords; LoopCounter++) { DO_STAT_VAR(RMBSec4U1, pPeopleRecords[LoopCounter].Unknown1) DO_STAT_VAR(RMBSec4U2, pPeopleRecords[LoopCounter].Unknown2) DO_STAT_VAR(RMBSec4U3, pPeopleRecords[LoopCounter].Unknown3) } #endif return (TRUE); } /*=========================================================================== * End of Class Method CDFRMBRecord::ReadPeople() *=========================================================================*/ #undef __FUNC__ #define __FUNC__ "CDFRMBRecord::ReadDoors()" /*=========================================================================== * * Class CDFRMBRecord Method - boolean ReadDoors (pFileHandle); * * Attempts to read the record Door data from the current position in the * file stream. Returns FALSE on any error. Protected class method. * *=========================================================================*/ boolean CDFRMBRecord::ReadDoors (FILE* pFileHandle) { int Result; /* Ignore if nothing to do */ if (Header.NumDoorRecords == 0) return (TRUE); /* Allocate pointer array */ CreatePointerArray(pDoorRecords, dfblk_rmb_door_t, Header.NumDoorRecords); /* Attempt to read the data all at once */ Result = fread (pDoorRecords, sizeof(dfblk_rmb_door_t), Header.NumDoorRecords, pFileHandle); if (Result != Header.NumDoorRecords) { SET_EXT_ERROR2(ERR_READ, "Failed to read RMB Door Data from file!"); return (FALSE); } /* Do optional statistics on success */ #ifdef DOSTATS int LoopCounter; for (LoopCounter = 0; LoopCounter < Header.NumDoorRecords; LoopCounter++) { DO_STAT_VAR(RMBSec5U1, pDoorRecords[LoopCounter].Unknown1) DO_STAT_VAR(RMBSec5U2, pDoorRecords[LoopCounter].Unknown2) DO_STAT_VAR(RMBSec5U3, pDoorRecords[LoopCounter].Unknown3) DO_STAT_VAR(RMBSec5U4, pDoorRecords[LoopCounter].Unknown4) } #endif return (TRUE); } /*=========================================================================== * End of Class Method CDFRMBRecord::ReadDoors() *=========================================================================*/ #undef __FUNC__ #define __FUNC__ "CDFRMBFile::CDFRMBFile()" /*=========================================================================== * * Class CDFRMBFile Constructor * *=========================================================================*/ CDFRMBFile::CDFRMBFile() { /* Initialize array pointers */ pInsideRecords = NULL; pOutsideRecords = NULL; p3DObjects = NULL; pFlatObjects = NULL; RecordOffset = 0; RecordSize = 0; /* Initialize fixed length data */ memset(&FLDData, 0, sizeof(dfblk_rmbfld_t)); } /*=========================================================================== * End of Class CDFRMBFile Constructor *=========================================================================*/ #undef __FUNC__ #define __FUNC__ "CDFRMBFile::Destroy()" /*=========================================================================== * * Class CDFRMBFile Destructor * *=========================================================================*/ void CDFRMBFile::Destroy (void) { /* Unallocate memory */ DestroyPointerArray(pOutsideRecords); DestroyPointerArray(pInsideRecords); DestroyPointerArray(p3DObjects); DestroyPointerArray(pFlatObjects); RecordOffset = 0; RecordSize = 0; /* Initialize fixed length data */ memset(&FLDData, 0, sizeof(dfblk_rmbfld_t)); } /*=========================================================================== * End of Class CDFRMBFile Destructor *=========================================================================*/ #undef __FUNC__ #define __FUNC__ "CDFRMBFile::CreateBlockRecords()" /*=========================================================================== * * Class CDFRMBFile Method - void CreateBlockRecords (void); * * Allocates the block records. A virtual and protected class method. * *=========================================================================*/ void CDFRMBFile::CreateBlockRecords (void) { CreatePointerArray(pOutsideRecords, CDFRMBRecord, FLDData.NumBlocks); CreatePointerArray(pInsideRecords, CDFRMBRecord, FLDData.NumBlocks); } /*=========================================================================== * End of Class Method CDFRMBFile::CreateBlockRecords() *=========================================================================*/ #undef __FUNC__ #define __FUNC__ "CDFRMBFile::Read()" /*=========================================================================== * * Class CDFRMBFile Method - boolean Read (pFileHandle, RecordSize); * * Attempts to read the RMB file from the current position in the file stream. * Returns FALSE on any error. * *=========================================================================*/ boolean CDFRMBFile::Read (FILE* pFileHandle, const long Size) { boolean Result; /* Ensure valid input */ if (pFileHandle == NULL) { SET_EXT_ERROR2(ERR_NULL, "Received invalid NULL file handle!"); return (FALSE); } /* Delete any current information */ Destroy(); /* Save record information */ RecordOffset = ftell(pFileHandle); RecordSize = Size; /* Attempt to read in all the record data */ Result = ReadFLD(pFileHandle); if (Result) Result = ReadBlocks (pFileHandle); if (Result) Result = Read3DObjects (pFileHandle); if (Result) Result = ReadFlatObjects (pFileHandle); /* Do optional statistics */ #ifdef DOSTATS long RecSize; long FilePos; FilePos = ftell(pFileHandle); RecSize = FilePos - RecordOffset; if (RecSize != RecordSize) SystemLog.Printf ("Did not properly read RMB file, %ld byte error!", RecordSize - RecSize); DO_STAT_REC2(RMBNumRecords1, FLDData.NumSubRecords1); DO_STAT_REC2(RMBNumRecords2, FLDData.NumSubRecords2); DO_STAT_REC2(RMBNumRecords3, FLDData.NumSubRecords3); #endif return (Result); } /*=========================================================================== * End of Class Method CDFRMBFile::Read() *=========================================================================*/ #undef __FUNC__ #define __FUNC__ "CDFRMBFile::ReadFLD()" /*=========================================================================== * * Class CDFRMBFile Method - boolean ReadFLD (pFileHandle); * * Attempts to read the RMB file FLD data from the current position in the * file stream. Returns FALSE on any error. Protected class method. * *=========================================================================*/ boolean CDFRMBFile::ReadFLD (FILE* pFileHandle) { int Result; /* Read in FLD all at once */ Result = fread (&FLDData, 1, sizeof(dfblk_rmbfld_t), pFileHandle); if (Result != sizeof(dfblk_rmbfld_t)) { SET_EXT_ERROR2(ERR_READ, "Failed to read Fixed Length Data!"); return (FALSE); } return (TRUE); } /*=========================================================================== * End of Class Method CDFRMBFile::ReadFLD() *=========================================================================*/ #undef __FUNC__ #define __FUNC__ "CDFRMBFile::ReadBlocks()" /*=========================================================================== * * Class CDFRMBFile Method - boolean ReadRecords1 (pFileHandle); * * Attempts to read the RMB subrecord1 data from the current position in the * file stream. Returns FALSE on any error. Protected class method. * *=========================================================================*/ boolean CDFRMBFile::ReadBlocks (FILE* pFileHandle) { boolean Result; int LoopCounter; long RecOffset; long ExtraBytes; /* Initialize record arrays if required */ if (FLDData.NumBlocks == 0) return (TRUE); CreateBlockRecords(); /* Read all subrecords */ for (LoopCounter = 0; LoopCounter < FLDData.NumBlocks; LoopCounter++) { RecOffset = ftell(pFileHandle); /* Attempt to read in the first record set */ Result = pOutsideRecords[LoopCounter].Read(pFileHandle); if (!Result) return (FALSE); /* Attempt to read in the second record set */ Result = pInsideRecords[LoopCounter].Read(pFileHandle); if (!Result) return (FALSE); /* Compute amount of extra bytes remaining */ ExtraBytes = ftell(pFileHandle) - RecOffset - FLDData.BlockSizes[LoopCounter].RecordSize; /* Special case of 1 extra byte at end of record */ if (ExtraBytes == -1) pInsideRecords[LoopCounter].SetExtraByte(fgetc(pFileHandle)); else if (ExtraBytes != 0) SystemLog.Printf ("Failed to read correct record size, %d spare bytes!", LoopCounter, ExtraBytes); /* Jump to the proper record offset for the next data */ fseek (pFileHandle, RecOffset + FLDData.BlockSizes[LoopCounter].RecordSize, SEEK_SET); } return (TRUE); } /*=========================================================================== * End of Class Method CDFRMBFile::ReadBlocks() *=========================================================================*/ #undef __FUNC__ #define __FUNC__ "CDFRMBFile::Read3DObjects()" /*=========================================================================== * * Class CDFRMBFile Method - boolean Read3DObjects (pFileHandle); * * Attempts to read the RMB 3D Object data from the current position in the * file stream. Returns FALSE on any error. Protected class method. * *=========================================================================*/ boolean CDFRMBFile::Read3DObjects (FILE* pFileHandle) { boolean Result; /* Initialize record array if required */ if (FLDData.Num3DObjects == 0) return (TRUE); CreatePointerArray(p3DObjects, dfblk_rmb_3dobject_t, FLDData.Num3DObjects); /* Read all subrecords at once */ Result = fread (p3DObjects, sizeof(dfblk_rmb_3dobject_t), FLDData.Num3DObjects, pFileHandle); if (Result != FLDData.Num3DObjects) { SET_EXT_ERROR2(ERR_READ, "Failed to read 3D Object data from RMB file!"); return (FALSE); } return (TRUE); } /*=========================================================================== * End of Class Method CDFRMBFile::Read3DObjects() *=========================================================================*/ #undef __FUNC__ #define __FUNC__ "CDFRMBFile::ReadFlatObjects()" /*=========================================================================== * * Class CDFRMBFile Method - boolean ReadFlatObjects (pFileHandle); * * Attempts to read the RMB Flat Object data from the current position in the * file stream. Returns FALSE on any error. Protected class method. * *=========================================================================*/ boolean CDFRMBFile::ReadFlatObjects (FILE* pFileHandle) { boolean Result; /* Initialize record array if required */ if (FLDData.NumFlatObjects == 0) return (TRUE); CreatePointerArray(pFlatObjects, dfblk_rmb_flatobject_t, FLDData.NumFlatObjects); /* Read all subrecords at once */ Result = fread (pFlatObjects, sizeof(dfblk_rmb_flatobject_t), FLDData.NumFlatObjects, pFileHandle); if (Result != FLDData.NumFlatObjects) { SET_EXT_ERROR2(ERR_READ, "Failed to read flat object data from RMB file!"); return (FALSE); } return (TRUE); } /*=========================================================================== * End of Class Method CDFRMBFile::ReadRecords3() *=========================================================================*/ #undef __FUNC__ #define __FUNC__ "CDFBlocksFile::CDFBlocksFile()" /*=========================================================================== * * Class CDFBlocksFile Constructor * *=========================================================================*/ CDFBlocksFile::CDFBlocksFile() { int LoopCounter; /* Allocate records array */ CreatePointerArray(pRecords, CDFRMBFile*, DFBLK_MAX_RECORDS); /* Initialize array */ for (LoopCounter = 0; LoopCounter < DFBLK_MAX_RECORDS; LoopCounter++) pRecords[LoopCounter] = NULL; SetFilename("arena2\\blocks.bsa"); } /*=========================================================================== * End of Class CDFBlocksFile Constructor *=========================================================================*/ #undef __FUNC__ #define __FUNC__ "CDFBlocksFile::~CDFBlocksFile()" /*=========================================================================== * * Class CDFBlocksFile Destructor * *=========================================================================*/ CDFBlocksFile::~CDFBlocksFile() { Destroy(); /* Unallocate records array */ DestroyPointerArray(pRecords); } /*=========================================================================== * End of Class CDFBlocksFile Destructor *=========================================================================*/ #undef __FUNC__ #define __FUNC__ "CDFBlocksFile::Destroy()" /*=========================================================================== * * Class CDFBlocksFile Destructor * *=========================================================================*/ void CDFBlocksFile::Destroy (void) { int LoopCounter; /* Delete allocated records array */ for (LoopCounter = 0; LoopCounter < DFBLK_MAX_RECORDS; LoopCounter++) { DestroyPointer(pRecords[LoopCounter]); } /* Call base class method */ CDFBSAFile::Destroy(); } /*=========================================================================== * End of Class CDFBlocksFile Destructor *=========================================================================*/ #undef __FUNC__ #define __FUNC__ "CDFBlocksFile::CreateRMBFile()" /*=========================================================================== * * Class CDFBlocksFile Method - void CreateRMBFile (Index); * * Attempts to create a new RMBFile object in the given array index. Protected * class method. * *=========================================================================*/ void CDFBlocksFile::CreateRMBFile (const int Index) { /* Unallocate if already allocated */ DestroyPointer(pRecords[Index]); /* Create new pointer */ CreatePointer(pRecords[Index], CDFRMBFile); } /*=========================================================================== * End of Class Method CDFBlocksFile::CreateRMBFile() *=========================================================================*/ #undef __FUNC__ #define __FUNC__ "CDFBlocksFile::GetRMBFile()" /*=========================================================================== * * Class CDFBlocksFile Method - CDFRMBFile* GetRMBFile (pFilename); * * Attempts to retrieve the specified RMBFile as given by its filename. * Will attempt to load it if required. Returns NULL on any error. * *=========================================================================*/ CDFRMBFile* CDFBlocksFile::GetRMBFile (const char* pFilename) { CDFRMBFile* pFile; boolean HadToOpenFile = FALSE; int Index; /* Open file to read directory if required */ if (!DirectoryRead && !IsOpen()) { if (!Open()) return (NULL); HadToOpenFile = TRUE; } /* Attempt to find record index */ Index = FindRecordIndex(pFilename); /* Retrieve/load required record */ pFile = GetRMBFile(Index); if (HadToOpenFile) Close(); return (pFile); } /*=========================================================================== * End of Class Method CDFBlocksFile::GetRMBFile() *=========================================================================*/ #undef __FUNC__ #define __FUNC__ "CDFBlocksFile::GetRMBFile" /*=========================================================================== * * Class CDFBlocksFile Method - CDFRMBFile* GetRMBFile (Index); * * Attempts to retrieve the specified RMBFile as given by its record index. * Will attempt to load it if required. Returns NULL on any error. * *=========================================================================*/ CDFRMBFile* CDFBlocksFile::GetRMBFile (const int Index) { boolean Result; boolean HadToOpenFile = FALSE; /* Open file to read directory if required */ if (!DirectoryRead && !IsOpen()) { if (!Open()) return (NULL); HadToOpenFile = TRUE; } /* Check record index to ensure its valid */ if (!IsValidIndex(Index)) { SET_EXT_ERROR3(ERR_INDEX, "Invalid Blocks.BSA record index %d received!", Index); if (HadToOpenFile) Close(); return (NULL); } /* Does the object already exist? */ if (pRecords[Index] != NULL) { if (HadToOpenFile) Close(); return (pRecords[Index]); } /* Open file to read object if required */ if (!IsOpen()) { if (!Open()) return (NULL); HadToOpenFile = TRUE; } /* Attempt to load object */ Result = ReadRMB(Index); if (HadToOpenFile) Close(); if (!Result) { DestroyPointer(pRecords[Index]); return (NULL); } return (pRecords[Index]); } /*=========================================================================== * End of Class Method CDFBlocksFile::GetRMBFile() *=========================================================================*/ #undef __FUNC__ #define __FUNC__ "CDFBlocksFile::GetRMBFile()" /*=========================================================================== * * Class CDFBlocksFile Method - boolean GetRMBFile (FileIndex, CharIndex, Number); * * Attempts to input a RMBFile into the given array object as specified by * the input indices. Returns FALSE on any error. * *=========================================================================*/ CDFRMBFile* CDFBlocksFile::GetRMBFile (const int FileIndex, const int CharIndex, const int Number) { char Filename[15]; char FileChar[3]; int Index; /* Ensure valid input */ if (FileIndex < 0 || FileIndex >= DFBLK_MAX_FILEINDEX) { SET_EXT_ERROR3(ERR_INDEX, "Invalid file index %d received!", FileIndex); return (FALSE); } /* Ensure valid input */ if (Number < 0 || Number >= DFBLK_MAX_FILENUMBER) { SET_EXT_ERROR3(ERR_INDEX, "Invalid file number %d received!", Number); return (FALSE); } /* Fill in the file character string */ if (CharIndex < 0x0F) strcpy(FileChar, "AA"); else if (CharIndex <= 0x1F) strcpy(FileChar, "DA"); else if (CharIndex <= 0x2F) strcpy(FileChar, "AL"); else if (CharIndex <= 0x3F) strcpy(FileChar, "DL"); else if (CharIndex <= 0x4F) strcpy(FileChar, "AM"); else if (CharIndex <= 0x5F) strcpy(FileChar, "DM"); else if (CharIndex <= 0x6F) strcpy(FileChar, "AS"); else if (CharIndex <= 0x7F) strcpy(FileChar, "DS"); else if (CharIndex <= 0x8F) strcpy(FileChar, "AA"); else if (CharIndex <= 0x9F) strcpy(FileChar, "DA"); else { SET_EXT_ERROR3(ERR_INDEX, "Invalid file char %d received!", FileChar); return (FALSE); } SystemLog.Printf ("CDFBlocksFile::ReadRMB(%d, 0x%02X, %d)", FileIndex, CharIndex, Number); /* Create the filename */ sprintf (Filename, "%4s%2s%02d.rmb", GetDFRMBFilename(FileIndex), FileChar, Number); /* Find the record index of the specified file */ Index = FindRecordIndex(Filename); /* Ensure record is loaded */ return (GetRMBFile(Index)); } /*=========================================================================== * End of Class Method CDFBlocksFile::GetRMBFile() *=========================================================================*/ #undef __FUNC__ #define __FUNC__ "CDFBlocksFile::IsRMBFile()" /*=========================================================================== * * Class CDFBlocksFile Method - boolean IsRMBFile (Index); * * Returns TRUE if the given BSA directory entry is a RMB type file. * *=========================================================================*/ boolean CDFBlocksFile::IsRMBFile (const int Index) { /* Ensure a valid input */ if (!IsValidIndex(Index)) return (FALSE); /* Ensure a valid filename type */ if (!CompareExtension(pDirectory[Index]->Filename, "RMB")) return (FALSE); return (TRUE); } /*=========================================================================== * End of Class Method CDFBlocksFile::IsRMBFile() *=========================================================================*/ #undef __FUNC__ #define __FUNC__ "CDFBlocksFile::IsRDIFile()" /*=========================================================================== * * Class CDFBlocksFile Method - boolean IsRDIFile (Index); * * Returns TRUE if the given BSA directory entry is a RDI type file. * *=========================================================================*/ boolean CDFBlocksFile::IsRDIFile (const int Index) { /* Ensure a valid input */ if (!IsValidIndex(Index)) return (FALSE); /* Ensure a valid filename type */ if (!CompareExtension(pDirectory[Index]->Filename, "RDI")) return (FALSE); return (TRUE); } /*=========================================================================== * End of Class Method CDFBlocksFile::IsRDIFile() *=========================================================================*/ #undef __FUNC__ #define __FUNC__ "CDFBlocksFile::IsRDBFile()" /*=========================================================================== * * Class CDFBlocksFile Method - boolean IsRDBFile (Index); * * Returns TRUE if the given BSA directory entry is a RDB type file. * *=========================================================================*/ boolean CDFBlocksFile::IsRDBFile (const int Index) { /* Ensure a valid input */ if (!IsValidIndex(Index)) return (FALSE); /* Ensure a valid filename type */ if (!CompareExtension(pDirectory[Index]->Filename, "RDB")) return (FALSE); return (TRUE); } /*=========================================================================== * End of Class Method CDFBlocksFile::IsRDBFile() *=========================================================================*/ #undef __FUNC__ #define __FUNC__ "CDFBlocksFile::ReadRMB()" /*=========================================================================== * * Class CDFBlocksFile Method - boolean ReadRMB (pFileName); * * Attempts to input a RMBFile into the given array object. Returns FALSE * on any error. * *=========================================================================*/ boolean CDFBlocksFile::ReadRMB (const char* pFilename) { boolean Result; int Index; /* Find the record index of the specified file */ Index = FindRecordIndex(pFilename); Result = ReadRMB(Index); return (Result); } /*=========================================================================== * End of Class Method CDFBlocksFile::ReadRMB() *=========================================================================*/ #undef __FUNC__ #define __FUNC__ "CDFBlocksFile::ReadRMB()" /*=========================================================================== * * Class CDFBlocksFile Method - boolean ReadRMB (Index); * * Attempts to input a RMBFile into the given array object. Returns FALSE * on any error. * *=========================================================================*/ boolean CDFBlocksFile::ReadRMB (const int Index) { boolean HadToOpenFile = FALSE; boolean Result; /* Ensure a valid input */ if (!IsRMBFile(Index)) { SET_EXT_ERROR3(ERR_NULL, "BSA directory %d is not a valid RMB type!", Index); return (FALSE); } /* Attempt to open BSA file if required */ if (!IsOpen()) { if (!Open()) return (FALSE); HadToOpenFile = TRUE; } /* Initialize array statistics if required */ #ifdef DOSTATS static boolean DoStatsInit = FALSE; if (!DoStatsInit) { DoStatsInit = TRUE; INIT_STAT_ARR(RMBHeaderUnknowns, 6) } #endif /* Allocate the array record */ CreateRMBFile(Index); /* Move to the appropiate position in file */ fseek (pFileHandle, pDirectory[Index]->RecordOffset, SEEK_SET); /* Attempt to read the RMB file */ Result = pRecords[Index]->Read(pFileHandle, pDirectory[Index]->RecordSize); /* Close file if required */ if (HadToOpenFile) Close(); if (!Result) { DestroyPointer(pRecords[Index]); } return (Result); } /*=========================================================================== * End of Class Method CDFBlocksFile::ReadRMB() *=========================================================================*/ #ifdef DOSTATS #undef __FUNC__ #define __FUNC__ "DFBlocksOutputStats()" /*=========================================================================== * * Function - void DFBlocksOutputStats (void); * * Output statistics if statistic mode is defined. * *=========================================================================*/ void DFBlocksOutputStats (void) { OUT_STAT_REC(RMBNumRecords1); OUT_STAT_REC(RMBNumRecords2); OUT_STAT_REC(RMBNumRecords3); OUT_STAT_REC(RMBNumSec1Rec) OUT_STAT_REC(RMBNumSec2Rec) OUT_STAT_REC(RMBNumSec3Rec) OUT_STAT_REC(RMBNumSec4Rec) OUT_STAT_REC(RMBNumSec5Rec) OUT_STAT_ARR(RMBHeaderUnknowns, 6) OUT_STAT_VAR(RMBSec1U1) OUT_STAT_VAR(RMBSec1U2) OUT_STAT_VAR(RMBSec1U3) OUT_STAT_VAR(RMBSec1U4) OUT_STAT_VAR(RMBSec1U5) OUT_STAT_VAR(RMBSec1U6) OUT_STAT_VAR(RMBSec1U7) OUT_STAT_VAR(RMBSec1U8) OUT_STAT_VAR(RMBSec1X1) OUT_STAT_VAR(RMBSec1Y1) OUT_STAT_VAR(RMBSec1Z1) OUT_STAT_VAR(RMBSec1X2) OUT_STAT_VAR(RMBSec1Y2) OUT_STAT_VAR(RMBSec1Z2) OUT_STAT_VAR(RMBSec2U1) OUT_STAT_VAR(RMBSec2U2) OUT_STAT_VAR(RMBSec2U3) OUT_STAT_VAR(RMBSec3U1) OUT_STAT_VAR(RMBSec3U2) OUT_STAT_VAR(RMBSec3U3) OUT_STAT_VAR(RMBSec4U1) OUT_STAT_VAR(RMBSec4U2) OUT_STAT_VAR(RMBSec4U3) OUT_STAT_VAR(RMBSec5U1) OUT_STAT_VAR(RMBSec5U2) OUT_STAT_VAR(RMBSec5U3) OUT_STAT_VAR(RMBSec5U4) } /*=========================================================================== * End of Function DFBlocksOutputStats() *=========================================================================*/ #endif