/*===========================================================================
 *
 * DFMaps.CPP, Dave Humphrey (uesp@m0use.net), 14 November 2000
 *
 *=========================================================================*/

//#define DOSTATS

	/* Include Files */
#include "dfmaps.h"
#include "dfcommon.h"


	/* Initialize statistics if required */
DEF_STAT_VAR(PItemUnknown1)
DEF_STAT_VAR(DItemUnknown1)
DEF_STAT_VAR(PItemUnknown2)
DEF_STAT_VAR(DItemUnknown2)
DEF_STAT_VAR(PItemUnknown3)
DEF_STAT_VAR(DItemUnknown3)
DEF_STAT_VAR(PItemUnknown4)
DEF_STAT_VAR(DItemUnknown4)
DEF_STAT_VAR(PItemUnknown5)
DEF_STAT_VAR(DItemUnknown5)
DEF_STAT_VAR(PItemUnknown6)
DEF_STAT_VAR(DItemUnknown6)
DEF_STAT_VAR(DItemUnknown7)
DEF_STAT_VAR(DItemUnknown8)
DEF_STAT_VAR(DItemUnknown9)
DEF_STAT_VAR(DItemUnknown10)
DEF_STAT_REC(PItemNumPreRec)
DEF_STAT_REC(DItemNumPreRec)
DEF_STAT_ARR(PItemPreRec, 6)
DEF_STAT_ARR(DItemPreRec, 6)
DEF_STAT_VAR(PItemXPos)
DEF_STAT_VAR(PItemYPos)
DEF_STAT_VAR(DItemXPos)
DEF_STAT_VAR(DItemYPos)
DEF_STAT_REC(PItemNumPostRec)
DEF_STAT_REC(DItemNumPostRec)
DEF_STAT_REC(NumDunPostRec)
DEF_STAT_REC(TotalDungeons)
DEF_STAT_REC(TotalLocations)
DEF_STAT_ARR(PItemPostNulls, 16)
DEF_STAT_VAR(PItemHouseName)
DEF_STAT_VAR(PItemHouseType)
DEF_STAT_VAR(PItemPostU1)
DEF_STAT_VAR(PItemPostU2)
DEF_STAT_VAR(PItemPostU3)
DEF_STAT_ARR(PItemNulls, 380)
DEF_STAT_ARR(DItemPostUnknowns, 4)
DEF_STAT_CNT(DItemPostUn2)
DEF_STAT_CNT(DItemPostUn3)
DEF_STAT_CNT(DItemPostUn4)
DEF_STAT_CNT(PItemBlock1)
DEF_STAT_CNT(PItemBlock2)
DEF_STAT_CNT(PItemBlock3)


#undef  __FUNC__
#define __FUNC__ "CDFMapItemRecord::CDFMapItemRecord()"
/*===========================================================================
 *
 * Class CDFMapItemRecord Constructor
 *
 *=========================================================================*/
CDFMapItemRecord::CDFMapItemRecord() {
  NumPreRecords = 0;
  RecordOffset = 0;
  RecordSize = 0;
  Dungeon = FALSE;
  pPreRecords = NULL;
 }
/*===========================================================================
 *		End of Class CDFMapItemRecord Constructor
 *=========================================================================*/


#undef  __FUNC__
#define __FUNC__ "CDFMapItemRecord::Destroy()"
/*===========================================================================
 *
 * Class CDFMapItemRecord Destructor
 *
 *=========================================================================*/
void CDFMapItemRecord::Destroy (void) {

	/* Unallocate memory */
  DestroyPointerArray(pPreRecords);
  RecordSize = 0;
  RecordOffset = 0;
  NumPreRecords = 0;
  Dungeon = FALSE;
 }
/*===========================================================================
 *		End of Class CDFMapItemRecord Constructor
 *=========================================================================*/


#undef  __FUNC__
#define __FUNC__ "CDFMapItemRecord::Clear()"
/*===========================================================================
 *
 * Class CDFMapItemRecord Method - void Clear (void);
 *
 * Removes unwanted data.
 *
 *=========================================================================*/
void CDFMapItemRecord::Clear (void) {

	/* Unallocate memory */
  DestroyPointerArray(pPreRecords);
  RecordOffset = 0;
  NumPreRecords = 0;
 }
/*===========================================================================
 *		End of Class Method CDFMapItemRecord::Clear()
 *=========================================================================*/


#undef  __FUNC__
#define __FUNC__ "CDFMapItemRecord::CreatePreRecords()"
/*===========================================================================
 *
 * Class CDFMapItemRecord Method - void CreatePreRecords (void);
 *
 * Creates the pre-record array.  Protected class method.
 *
 *=========================================================================*/
void CDFMapItemRecord::CreatePreRecords (void) {
 
	/* Ensure there is something to create */
  pPreRecords = NULL;
  if (NumPreRecords == 0) return;

	/* Allocate the pointer array */
  CreatePointerArray(pPreRecords, dfmap_pitem_prerecord_t, NumPreRecords);	
 }
/*===========================================================================
 *		End of Class Method CDFMapItemRecord::CreatePreRecords()
 *=========================================================================*/


#undef  __FUNC__
#define __FUNC__ "CDFMapItemRecord::Dump()"
/*===========================================================================
 *
 * Class CDFMapItemRecord Method - void Dump (pFileHandle, DumpFlags);
 *
 * Output object info to a file stream.
 *
 *=========================================================================*/
void CDFMapItemRecord::Dump (FILE* pFileHandle, const dfmap_dumpflags_t DumpFlags) {
  char TypeChar = Dungeon ? 'D' : 'P';

	/* Ensure we wish to output dump information */
  if ((DumpFlags & DFMAP_DUMP_ITEMINFO) == 0) return;

	/* Ensure valid input */
  if (pFileHandle == NULL) { 
    SET_EXT_ERROR2(ERR_NULL, "Invalid NULL file handle received!");
    return;
   }

	/* Output basic information */
  fprintf (pFileHandle, "\t\t\t%cI: Name='%s', Position=(%ld, %ld), ID=0x%04X,\n", TypeChar, Header.Name, Header.XPosition, Header.YPosition, Header.LocationID&0xFFFF);
  fprintf (pFileHandle, "\t\t\t%cI: Offset=0x%08lX, PreRecords=%d\n", TypeChar, RecordOffset, NumPreRecords);
  
	/* Output unknown information if required */
  if (DumpFlags & DFMAP_DUMP_PITEMS_UNKNOWNS) {
    fprintf (pFileHandle, "\t\t\t%cI: Unknowns = 0x%08lX 0x%08lX 0x%08lX 0x%08lX 0x%04lX 0x%08lX\n", TypeChar, Header.Unknown1, Header.Unknown2,  Header.Unknown3, Header.Unknown4&0xFFFF, Header.Unknown5);
   }
 }
/*===========================================================================
 *		End of Class Method CDFMapItemRecord::Dump()
 *=========================================================================*/


#undef  __FUNC__
#define __FUNC__ "CDFMapItemRecord::Read()"
/*===========================================================================
 *
 * Class CDFMapItemRecord Method - boolean Read (FILE* pFileHandle);
 *
 * Attempts to read in the data from the current position in the file
 * stream.  Returns FALSE on any error.
 *
 *=========================================================================*/
boolean CDFMapItemRecord::Read (FILE* pFileHandle) {
  boolean Result;

	/* Ensure valid input */
  if (pFileHandle == NULL) { 
    SET_EXT_ERROR2(ERR_NULL, "Invalid NULL file handle received!");
    return (FALSE);
   }

	/* Delete the current contents */
  Clear();

	/* Save the record offset */
  RecordOffset = ftell(pFileHandle);

  if (RecordOffset < 0) { 
    SET_EXT_ERROR2(ERR_READ, "Failed to retrieve PItem record offset!");
    return (FALSE);
   }

	/* Read in record data */
  Result = ReadPreRecords(pFileHandle);
  if (Result) Result = ReadHeader(pFileHandle);
  if (Result) Result = ReadPostHeader(pFileHandle);
  if (Result) Result = ReadPostRecords(pFileHandle);
  if (Result) Result = ReadExtra(pFileHandle);

  return (TRUE);
 }
/*===========================================================================
 *		End of Class Method CDFMapItemRecord::Read()
 *=========================================================================*/


#undef  __FUNC__
#define __FUNC__ "CDFMapItemRecord::ReadHeader()"
/*===========================================================================
 *
 * Class CDFMapItemRecord Method - boolean ReadHeader (FILE* pFileHandle);
 *
 * Attempts to read in the header data from the current position in 
 * the file stream.  Returns FALSE on any error. Protected class method.
 *
 *=========================================================================*/
boolean CDFMapItemRecord::ReadHeader (FILE* pFileHandle) {
  int Result;

	/* Read in the header data all at once */
  Result = fread (&Header, 1, sizeof(dfmap_pitem_header_t), pFileHandle);

  if (Result != sizeof(dfmap_pitem_header_t)) {
    SET_EXT_ERROR3(ERR_READ, "Error reading PItem header data (Offset 0x%08lX)!", ftell(pFileHandle));
    return (FALSE);
   }

	/* Perform statistics */
  #ifdef DFMAP_DOSTATS
    
    if (Dungeon) {
      DO_STAT_VAR(DItemXPos, Header.XPosition) 
      DO_STAT_VAR(DItemYPos, Header.YPosition) 
      DO_STAT_VAR(DItemUnknown1, Header.Unknown1)
      DO_STAT_VAR(DItemUnknown2, Header.Unknown2)
      DO_STAT_VAR(DItemUnknown3, Header.Unknown3)
      DO_STAT_VAR(DItemUnknown4, Header.Unknown4)
      DO_STAT_VAR(DItemUnknown5, Header.Unknown5)
     }
    else {
      DO_STAT_VAR(PItemXPos, Header.XPosition) 
      DO_STAT_VAR(PItemYPos, Header.YPosition) 
      DO_STAT_VAR(PItemUnknown1, Header.Unknown1)
      DO_STAT_VAR(PItemUnknown2, Header.Unknown2)
      DO_STAT_VAR(PItemUnknown3, Header.Unknown3)
      DO_STAT_VAR(PItemUnknown4, Header.Unknown4)
      DO_STAT_VAR(PItemUnknown5, Header.Unknown5)
     }
  #endif
 
  return (TRUE);
 }
/*===========================================================================
 *		End of Class Method CDFMapItemRecord::ReadHeader()
 *=========================================================================*/


#undef  __FUNC__
#define __FUNC__ "CDFMapItemRecord::ReadPostHeader()"
/*===========================================================================
 *
 * Class CDFMapItemRecord Method - boolean ReadPostHeader (FILE* pFileHandle);
 *
 * Attempts to read in the post header data from the current position in 
 * the file stream.  Returns FALSE on any error. Protected class method.
 *
 *=========================================================================*/
boolean CDFMapItemRecord::ReadPostHeader (FILE* pFileHandle) {
  int Result;

	/* Read the extra 9-bytes */
  Result = fread (Unknowns1, 1, 9, pFileHandle);

  if (Result != 9) {
    SET_EXT_ERROR3(ERR_READ, "Error reading 9 bytes of unknown post-header data (Offset 0x%08lX)!", ftell(pFileHandle));
    return (FALSE);
   }

	/* Read in the number of post records */
  clearerr(pFileHandle);
  NumPostRecords = (ushort) read_short(pFileHandle);

  if (ferror(pFileHandle) || feof(pFileHandle)) {
    SET_EXT_ERROR3(ERR_READ, "Error reading the number of post records in location (Offset 0x%08lX)!", ftell(pFileHandle));
    return (FALSE);
   }

	/* Perform statistics */
  return (TRUE);
 }
/*===========================================================================
 *		End of Class Method CDFMapItemRecord::ReadPostHeader()
 *=========================================================================*/


#undef  __FUNC__
#define __FUNC__ "CDFMapItemRecord::ReadPreRecords()"
/*===========================================================================
 *
 * Class CDFMapItemRecord Method - boolean ReadPreRecords (FILE* pFileHandle);
 *
 * Attempts to read in the pre-record data from the current position in 
 * the file stream.  Returns FALSE on any error. Protected class method.
 *
 *=========================================================================*/
boolean CDFMapItemRecord::ReadPreRecords (FILE* pFileHandle) {
  int Result;

	/* Read in the number of pre-records */
  clearerr(pFileHandle);
  NumPreRecords = read_long(pFileHandle);

	/* Ensure input was successful */
  if (ferror(pFileHandle) || feof(pFileHandle)) {
    SET_EXT_ERROR3(ERR_READ, "Error reading number of prerecords from PItem data (Offset 0x%08lX)!", ftell(pFileHandle));
    return (FALSE);
   }

  if (NumPreRecords == 0) return (TRUE);
  CreatePreRecords();

	/* Read in the prerecord data all at once */
  Result = fread (pPreRecords, sizeof(dfmap_pitem_prerecord_t), NumPreRecords, pFileHandle);

  if (Result != NumPreRecords) {
    SET_EXT_ERROR3(ERR_READ, "Error reading prerecord data from PItem record (Offset 0x%08lX)!", ftell(pFileHandle));
    return (FALSE);
   }

   	/* Perform statistics */
  #ifdef DOSTATS

    if (Dungeon) { 
      DO_STAT_REC2(DItemNumPreRec, NumPreRecords)
      int I;
    
      for (I = 0; I < NumPreRecords; I++) {
        DO_STAT_ARR(DItemPreRec, pPreRecords[I].Data, 6)
       }
     }
    else {
      DO_STAT_REC2(PItemNumPreRec, NumPreRecords)
      int I;
    
      for (I = 0; I < NumPreRecords; I++) {
        DO_STAT_ARR(PItemPreRec, pPreRecords[I].Data, 6)
       }
     }

  #endif
 
  return (TRUE);
 }
/*===========================================================================
 *		End of Class Method CDFMapItemRecord::ReadPreRecords()
 *=========================================================================*/


#undef  __FUNC__
#define __FUNC__ "CDFMapPItemRecord::CDFMapPItemRecord()"
/*===========================================================================
 *
 * Class CDFMapPItemRecord Constructor
 *
 *=========================================================================*/
CDFMapPItemRecord::CDFMapPItemRecord() {
  pPostRecords = NULL;
  NumPostRecords = 0;
  Dungeon = FALSE;
 }
/*===========================================================================
 *		End of Class CDFMapPItemRecord Constructor
 *=========================================================================*/


#undef  __FUNC__
#define __FUNC__ "CDFMapPItemRecord::Destroy()"
/*===========================================================================
 *
 * Class CDFMapPItemRecord Destructor
 *
 *=========================================================================*/
void CDFMapPItemRecord::Destroy (void) {

	/* Call the base class method */
  CDFMapItemRecord::Destroy();	

	/* Unallocate memory */
  DestroyPointerArray(pPostRecords);
  NumPostRecords = 0;
 }
/*===========================================================================
 *		End of Class CDFMapPItemRecord Destructor
 *=========================================================================*/


#undef  __FUNC__
#define __FUNC__ "CDFMapPItemRecord::Clear()"
/*===========================================================================
 *
 * Class CDFMapPItemRecord Method - void Clear (void);
 *
 * Removes unwanted data.
 *
 *=========================================================================*/
void CDFMapPItemRecord::Clear (void) {

	/* Call the base class method */
  CDFMapItemRecord::Clear();

	/* Unallocate memory */
  DestroyPointerArray(pPostRecords);
  NumPostRecords = 0;
 }
/*===========================================================================
 *		End of Class Method CDFMapPItemRecord::Clear()
 *=========================================================================*/


#undef  __FUNC__
#define __FUNC__ "CDFMapPItemRecord::CreatePostRecords()"
/*===========================================================================
 *
 * Class CDFMapPItemRecord Method - void CreatePostRecords (void);
 *
 * Creates the post-record array.  Protected class method.
 *
 *=========================================================================*/
void CDFMapPItemRecord::CreatePostRecords (void) {
 
	/* Ensure there is something to create */
  pPostRecords = NULL;
  if (NumPostRecords == 0) return;

	/* Allocate the pointer array */
  CreatePointerArray(pPostRecords, dfmap_pitem_postrecord_t, NumPostRecords);	
 }
/*===========================================================================
 *		End of Class Method CDFMapPItemRecord::CreatePostRecords()
 *=========================================================================*/


#undef  __FUNC__
#define __FUNC__ "CDFMapPItemRecord::Dump()"
/*===========================================================================
 *
 * Class CDFMapPItemRecord Method - void Dump (pFileHandle, DumpFlags);
 *
 * Output object info to a file stream.
 *
 *=========================================================================*/
void CDFMapPItemRecord::Dump (FILE* pFileHandle, const dfmap_dumpflags_t DumpFlags) {

	/* Ensure valid input */
  if (pFileHandle == NULL) { 
    SET_EXT_ERROR2(ERR_NULL, "Invalid NULL file handle received!");
    return;
   }

	/* Call the base class method first */
  CDFMapItemRecord::Dump(pFileHandle, DumpFlags);

	/* Ensure we wish to output dump information */
  if ((DumpFlags & DFMAP_DUMP_PITEMS) == 0) return;

 }
/*===========================================================================
 *		End of Class Method CDFMapPItemRecord::Dump()
 *=========================================================================*/


#undef  __FUNC__
#define __FUNC__ "CDFMapPItemRecord::ReadExtra()"
/*===========================================================================
 *
 * Class CDFMapPItemRecord Method - boolean ReadExtra (FILE* pFileHandle);
 *
 * Attempts to read in the extra data from the current position in 
 * the file stream.  Returns FALSE on any error. Protected class method.
 *
 *=========================================================================*/
boolean CDFMapPItemRecord::ReadExtra (FILE* pFileHandle) {
  int Result;

  	/* Read the footer data all at once  */
  Result = fread (&Footer, 1, sizeof(dfmap_pitem_footer_t), pFileHandle);

  if (Result != sizeof(dfmap_pitem_footer_t)) {
    SET_EXT_ERROR3(ERR_READ, "Error reading footer data location record (Offset 0x%08lX)!", ftell(pFileHandle));
    return (FALSE);
   }

	/* Perform statistics */
  #ifdef DOSTATS
    DO_STAT_VAR(PItemUnknown6, Unknown6)
    DO_STAT_ARR(PItemNulls, ExtraBytes, 380)

    DO_STAT_CNT(PItemBlock1, ExtraBytes[13])
    DO_STAT_CNT(PItemBlock2, ExtraBytes[77])
    DO_STAT_CNT(PItemBlock3, ExtraBytes[141])

    long FilePos = ftell(pFileHandle);

    if (FilePos != RecordOffset + RecordSize) 
      SystemLog.Printf ("\tPItem extra bytes: %ld (%ld, Dungeon = %d)!", FilePos - RecordOffset - RecordSize, Header.Unknown5, Dungeon); 
  #endif
 
  return (TRUE);
 }
/*===========================================================================
 *		End of Class Method CDFMapPItemRecord::ReadExtra()
 *=========================================================================*/


#undef  __FUNC__
#define __FUNC__ "CDFMapPItemRecord::ReadPostHeader()"
/*===========================================================================
 *
 * Class CDFMapPItemRecord Method - boolean ReadPostHeader (FILE* pFileHandle);
 *
 * Attempts to read in the post header data from the current position in 
 * the file stream.  Returns FALSE on any error. Protected class method.
 *
 *=========================================================================*/
boolean CDFMapPItemRecord::ReadPostHeader (FILE* pFileHandle) {
  int Result;

	/* Call the base class method first */
  Result = CDFMapItemRecord::ReadPostHeader(pFileHandle);
  if (!Result) return (FALSE);

	/* Read the extra 5-bytes */
  Result = fread (Unknowns2, 1, 5, pFileHandle);

  if (Result != 5) {
    SET_EXT_ERROR3(ERR_READ, "Error reading 5 bytes of unknown post-header data (Offset 0x%08lX)!", ftell(pFileHandle));
    return (FALSE);
   }

	/* Perform statistics */
  return (TRUE);
 }
/*===========================================================================
 *		End of Class Method CDFMapPItemRecord::ReadPostHeader()
 *=========================================================================*/


#undef  __FUNC__
#define __FUNC__ "CDFMapPItemRecord::ReadPostRecords()"
/*===========================================================================
 *
 * Class CDFMapPItemRecord Method - boolean ReadPostRecords (FILE* pFileHandle);
 *
 * Attempts to read in the post-record data from the current position in 
 * the file stream.  Returns FALSE on any error. Protected class method.
 *
 *=========================================================================*/
boolean CDFMapPItemRecord::ReadPostRecords (FILE* pFileHandle) {
  int Result;

	/* Allocate the post record array if required */
  if (NumPostRecords == 0) return (TRUE);
  CreatePostRecords();

	/* Read in the post record data all at once */
  Result = fread (pPostRecords, sizeof(dfmap_pitem_postrecord_t), NumPostRecords, pFileHandle);

  if (Result != NumPostRecords) {
    SET_EXT_ERROR3(ERR_READ, "Error reading postrecord data from PItem record (Offset 0x%08lX)!", ftell(pFileHandle));
    return (FALSE);
   }

   	/* Perform statistics */
  #ifdef DOSTATS
    int LoopCounter;

    for (LoopCounter = 0; LoopCounter < NumPostRecords; LoopCounter++) {
      DO_STAT_VAR(PItemHouseName, pPostRecords[LoopCounter].HouseName)
      DO_STAT_VAR(PItemHouseType, pPostRecords[LoopCounter].HouseType)
      DO_STAT_VAR(PItemPostU1, pPostRecords[LoopCounter].Unknown1)
      DO_STAT_VAR(PItemPostU2, pPostRecords[LoopCounter].Unknown2)
      DO_STAT_VAR(PItemPostU3, pPostRecords[LoopCounter].Unknown3)
      DO_STAT_ARR(PItemPostNulls, pPostRecords[LoopCounter].NullValues, 16)
     }
   	
    DO_STAT_REC2(PItemNumPostRec, NumPostRecords)
  #endif
  
  return (TRUE);
 }
/*===========================================================================
 *		End of Class Method CDFMapPItemRecord::ReadPostRecords()
 *=========================================================================*/


#undef  __FUNC__
#define __FUNC__ "CDFMapDItemRecord::CDFMapDItemRecord()"
/*===========================================================================
 *
 * Class CDFMapDItemRecord Constructor
 *
 *=========================================================================*/
CDFMapDItemRecord::CDFMapDItemRecord() {
  pPostRecords = NULL;
  Dungeon = TRUE;
  NumDungeonPostRecords = 0;
  ExtraBytesSize = 0;
 }
/*===========================================================================
 *		End of Class CDFMapDItemRecord Constructor
 *=========================================================================*/


#undef  __FUNC__
#define __FUNC__ "CDFMapDItemRecord::Destroy()"
/*===========================================================================
 *
 * Class CDFMapDItemRecord Destructor
 *
 *=========================================================================*/
void CDFMapDItemRecord::Destroy (void) {

	/* Call the base class method */
  CDFMapItemRecord::Destroy();	

	/* Unallocate memory */
  DestroyPointerArray(pPostRecords);
  NumDungeonPostRecords = 0;
  ExtraBytesSize = 0;
 }
/*===========================================================================
 *		End of Class CDFMapDItemRecord Destructor
 *=========================================================================*/


#undef  __FUNC__
#define __FUNC__ "CDFMapDItemRecord::Clear()"
/*===========================================================================
 *
 * Class CDFMapDItemRecord Method - void Clear (void);
 *
 * Removes unwanted data.
 *
 *=========================================================================*/
void CDFMapDItemRecord::Clear (void) {

	/* Call the base class method */
  CDFMapItemRecord::Clear();

	/* Unallocate memory */
  DestroyPointerArray(pPostRecords);
  NumDungeonPostRecords = 0;
  ExtraBytesSize = 0;
 }
/*===========================================================================
 *		End of Class Method CDFMapDItemRecord::Clear()
 *=========================================================================*/


#undef  __FUNC__
#define __FUNC__ "CDFMapDItemRecord::CreatePostRecords()"
/*===========================================================================
 *
 * Class CDFMapDItemRecord Method - void CreatePostRecords (void);
 *
 * Creates the post-record array.  Protected class method.
 *
 *=========================================================================*/
void CDFMapDItemRecord::CreatePostRecords (void) {
 
	/* Ensure there is something to create */
  pPostRecords = NULL;
  if (NumDungeonPostRecords == 0) return;

	/* Allocate the pointer array */
  CreatePointerArray(pPostRecords, dfmap_ditem_postrecord_t, NumDungeonPostRecords);	
 }
/*===========================================================================
 *		End of Class Method CDFMapDItemRecord::CreatePostRecords()
 *=========================================================================*/


#undef  __FUNC__
#define __FUNC__ "CDFMapDItemRecord::Dump()"
/*===========================================================================
 *
 * Class CDFMapDItemRecord Method - void Dump (pFileHandle, DumpFlags);
 *
 * Output object info to a file stream.
 *
 *=========================================================================*/
void CDFMapDItemRecord::Dump (FILE* pFileHandle, const dfmap_dumpflags_t DumpFlags) {

	/* Ensure valid input */
  if (pFileHandle == NULL) { 
    SET_EXT_ERROR2(ERR_NULL, "Invalid NULL file handle received!");
    return;
   }

	/* Call the base class method first */
  CDFMapItemRecord::Dump(pFileHandle, DumpFlags);

	/* Ensure we wish to output dump information */
  if ((DumpFlags & DFMAP_DUMP_DITEMS) == 0) return;

 }
/*===========================================================================
 *		End of Class Method CDFMapDItemRecord::Dump()
 *=========================================================================*/


#undef  __FUNC__
#define __FUNC__ "CDFMapDItemRecord::ReadExtra()"
/*===========================================================================
 *
 * Class CDFMapDItemRecord Method - boolean ReadExtra (FILE* pFileHandle);
 *
 * Attempts to read in the extra data from the current position in 
 * the file stream.  Returns FALSE on any error. Protected class method.
 *
 *=========================================================================*/
boolean CDFMapDItemRecord::ReadExtra (FILE* pFileHandle) {
  int Result;

  	/* Read the extra three short numbers */
  Unknown8  = read_short(pFileHandle);
  Unknown9  = read_short(pFileHandle);
  Unknown10 = read_short(pFileHandle);
    
  if (ferror(pFileHandle) || feof(pFileHandle)) {
    SET_EXT_ERROR3(ERR_READ, "Error reading post header data (Offset 0x%08lX)!", ftell(pFileHandle));
    return (FALSE);
   }

  	/* Read the extra bytes */
  ExtraBytesSize = DFMAP_DITEM_EXTRABYTES - 8 - NumDungeonPostRecords*4;
  Result = fread (ExtraBytes, 1, ExtraBytesSize, pFileHandle);

  if (Result != ExtraBytesSize) {
    SET_EXT_ERROR3(ERR_READ, "Error reading extra bytes of location record (Offset 0x%08lX)!", ftell(pFileHandle));
    return (FALSE);
   }

	/* Perform statistics */
  #ifdef DOSTATS
    DO_STAT_VAR(DItemUnknown8, Unknown6)
    DO_STAT_VAR(DItemUnknown9, Unknown6)
    DO_STAT_VAR(DItemUnknown10, Unknown6)
    long FilePos = ftell(pFileHandle);

    if (FilePos != RecordOffset + RecordSize) {
      SystemLog.Printf ("\tDItem extra bytes: %ld (0x%08lX)!", FilePos - RecordOffset - RecordSize, RecordOffset); 
     }
  #endif
 
  return (TRUE);
 }
/*===========================================================================
 *		End of Class Method CDFMapDItemRecord::ReadExtra()
 *=========================================================================*/


#undef  __FUNC__
#define __FUNC__ "CDFMapDItemRecord::ReadPostHeader()"
/*===========================================================================
 *
 * Class CDFMapDItemRecord Method - boolean ReadPostHeader (FILE* pFileHandle);
 *
 * Attempts to read in the post header data from the current position in 
 * the file stream.  Returns FALSE on any error. Protected class method.
 *
 *=========================================================================*/
boolean CDFMapDItemRecord::ReadPostHeader (FILE* pFileHandle) {
  int Result;

	/* Call the base class method first */
  Result = CDFMapItemRecord::ReadPostHeader(pFileHandle);
  if (!Result) return (FALSE);

	/* Read the extra two longs and short number of dungeon post-records */
  Unknown6 = read_long(pFileHandle);
  Unknown7 = read_long(pFileHandle);
  NumDungeonPostRecords = (ushort) read_short(pFileHandle);
  
  if (ferror(pFileHandle) || feof(pFileHandle)) {
    SET_EXT_ERROR3(ERR_READ, "Error reading post header data (Offset 0x%08lX)!", ftell(pFileHandle));
    return (FALSE);
   }

	/* Perform statistics */
  DO_STAT_VAR(DItemUnknown6, Unknown6)
  DO_STAT_VAR(DItemUnknown7, Unknown7)
  return (TRUE);
 }
/*===========================================================================
 *		End of Class Method CDFMapDItemRecord::ReadPostHeader()
 *=========================================================================*/


#undef  __FUNC__
#define __FUNC__ "CDFMapDItemRecord::ReadPostRecords()"
/*===========================================================================
 *
 * Class CDFMapDItemRecord Method - boolean ReadPostRecords (FILE* pFileHandle);
 *
 * Attempts to read in the post-record data from the current position in 
 * the file stream.  Returns FALSE on any error. Protected class method.
 *
 *=========================================================================*/
boolean CDFMapDItemRecord::ReadPostRecords (FILE* pFileHandle) {
  int Result;

	/* Allocate the post record array if required */
  if (NumDungeonPostRecords == 0) return (TRUE);
  CreatePostRecords();

	/* Read in the post record data all at once */
  Result = fread (pPostRecords, sizeof(dfmap_ditem_postrecord_t), NumDungeonPostRecords, pFileHandle);

  if (Result != NumDungeonPostRecords) {
    SET_EXT_ERROR3(ERR_READ, "Error reading postrecord data from DItem record (Offset 0x%08lX)!", ftell(pFileHandle));
    return (FALSE);
   }

	/* Perform statistics */
  #ifdef DOSTATS
    int LoopCounter;

    for (LoopCounter = 0; LoopCounter < NumDungeonPostRecords; LoopCounter++) {
      DO_STAT_ARR(DItemPostUnknowns, pPostRecords[LoopCounter].Unknowns, 4)

      DO_STAT_CNT(DItemPostUn2, pPostRecords[LoopCounter].Unknowns[1])
      DO_STAT_CNT(DItemPostUn3, pPostRecords[LoopCounter].Unknowns[2])
      DO_STAT_CNT(DItemPostUn4, pPostRecords[LoopCounter].Unknowns[3])
     }
   	
    DO_STAT_REC2(NumDunPostRec, NumDungeonPostRecords)
  #endif

  return (TRUE);
 }
/*===========================================================================
 *		End of Class Method CDFMapDItemRecord::ReadPostRecords()
 *=========================================================================*/


#undef  __FUNC__
#define __FUNC__ "CDFMapTableRecord::CDFMapTableRecord()"
/*===========================================================================
 *
 * Class CDFMapTableRecord Constructor
 *
 *=========================================================================*/
CDFMapTableRecord::CDFMapTableRecord() {
  memset(&TableData, 0, sizeof(dfmap_table_t));
  RecordOffset = 0;
 }
/*===========================================================================
 *		End of Class CDFMapTableRecord Constructor
 *=========================================================================*/


#undef  __FUNC__
#define __FUNC__ "CDFMapTableRecord::Destroy()"
/*===========================================================================
 *
 * Class CDFMapTableRecord Destructor
 *
 *=========================================================================*/
void CDFMapTableRecord::Destroy (void) {
  memset(&TableData, 0, sizeof(dfmap_table_t));
  RecordOffset = 0;
 }
/*===========================================================================
 *		End of Class CDFMapTableRecord Constructor
 *=========================================================================*/


#undef  __FUNC__
#define __FUNC__ "CDFMapTableRecord::Dump()"
/*===========================================================================
 *
 * Class CDFMapTableRecord Method - void Dump (pFileHandle, DumpFlags);
 *
 * Output object info to a file stream.
 *
 *=========================================================================*/
void CDFMapTableRecord::Dump (FILE* pFileHandle, const dfmap_dumpflags_t DumpFlags) {

	/* Ensure we wish to output dump information */
  if ((DumpFlags & DFMAP_DUMP_MAPTABLE) == 0) return;

	/* Ensure valid input */
  if (pFileHandle == NULL) { 
    SET_EXT_ERROR2(ERR_NULL, "Invalid NULL file handle received!");
    return;
   }

	/* Output basic information */
  fprintf (pFileHandle, "\t\t\tMT: Position = %d, %d  (Type = %d)\n", TableData.XPosition, TableData.YPosition, TableData.LocationType);

	/* Output unknown information if required */
  if (DumpFlags & DFMAP_DUMP_MAPTABLE_UNKNOWNS) {
    fprintf (pFileHandle, "\t\t\tMT: Unknowns = 0x%02X 0x%08lX 0x%04X 0x%08lX\n", TableData.Unknown1&0xFF, TableData.Unknown2, TableData.Unknown3&0xFFFF, TableData.Unknown4);
   }
 }
/*===========================================================================
 *		End of Class Method CDFMapTableRecord::Dump()
 *=========================================================================*/


#undef  __FUNC__
#define __FUNC__ "CDFMapTableRecord::Read()"
/*===========================================================================
 *
 * Class CDFMapTableRecord Method - boolean Read (FILE* pFileHandle);
 *
 * Attempts to read in the data from the current position in the file
 * stream.  Returns FALSE on any error.
 *
 *=========================================================================*/
boolean CDFMapTableRecord::Read (FILE* pFileHandle) {
  int Result;

	/* Ensure valid input */
  if (pFileHandle == NULL) { 
    SET_EXT_ERROR2(ERR_NULL, "Invalid NULL file handle received!");
    return (FALSE);
   }

	/* Delete the current contents */
  Destroy();

	/* Save the record offset */
  RecordOffset = ftell(pFileHandle);

  if (RecordOffset < 0) { 
    SET_EXT_ERROR2(ERR_READ, "Failed to retrieve PItem record offset!");
    return (FALSE);
   }

	/* Read in record data all at once */
  Result = fread (&TableData, 1, sizeof(dfmap_table_t), pFileHandle);

  if (Result != sizeof(dfmap_table_t)) {
    SET_EXT_ERROR3(ERR_READ, "CDFMapTableRecord::Read() - Error reading map table data (Offset 0x%08lX)!", ftell(pFileHandle));
    return (FALSE);
   }

  return (TRUE);
 }
/*===========================================================================
 *		End of Class Method CDFMapTableRecord::Read()
 *=========================================================================*/


#undef  __FUNC__
#define __FUNC__ "CDFMapRegion::CDFMapRegion()"
/*===========================================================================
 *
 * Class CDFMapRegion Constructor
 *
 *=========================================================================*/
CDFMapRegion::CDFMapRegion() {
  RegionFlags = DFMAP_REGION_NONE;
  RegionNumber = -1;
  NumLocations = 0;
  NumDungeons = 0;
  pMapTables = NULL;
  pMapNames = NULL;
  pPItemRecords = NULL;
  pDItemRecords = NULL;
  pPItemOffsets = NULL;
  pDItemOffsets = NULL;
  MapPItemOffset = 0;
  MapDItemOffset = 0;
  MapTableOffset = 0;
  MapNamesOffset = 0;
 }
/*===========================================================================
 *		End of Class CDFMapRegion Constructor
 *=========================================================================*/


#undef  __FUNC__
#define __FUNC__ "CDFMapRegion::Destroy()"
/*===========================================================================
 *
 * Class CDFMapRegion Destructor
 *
 *=========================================================================*/
void CDFMapRegion::Destroy (void) {

  	/* Destroy allocated memory */
  DestroyPointerArray(pPItemRecords);
  DestroyPointerArray(pDItemRecords);
  DestroyPointerArray(pPItemOffsets);
  DestroyPointerArray(pDItemOffsets);
  DestroyPointerArray(pMapTables);
  DestroyPointerArray(pMapNames);

  RegionFlags = DFMAP_REGION_NONE;
  RegionNumber = -1;
  NumLocations = 0;
  NumDungeons = 0;
  MapPItemOffset = 0;
  MapDItemOffset = 0;
  MapTableOffset = 0;
  MapNamesOffset = 0;
 }
/*===========================================================================
 *		End of Class CDFMapRegion Destructor
 *=========================================================================*/


#undef  __FUNC__
#define __FUNC__ "CDFMapRegion::Dump()"
/*===========================================================================
 *
 * Class CDFMapRegion Method - void Dump (pFileHandle, DumpFlags);
 *
 * Output object info to a file stream.
 *
 *=========================================================================*/
void CDFMapRegion::Dump (FILE* pFileHandle, const dfmap_dumpflags_t DumpFlags) {
  int LoopCounter;

	/* Output region dump information only if required */
  if ((DumpFlags & DFMAP_DUMP_REGION) == 0) return;

	/* Ensure valid input */
  if (pFileHandle == NULL) { 
    SET_EXT_ERROR2(ERR_NULL, "Invalid NULL file handle received!");
    return;
   }

	/* Output basic information */
  fprintf (pFileHandle, "\tRegion %d, %d Locations, %d Dungeons  (Region Flags = %d)\n", RegionNumber, NumLocations, NumDungeons, RegionFlags);
  fprintf (pFileHandle, "\tOffsets: PItem=0x%08lX, DItem=0x%08lX, Table=0x%08lX, Names=0x%08lX\n", MapPItemOffset, MapDItemOffset, MapTableOffset, MapNamesOffset);
  fprintf (pFileHandle, "\tLocation Data...\n");

  if (RegionFlags == 0) {
    fprintf (pFileHandle, "\t\tNot loaded!\n");
    fflush (pFileHandle);
    return;
   }

	/* Output Location information */
  for (LoopCounter = 0; LoopCounter < NumLocations; LoopCounter++) {

		/* Output map name if loaded */
    if ((RegionFlags & DFMAP_REGION_NAMES) && (DumpFlags & DFMAP_DUMP_MAPNAMES))
      fprintf (pFileHandle, "\t\tName: '%s'\n", pMapNames[LoopCounter].Name);
    else 
      fprintf (pFileHandle, "\t\tBegin Location:\n");

		/* Output pItems if loaded */
    if ((RegionFlags & DFMAP_REGION_PITEM))
      pPItemRecords[LoopCounter].Dump(pFileHandle, DumpFlags);
    else 
      fprintf (pFileHandle, "\t\tMapPItem: Not loaded!\n");

		/* Output table if loaded */
    if ((RegionFlags & DFMAP_REGION_TABLE))
      pMapTables[LoopCounter].Dump(pFileHandle, DumpFlags);
    else 
      fprintf (pFileHandle, "\t\tMapTable: Not loaded!\n");
   }
	
	/* Output Dungeon information */
  fprintf (pFileHandle, "\tDungeon Data...\n");

  if (!(RegionFlags & DFMAP_REGION_DITEM)) {
    fprintf (pFileHandle, "\t\tMapDItem: Not loaded!\n");
    fflush (pFileHandle);
    return;
   }

  for (LoopCounter = 0; LoopCounter < NumDungeons; LoopCounter++) {
    pDItemRecords[LoopCounter].Dump(pFileHandle, DumpFlags);
   }

  fflush (pFileHandle);
 }
/*===========================================================================
 *		End of Class Method CDFMapRegion::Dump()
 *=========================================================================*/


#undef  __FUNC__
#define __FUNC__ "CDFMapRegion::FindLocation()"
/*===========================================================================
 *
 * Class CDFMapRegion Method - boolean FindLocation (PixelX, PixelY, RegionIndex, LocationIndex);
 *
 * Attempts to find a location in the region matching the given land
 * pixel coordinates. Returns TRUE on success and sets the region and
 * location indices.  Use the fact that the maptable is sorted by Y-position
 * to help speed the search.
 *
 *=========================================================================*/
boolean CDFMapRegion::FindLocation (const int PixelX, const int PixelY, int& RegionIndex, int& LocationIndex) {
  int LoopCounter;
  int MapPixelY;
  int MapPixelX;

	/* Check each location */
  for (LoopCounter = 0; LoopCounter < NumLocations; LoopCounter++) {

		/* Convert maptable coordinates to pixel coordinates */
    MapPixelX = pMapTables[LoopCounter].GetXPosition()/128;
    MapPixelY = DFWOODS_MAP_HEIGHT - 1 -  pMapTables[LoopCounter].GetYPosition()/128;

		/* Do we have a match yet? */
    if (MapPixelX == PixelX && MapPixelY == PixelY) {
      RegionIndex = RegionNumber;
      LocationIndex = LoopCounter;
      SystemLog.Printf ("Found location at pixel (%d, %d), %d in region %d (%s).", PixelX, PixelY,LocationIndex, RegionIndex, pMapNames[LocationIndex].Name);
      return (TRUE);
     }
   }

	/* No match found */
  return (FALSE);
 }
/*===========================================================================
 *		End of Class Method CDFMapRegion::FindLocation()
 *=========================================================================*/


#undef  __FUNC__
#define __FUNC__ "CDFMapRegion::GetMapPItem()"
/*===========================================================================
 *
 * Class CDFMapRegion Method - CDFMapPItemRecord* GetMapPItem (Location);
 *
 * Attempt to return the given PItem data for the location.  Returns NULL
 * on any error.
 *
 *=========================================================================*/
CDFMapPItemRecord* CDFMapRegion::GetMapPItem (const int LocationIndex) {

	/* Ensure a valid location index */
  if (!IsValidLocation(LocationIndex) || pPItemRecords == NULL) {
    SET_EXT_ERROR3(ERR_INDEX, "Invalid location index %d specified!", LocationIndex);
    return (NULL);
   }

  return (&pPItemRecords[LocationIndex]);
 }
/*===========================================================================
 *		End of Class Method CDFMapRegion::GetMapPItem()
 *=========================================================================*/


#undef  __FUNC__
#define __FUNC__ "CDFMapRegion::GetMapDtem()"
/*===========================================================================
 *
 * Class CDFMapRegion Method - CDFMapDItemRecord* GetMapDItem (Location);
 *
 * Attempt to return the given DItem data for the location.  Returns NULL
 * on any error.
 *
 *=========================================================================*/
CDFMapDItemRecord* CDFMapRegion::GetMapDItem (const int LocationIndex) {

	/* Ensure a valid location index */
  if (!IsValidLocation(LocationIndex) || pDItemRecords == NULL) {
    SET_EXT_ERROR3(ERR_INDEX, "Invalid location index %d specified!", LocationIndex);
    return (NULL);
   }

  return (&pDItemRecords[LocationIndex]);
 }
/*===========================================================================
 *		End of Class Method CDFMapRegion::GetMapDItem()
 *=========================================================================*/


#undef  __FUNC__
#define __FUNC__ "CDFMapRegion::GetMapTable()"
/*===========================================================================
 *
 * Class CDFMapRegion Method - CDFMapTableRecord* GetMapTable (Location);
 *
 * Attempt to return the given table data for the location.  Returns NULL
 * on any error.
 *
 *=========================================================================*/
CDFMapTableRecord* CDFMapRegion::GetMapTable (const int LocationIndex) {

	/* Ensure a valid location index */
  if (!IsValidLocation(LocationIndex) || pMapTables == NULL) {
    SET_EXT_ERROR3(ERR_INDEX, "Invalid location index %d specified!", LocationIndex);
    return (NULL);
   }

  return (&pMapTables[LocationIndex]);
 }
/*===========================================================================
 *		End of Class Method CDFMapRegion::GetMapTable()
 *=========================================================================*/


#undef  __FUNC__
#define __FUNC__ "CDFMapRegion::GetMapName()"
/*===========================================================================
 *
 * Class CDFMapRegion Method - char* GetMapName (Location);
 *
 * Attempt to return the given map name for the location.  Returns NULL
 * on any error.
 *
 *=========================================================================*/
char* CDFMapRegion::GetMapName (const int LocationIndex) {

	/* Ensure a valid location index */
  if (!IsValidLocation(LocationIndex) || pMapNames == NULL) {
    SET_EXT_ERROR3(ERR_INDEX, "CDFMapRegion::GetMapName() - Invalid location index %d specified!", LocationIndex);
    return (NULL);
   }

  return (pMapNames[LocationIndex].Name);
 }
/*===========================================================================
 *		End of Class Method CDFMapRegion::GetMapName()
 *=========================================================================*/


#undef  __FUNC__
#define __FUNC__ "CDFMapRegion::Read()"
/*===========================================================================
 *
 * Class CDFMapRegion Method - boolean Read (pFileHandle, Flags);
 *
 * Attempts to read in the data for the region as specified in the
 * flags parameter.  Returns FALSE on any error.
 *
 *=========================================================================*/
boolean CDFMapRegion::Read (FILE* pFileHandle, const dfmap_regionflags_t Flags) {
  boolean Result;

	/* Ignore if the given components are already read */
  if ((Flags & RegionFlags) == Flags) return (TRUE);

	/* Ensure valid input */
  if (pFileHandle == NULL) {
    SET_EXT_ERROR2(ERR_NULL, "Invalid NULL file handle received!");
    return (FALSE);
   }

	/* Read in the number of locations if required */
  if (!(RegionFlags & DFMAP_REGION_NUMLOCATIONS)) {
    Result = ReadNumLocations(pFileHandle);
    if (!Result) return (FALSE);
   }

	/* Read in the number of dungeons if required */
  if (!(RegionFlags & DFMAP_REGION_NUMDUNGEONS)) {
    Result = ReadNumDungeons(pFileHandle);
    if (!Result) return (FALSE);
   }

	/* Read the PItem offset list if required */
  if (((Flags & DFMAP_REGION_PITEM) || (Flags & DFMAP_REGION_POFFSET)) && !(RegionFlags & DFMAP_REGION_POFFSET)) {
    Result = ReadPItemOffsets(pFileHandle);
    if (!Result) return (FALSE);
   }

	/* Read the DItem offset list if required */
  if (((Flags & DFMAP_REGION_DITEM) || (Flags & DFMAP_REGION_DOFFSET)) && !(RegionFlags & DFMAP_REGION_DOFFSET) ) {
    Result = ReadDItemOffsets(pFileHandle);
    if (!Result) return (FALSE);
   }

	/* Read the PItem records if required */
  if ((Flags & DFMAP_REGION_PITEM) && !(RegionFlags & DFMAP_REGION_PITEM)) {
    Result = ReadPItemRecords(pFileHandle);
    if (!Result) return (FALSE);
   }

	/* Read the PItem records if required */
  if ((Flags & DFMAP_REGION_DITEM) && !(RegionFlags & DFMAP_REGION_DITEM)) {
    Result = ReadDItemRecords(pFileHandle);
    if (!Result) return (FALSE);
   }
  	
	/* Read the Maptable records if required */
  if ((Flags & DFMAP_REGION_TABLE) && !(RegionFlags & DFMAP_REGION_TABLE)) {
    Result = ReadMapTableRecords(pFileHandle);
    if (!Result) return (FALSE);
   }

	/* Read the Maptable records if required */
  if ((Flags & DFMAP_REGION_NAMES) && !(RegionFlags & DFMAP_REGION_NAMES)) {
    Result = ReadMapNamesRecords(pFileHandle);
    if (!Result) return (FALSE);
   }

  return (Result);
 }
/*===========================================================================
 *		End of Class Method CDFMapRegion::Read()
 *========================================================================*/


#undef  __FUNC__
#define __FUNC__ "CDFMapRegion::ReadNumLocations()"
/*===========================================================================
 *
 * Class CDFMapRegion Method - boolean ReadNumLocations (pFileHandle);
 *
 * Attempts to read in the number of locations in the region.
 * Returns FALSE on any error.  Protected class method.
 *
 *=========================================================================*/
boolean CDFMapRegion::ReadNumLocations (FILE* pFileHandle) {
  int Result;

	/* Move to the begining of the map names data */
  Result = fseek (pFileHandle, MapNamesOffset, SEEK_SET);

  if (Result < 0) {
    SET_EXT_ERROR2(ERR_READ, "Failed to move file position to MapNames data!");
    return (FALSE);
   }

	/* Read in the number of locations */
  clearerr(pFileHandle);
  NumLocations = read_long(pFileHandle);
  
  if (ferror(pFileHandle) || feof(pFileHandle) || NumLocations < 0) {
    SET_EXT_ERROR2(ERR_READ, "Failed to read the number of region locations!");
    NumLocations = 0;
    return (FALSE);
   }

	/* Do optional statistics */
  #ifdef DOSTATS
    DO_STAT_REC2(TotalLocations, NumLocations)
    TotalLocationsTotalCount += NumLocations - 1; 
  #endif

	/* Flag that this has been read */
  RegionFlags |= DFMAP_REGION_NUMLOCATIONS;
  return (TRUE);
 }
/*===========================================================================
 *		End of Class Method CDFMapRegion::ReadNumLocations()
 *=========================================================================*/


#undef  __FUNC__
#define __FUNC__ "CDFMapRegion::ReadNumDungeons()"
/*===========================================================================
 *
 * Class CDFMapRegion Method - boolean ReadNumDungeons (pFileHandle);
 *
 * Attempts to read in the number of dungeons in the region.
 * Returns FALSE on any error.  Protected class method.
 *
 *=========================================================================*/
boolean CDFMapRegion::ReadNumDungeons (FILE* pFileHandle) {
  int Result;

	/* Move to the begining of the mapditem data */
  Result = fseek (pFileHandle, MapDItemOffset, SEEK_SET);

  if (Result < 0) {
    SET_EXT_ERROR2(ERR_READ, "Failed to move file position to MapDItem data!");
    return (FALSE);
   }

	/* Read in the number of dungeons */
  clearerr(pFileHandle);
  NumDungeons = read_long(pFileHandle);
  
  if (ferror(pFileHandle) || feof(pFileHandle) || NumDungeons < 0) {
    SET_EXT_ERROR2(ERR_READ, "Failed to read the number of region dungeons!");
    NumLocations = 0;
    return (FALSE);
   }

	/* Do optional statistics */
  #ifdef DOSTATS
    DO_STAT_REC2(TotalDungeons, NumDungeons)
    TotalDungeonsTotalCount += NumDungeons - 1; 
  #endif

  	/* Flag that this has been read */
  RegionFlags |= DFMAP_REGION_NUMDUNGEONS;
  return (TRUE);
 }
/*===========================================================================
 *		End of Class Method CDFMapRegion::ReadNumDungeons()
 *=========================================================================*/


#undef  __FUNC__
#define __FUNC__ "CDFMapRegion::ReadPItemOffsets()"
/*===========================================================================
 *
 * Class CDFMapRegion Method - boolean ReadPItemOffsets (pFileHandle);
 *
 * Attempts to read in the offset list to the pitem data.
 * Returns FALSE on any error.  Protected class method.
 *
 *=========================================================================*/
boolean CDFMapRegion::ReadPItemOffsets (FILE* pFileHandle) {
  int Result;

	/* Destroy and Reallocate the offset array */
  DestroyPointerArray(pPItemOffsets);

  if (NumLocations > 0) {
    CreatePointerArray(pPItemOffsets, dfmap_pitem_offset_t, NumLocations);
   }

	/* Move to the begining of the pitem data */
  Result = fseek (pFileHandle, MapPItemOffset, SEEK_SET);

  if (Result < 0) {
    SET_EXT_ERROR2(ERR_READ, "Failed to move file position to MapPItem data!");
    return (FALSE);
   }

	/* Read in the data all at once */
  Result = fread (pPItemOffsets, sizeof(dfmap_pitem_offset_t), NumLocations, pFileHandle);

  if (Result != NumLocations) {
    SET_EXT_ERROR2(ERR_READ, "Failed to read the MapPItem record offset list!");
    return (FALSE);
   }

	/* Flag that this has been read */
  RegionFlags |= DFMAP_REGION_POFFSET;
  return (TRUE);
 }
/*===========================================================================
 *		End of Class Method CDFMapRegion::ReadPItemOffsets()
 *=========================================================================*/


#undef  __FUNC__
#define __FUNC__ "CDFMapRegion::ReadPItemRecords()"
/*===========================================================================
 *
 * Class CDFMapRegion Method - boolean ReadPItemRecords (pFileHandle);
 *
 * Attempts to read in the records of the pitem data.
 * Returns FALSE on any error.  Protected class method.
 *
 *=========================================================================*/
boolean CDFMapRegion::ReadPItemRecords (FILE* pFileHandle) {
  int  Result;
  int  LoopCounter;
  long StartOffset;

	/* Destroy and Reallocate the records array */
  DestroyPointerArray(pPItemRecords);

  if (NumLocations > 0) {
    CreatePointerArray(pPItemRecords, CDFMapPItemRecord, NumLocations);
   }

	/* Compute first record offset */
  StartOffset = MapPItemOffset + NumLocations * sizeof(dfmap_pitem_offset_t);

	/* Read all the PItem records */
  for (LoopCounter = 0; LoopCounter < NumLocations; LoopCounter++) {

		/* Move position to start of record data */
    Result = fseek (pFileHandle, StartOffset + pPItemOffsets[LoopCounter], SEEK_SET);

    if (Result < 0) {
      SET_EXT_ERROR3(ERR_READ, "Failed to move file position to MapPItem record %d!", LoopCounter);
      return (FALSE);
     }

  	/* Set the record size */
    if (LoopCounter == NumLocations - 1)
      pPItemRecords[LoopCounter].SetRecordSize(MapDItemOffset - StartOffset - pPItemOffsets[LoopCounter]);
    else
      pPItemRecords[LoopCounter].SetRecordSize(pPItemOffsets[LoopCounter+1] - pPItemOffsets[LoopCounter]);

		/* Attempt to read in the record */
    Result = pPItemRecords[LoopCounter].Read(pFileHandle);
    if (!Result) return (FALSE);
   }

	/* Flag that this has been read */
  RegionFlags |= DFMAP_REGION_PITEM;
  return (TRUE);
 }
/*===========================================================================
 *		End of Class Method CDFMapRegion::ReadPItemRecords()
 *=========================================================================*/


#undef  __FUNC__
#define __FUNC__ "CDFMapRegion::ReadDItemOffsets()"
/*===========================================================================
 *
 * Class CDFMapRegion Method - boolean ReadDItemOffsets (pFileHandle);
 *
 * Attempts to read in the offset list to the Ditem data.
 * Returns FALSE on any error.  Protected class method.
 *
 *=========================================================================*/
boolean CDFMapRegion::ReadDItemOffsets (FILE* pFileHandle) {
  int Result;

	/* Destroy and Reallocate the offset array */
  DestroyPointerArray(pDItemOffsets);

  if (NumDungeons > 0) {
    CreatePointerArray(pDItemOffsets, dfmap_ditem_offset_t, NumDungeons);
   }

	/* Move to the begining of the ditem data, skipping number of dungeons which
	 * has been previously read */
  Result = fseek (pFileHandle, MapDItemOffset+4, SEEK_SET);

  if (Result < 0) {
    SET_EXT_ERROR2(ERR_READ, "Failed to move file position to MapDItem data!");
    return (FALSE);
   }

	/* Read in the data all at once */
  Result = fread (pDItemOffsets, sizeof(dfmap_ditem_offset_t), NumDungeons, pFileHandle);

  if (Result != NumDungeons) {
    SET_EXT_ERROR2(ERR_READ, "Failed to read the MapDItem record offset list!");
    return (FALSE);
   }

	/* Flag that this has been read */
  RegionFlags |= DFMAP_REGION_DOFFSET;
  return (TRUE);
 }
/*===========================================================================
 *		End of Class Method CDFMapRegion::ReadDItemOffsets()
 *=========================================================================*/


#undef  __FUNC__
#define __FUNC__ "CDFMapRegion::ReadDItemRecords()"
/*===========================================================================
 *
 * Class CDFMapRegion Method - boolean ReadDItemRecords (pFileHandle);
 *
 * Attempts to read in the records of the DItem data.
 * Returns FALSE on any error.  Protected class method.
 *
 *=========================================================================*/
boolean CDFMapRegion::ReadDItemRecords (FILE* pFileHandle) {
  int  Result;
  int  LoopCounter;
  long StartOffset;

	/* Destroy and Reallocate the records array */
  DestroyPointerArray(pDItemRecords);

  if (NumDungeons > 0) {
    CreatePointerArray(pDItemRecords, CDFMapDItemRecord, NumDungeons);
   }

	/* Compute first record offset */
  StartOffset = MapDItemOffset + 4 + NumDungeons * sizeof(dfmap_ditem_offset_t);

	/* Read all the DItem records */
  for (LoopCounter = 0; LoopCounter < NumDungeons; LoopCounter++) {

		/* Move position to start of record data */
    Result = fseek (pFileHandle, StartOffset + pDItemOffsets[LoopCounter].Offset, SEEK_SET);

    if (Result < 0) {
      SET_EXT_ERROR3(ERR_READ, "Failed to move file position to MapDItem record %d!", LoopCounter);
      return (FALSE);
     }

	     /* Set the record size */
    if (LoopCounter == NumDungeons - 1)
      pDItemRecords[LoopCounter].SetRecordSize(MapTableOffset - StartOffset - pDItemOffsets[LoopCounter].Offset);
    else
      pDItemRecords[LoopCounter].SetRecordSize(pDItemOffsets[LoopCounter+1].Offset - pDItemOffsets[LoopCounter].Offset);

		/* Attempt to read in the record */
    Result = pDItemRecords[LoopCounter].Read(pFileHandle);
    if (!Result) return (FALSE);
   }

	/* Flag that this has been read */
  RegionFlags |= DFMAP_REGION_DITEM;
  return (TRUE);
 }
/*===========================================================================
 *		End of Class Method CDFMapRegion::ReadDItemRecords()
 *=========================================================================*/


#undef  __FUNC__
#define __FUNC__ "CDFMapRegion::ReadMapTableRecords()"
/*===========================================================================
 *
 * Class CDFMapRegion Method - boolean ReadMapTableRecords (pFileHandle);
 *
 * Attempts to read in the records of the maptable data.
 * Returns FALSE on any error.  Protected class method.
 *
 *=========================================================================*/
boolean CDFMapRegion::ReadMapTableRecords (FILE* pFileHandle) {
  int  Result;
  int  LoopCounter;
  
	/* Destroy and Reallocate the records array */
  DestroyPointerArray(pMapTables);
  CreatePointerArray(pMapTables, CDFMapTableRecord, NumLocations);

	/* Move position to start of maptable data */
  Result = fseek (pFileHandle, MapTableOffset, SEEK_SET);

  if (Result < 0) {
    SET_EXT_ERROR2(ERR_READ, "Failed to move file position to MapTable data!");
    return (FALSE);
   }

	/* Read all the MapTable records */
  for (LoopCounter = 0; LoopCounter < NumLocations; LoopCounter++) {

		/* Attempt to read in the record */
    Result = pMapTables[LoopCounter].Read(pFileHandle);
    if (!Result) return (FALSE);
   }

	/* Flag that this has been read */
  RegionFlags |= DFMAP_REGION_TABLE;
  return (TRUE);
 }
/*===========================================================================
 *		End of Class Method CDFMapRegion::ReadMapTableRecords()
 *=========================================================================*/


#undef  __FUNC__
#define __FUNC__ "CDFMapRegion::ReadMapNamesRecords()"
/*===========================================================================
 *
 * Class CDFMapRegion Method - boolean ReadMapNamesRecords (pFileHandle);
 *
 * Attempts to read in the records of the maptable data.
 * Returns FALSE on any error.  Protected class method.
 *
 *=========================================================================*/
boolean CDFMapRegion::ReadMapNamesRecords (FILE* pFileHandle) {
  int  Result;
    
	/* Destroy and Reallocate the records array */
  DestroyPointerArray(pMapNames);
  CreatePointerArray(pMapNames, dfmap_name_t, NumLocations);

	/* Move position to start of mapnames data */
  Result = fseek (pFileHandle, MapNamesOffset + 4, SEEK_SET);

  if (Result < 0) {
    SET_EXT_ERROR2(ERR_READ, "Failed to move file position to MapNames data!");
    return (FALSE);
   }

	/* Read all the MapName records all at once */
  Result = fread (pMapNames, sizeof(dfmap_name_t), NumLocations, pFileHandle);

  if (Result != NumLocations) {
    SET_EXT_ERROR2(ERR_READ, "Failed to read MapNames data!");
    return (FALSE);
   }
  
	/* Flag that this has been read */
  RegionFlags |= DFMAP_REGION_NAMES;
  return (TRUE);
 }
/*===========================================================================
 *		End of Class Method CDFMapRegion::ReadMapNamesRecords()
 *=========================================================================*/


#undef  __FUNC__
#define __FUNC__ "CDFMapsFile::CDFMapsFile()"
/*===========================================================================
 *
 * Class CDFMapsFile Constructor
 *
 *=========================================================================*/
CDFMapsFile::CDFMapsFile() {
  SetFilename("arena2\\maps.bsa");
 }
/*===========================================================================
 *		End of Class CDFMapsFile Constructor
 *=========================================================================*/


#undef  __FUNC__
#define __FUNC__ "CDFMapsFile::Destructor()"
/*===========================================================================
 *
 * Class CDFMapsFile Destructor
 *
 *=========================================================================*/
void CDFMapsFile::Destroy (void) {
  int LoopCounter;

	/* Destroy each region's data */
  for (LoopCounter = 0; LoopCounter < DFMAP_MAX_REGIONS; LoopCounter++) {
    Regions[LoopCounter].Destroy();
   }

 }
/*===========================================================================
 *		End of Class CDFMapsFile Destructor
 *=========================================================================*/


#undef  __FUNC__
#define __FUNC__ "CDFMapsFile::Dump()"
/*===========================================================================
 *
 * Class CDFMapsFile Method - void Dump (pFileHandle, DumpFlags);
 *
 * Output object info to a file stream.
 *
 *=========================================================================*/
void CDFMapsFile::Dump (FILE* pFileHandle, const dfmap_dumpflags_t DumpFlags) {
  int LoopCounter;

	/* Ensure valid input */
  if (pFileHandle == NULL) { 
    SET_EXT_ERROR2(ERR_NULL, "Invalid NULL file handle received!");
    return;
   }

	/* Output base object information */
  CDFBSAFile::Dump(pFileHandle);

	/* Output region dump information if required */
  if ((DumpFlags & DFMAP_DUMP_REGION) == 0) return;

  for (LoopCounter = 0; LoopCounter < DFMAP_MAX_REGIONS; LoopCounter++) {
    fprintf (pFileHandle, "Region (%d), %s\n", LoopCounter, DFRegionNames[LoopCounter]);
    Regions[LoopCounter].Dump(pFileHandle, DumpFlags);
   }

  fflush (pFileHandle);
 }
/*===========================================================================
 *		End of Class Method CDFMapsFile::Dump()
 *=========================================================================*/


#undef  __FUNC__
#define __FUNC__ "CDFMapsFile::FindLandPixel()"
/*===========================================================================
 *
 * Class CDFMapsFile Method - boolean FindLandPixel (PixelX, PixelY, RegionIndex, LocationIndex);
 *
 * Searches for a location in the given landscape pixel.  On success returns
 * TRUE and sets the region and location indices.  On any error returns FALSE.
 *
 *=========================================================================*/
boolean CDFMapsFile::FindLandPixel (const int PixelX, const int PixelY, int& RegionIndex, int& LocationIndex) {
  int     LoopCounter;
  boolean Result;

	/* Ensure valid coordinates */
  if (PixelX < 0 || PixelY < 0 || PixelX >= DFWOODS_MAP_WIDTH || PixelY >= DFWOODS_MAP_HEIGHT) {
    return (FALSE);
   }

	/* Look for locations in all regions */
  for (LoopCounter = 0; LoopCounter < DFMAP_MAX_REGIONS; LoopCounter++) {
    Result = Regions[LoopCounter].FindLocation (PixelX, PixelY, RegionIndex, LocationIndex);
    if (Result) {
      return (TRUE);
     }
   }

	/* No locations found */
  return (FALSE);
 }
/*===========================================================================
 *		End of Class Method CDFMapsFile::FindLandPixel()
 *=========================================================================*/


#undef  __FUNC__
#define __FUNC__ "CDFMapsFile::GetMapPItem()"
/*===========================================================================
 *
 * Class CDFMapsFile Method - CDFMapPItemRecord* GetMapPItem (Region, Location);
 *
 * Attempt to return the given PItem data for the location.  Returns NULL
 * on any error.
 *
 *=========================================================================*/
CDFMapPItemRecord* CDFMapsFile::GetMapPItem (const int RegionIndex, const int LocationIndex) {
  boolean Result;

	/* Ensure a valid region index */
  if (!IsValidRegion(RegionIndex)) {
    SET_EXT_ERROR3(ERR_INDEX, "Invalid region index %d specified!", RegionIndex);
    return (NULL);
   }

	/* Load the region data if required */
  if (!Regions[RegionIndex].IsLoaded(DFMAP_REGION_PITEM)) {
    Result = ReadRegion(RegionIndex, DFMAP_REGION_PITEM);
    if (!Result) return (NULL);
   }

  return Regions[RegionIndex].GetMapPItem(LocationIndex);
 }
/*===========================================================================
 *		End of Class Method CDFMapsFile::GetMapPItem()
 *=========================================================================*/


#undef  __FUNC__
#define __FUNC__ "CDFMapsFile::GetMapPItem()"
/*===========================================================================
 *
 * Class CDFMapsFile Method - CDFMapDItemRecord* GetMapPItem (Region, Location);
 *
 * Attempt to return the given DItem data for the location.  Returns NULL
 * on any error.
 *
 *=========================================================================*/
CDFMapDItemRecord* CDFMapsFile::GetMapDItem (const int RegionIndex, const int LocationIndex) {
  boolean Result;

	/* Ensure a valid region index */
  if (!IsValidRegion(RegionIndex)) {
    SET_EXT_ERROR3(ERR_INDEX, "Invalid region index %d specified!", RegionIndex);
    return (NULL);
   }

	/* Load the region data if required */
  if (!Regions[RegionIndex].IsLoaded(DFMAP_REGION_DITEM)) {
    Result = ReadRegion(RegionIndex, DFMAP_REGION_DITEM);
    if (!Result) return (NULL);
   }


  return Regions[RegionIndex].GetMapDItem(LocationIndex);
 }
/*===========================================================================
 *		End of Class Method CDFMapsFile::GetMapDItem()
 *=========================================================================*/


#undef  __FUNC__
#define __FUNC__ "CDFMapsFile::GetMapTable"
/*===========================================================================
 *
 * Class CDFMapsFile Method - CDFMapPItemRecord* GetMapTable (Region, Location);
 *
 * Attempt to return the given table data for the location.  Returns NULL
 * on any error.
 *
 *=========================================================================*/
CDFMapTableRecord* CDFMapsFile::GetMapTable (const int RegionIndex, const int LocationIndex) {
  boolean Result;

	/* Ensure a valid region index */
  if (!IsValidRegion(RegionIndex)) {
    SET_EXT_ERROR3(ERR_INDEX, "CDFMapsFile::GetMapTable() - Invalid region index %d specified!", RegionIndex);
    return (NULL);
   }

	/* Load the region data if required */
  if (!Regions[RegionIndex].IsLoaded(DFMAP_REGION_TABLE)) {
    Result = ReadRegion(RegionIndex, DFMAP_REGION_PITEM);
    if (!Result) return (NULL);
   }

  return Regions[RegionIndex].GetMapTable(LocationIndex);
 }
/*===========================================================================
 *		End of Class Method CDFMapsFile::GetMapTable()
 *=========================================================================*/



#undef  __FUNC__
#define __FUNC__ "CDFMapsFile::GetMapName()"
/*===========================================================================
 *
 * Class CDFMapsFile Method - char* GetMapName (Region, Location);
 *
 * Attempt to return the given map name for the location.  Returns NULL
 * on any error.
 *
 *=========================================================================*/
char* CDFMapsFile::GetMapName (const int RegionIndex, const int LocationIndex) {
  boolean Result;

	/* Ensure a valid region index */
  if (!IsValidRegion(RegionIndex)) {
    SET_EXT_ERROR3(ERR_INDEX, "Invalid region index %d specified!", RegionIndex);
    return (NULL);
   }

	/* Load the region data if required */
  if (!Regions[RegionIndex].IsLoaded(DFMAP_REGION_NAMES)) {
    Result = ReadRegion(RegionIndex, DFMAP_REGION_PITEM);
    if (!Result) return (NULL);
   }

  return Regions[RegionIndex].GetMapName(LocationIndex);
 }
/*===========================================================================
 *		End of Class Method CDFMapsFile::GetMapName()
 *=========================================================================*/

 
  
#undef  __FUNC__
#define __FUNC__ "CDFMapsFile::ReadDirectory()"
/*===========================================================================
 *
 * Class CDFMapsFile Method - boolean ReadDirectory ();
 *
 * Virtual function to ensure the region offsets are set after each 
 * directory read.  Protected class method.
 *
 *=========================================================================*/
boolean CDFMapsFile::ReadDirectory (void) {
  boolean Result;

	/* Call the base class method */
  Result = CDFBSAFile::ReadDirectory();
  if (!Result) return (FALSE);

	/* Update the offset list */
  SetRegionOffsets();
  return (TRUE);
 }
/*===========================================================================
 *		End of Class Method CDFMapsFile::ReadDirectory()
 *=========================================================================*/



#undef  __FUNC__
#define __FUNC__ "CDFMapsFile::ReadRegion()"
/*===========================================================================
 *
 * Class CDFMapsFile Method - boolean ReadRegion (RegionIndex, Flags);
 *
 * Attempts to read in the data for the given region as specified in the
 * flags parameter.  Returns FALSE on any error.
 *
 *=========================================================================*/
boolean CDFMapsFile::ReadRegion (const int RegionIndex, const dfmap_regionflags_t Flags) {
  boolean HadToOpen = FALSE;
  boolean Result;

  	/* Ensure a valid region index */
  if (!IsValidRegion(RegionIndex)) {
    SET_EXT_ERROR3(ERR_INDEX, "Invalid region index %d!", RegionIndex);
    return (FALSE);
   }

	/* Ensure file is currently open */
  if (!IsOpen()) { 
    Result = Open();
    if (!Result) return (FALSE);
    HadToOpen = TRUE;
   }

	/* Initialize statistics if required */
  #ifdef DFMAP_DOSTATS
    static boolean DoStatsInit = FALSE;

    if (!DoStatsInit) {
      INIT_STAT_ARR(PItemPreRec, 6)
      INIT_STAT_ARR(DItemPreRec, 6)
      INIT_STAT_ARR(PItemPostNulls, 16)
      INIT_STAT_ARR(DItemPostUnknowns, 4)
      INIT_STAT_ARR(PItemNulls, 380)
      INIT_STAT_CNT(DItemPostUn2)
      INIT_STAT_CNT(DItemPostUn3)
      INIT_STAT_CNT(DItemPostUn4)
      INIT_STAT_CNT(PItemBlock1)
      INIT_STAT_CNT(PItemBlock2)
      INIT_STAT_CNT(PItemBlock3)
      DoStatsInit = TRUE;
     }
  #endif

	/* Read the region data */
  Result = Regions[RegionIndex].Read(pFileHandle, Flags);
	
	/* Close the file only if we had to open it */
  if (HadToOpen) Close();
  return (Result);
 }
/*===========================================================================
 *		End of Class Method CDFMapsFile::ReadRegion()
 *=========================================================================*/


#undef  __FUNC__
#define __FUNC__ "CDFMapsFile::Read()"
/*===========================================================================
 *
 * Class CDFMapsFile Method - boolean Read (Flags);
 *
 * Attempts to read in the data for all regions as specified in the
 * flags parameter.  Returns FALSE on any error.
 *
 *=========================================================================*/
boolean CDFMapsFile::Read (const dfmap_regionflags_t Flags) {
  boolean HadToOpen = FALSE;
  boolean Result;
  int     LoopCounter;

	/* Ensure file is currently open */
  if (!IsOpen()) { 
    Result = Open();
    if (!Result) return (FALSE);
    HadToOpen = TRUE;
   }

	/* Read the region data */
  for (LoopCounter = 0; LoopCounter < DFMAP_MAX_REGIONS; LoopCounter++) {
    Result = Regions[LoopCounter].Read(pFileHandle, Flags);
    if (!Result) break;
   }
	
	/* Close the file only if we had to open it */
  if (HadToOpen) Close();
  return (Result);
 }
/*===========================================================================
 *		End of Class Method CDFMapsFile::Read()
 *=========================================================================*/




#undef  __FUNC__
#define __FUNC__ "CDFMapsFile::SetRegionOffsets()"
/*===========================================================================
 *
 * Class CDFMapsFile Method - void SetRegionOffsets (void);
 *
 * Set the region offsets from the BSA directory.
 *
 *=========================================================================*/
void CDFMapsFile::SetRegionOffsets (void) {
  int LoopCounter;
  int RecordCounter;
  
	/* Set offsets for all regions or region directories, whichever is less */
  for (LoopCounter = 0, RecordCounter = 0; 
       LoopCounter < DFMAP_MAX_REGIONS && RecordCounter+3 < NumRecords;
       LoopCounter++) {
    Regions[LoopCounter].SetMapPItemOffset(pDirectory[RecordCounter++]->RecordOffset);
    Regions[LoopCounter].SetMapDItemOffset(pDirectory[RecordCounter++]->RecordOffset);
    Regions[LoopCounter].SetMapTableOffset(pDirectory[RecordCounter++]->RecordOffset);
    Regions[LoopCounter].SetMapNamesOffset(pDirectory[RecordCounter++]->RecordOffset);
    Regions[LoopCounter].SetRegionNumber(LoopCounter);
   }

 }
/*===========================================================================
 *		End of Class Method CDFMapsFile::SetRegionOffsets()
 *=========================================================================*/


#ifdef DOSTATS


#undef  __FUNC__
#define __FUNC__ "OutputStats()"
/*===========================================================================
 *
 * Function - void OutputStats (void);
 *
 * Outputs the current statistics to the system log file.
 *
 *=========================================================================*/
void OutputStats (void) {
  OUT_STAT_REC(TotalLocations)
  OUT_STAT_REC(TotalDungeons)
  OUT_STAT_REC(PItemNumPreRec)
  OUT_STAT_REC(DItemNumPreRec)
  OUT_STAT_REC(PItemNumPostRec)
  OUT_STAT_REC(DItemNumPostRec)
  OUT_STAT_REC(NumDunPostRec)
  OUT_STAT_VAR(PItemXPos)
  OUT_STAT_VAR(DItemYPos)
  OUT_STAT_VAR(PItemUnknown1)
  OUT_STAT_VAR(PItemUnknown2)
  OUT_STAT_VAR(PItemUnknown3)
  OUT_STAT_VAR(PItemUnknown4)
  OUT_STAT_VAR(PItemUnknown5)
  OUT_STAT_VAR(PItemUnknown6)
  OUT_STAT_VAR(DItemUnknown1)
  OUT_STAT_VAR(DItemUnknown2)
  OUT_STAT_VAR(DItemUnknown3)
  OUT_STAT_VAR(DItemUnknown4)
  OUT_STAT_VAR(DItemUnknown5)
  OUT_STAT_VAR(DItemUnknown6)
  OUT_STAT_VAR(DItemUnknown7)
  OUT_STAT_VAR(DItemUnknown8)
  OUT_STAT_VAR(DItemUnknown9)
  OUT_STAT_VAR(DItemUnknown10)
  OUT_STAT_ARR(PItemPreRec, 6)
  OUT_STAT_ARR(DItemPreRec, 6)
  OUT_STAT_VAR(PItemHouseName)
  OUT_STAT_VAR(PItemHouseType)
  OUT_STAT_ARR(PItemPostNulls, 16)
  OUT_STAT_VAR(PItemPostU1)
  OUT_STAT_VAR(PItemPostU2)
  OUT_STAT_VAR(PItemPostU3)
  OUT_STAT_ARR(PItemNulls, 380)
  OUT_STAT_ARR(DItemPostUnknowns, 4)
  OUT_STAT_CNT(DItemPostUn2)
  OUT_STAT_CNT(DItemPostUn3)
  OUT_STAT_CNT(DItemPostUn4)
  OUT_STAT_CNT(PItemBlock1)
  OUT_STAT_CNT(PItemBlock2)
  OUT_STAT_CNT(PItemBlock3)
 }
/*===========================================================================
 *		End of Function OutputStats()
 *========================================================================*/
#endif