/*===========================================================================
 *
 * File:	Dfcommon.CPP
 * Author:	Dave Humphrey (uesp@m0use.net)
 * Created On:	Monday, June 25, 2001
 *
 * Implements commonly used Daggerfall routines and data.
 *
 *=========================================================================*/
	
	/* Include files */
#include "uesp/dagger/common/dfcommon.h"
#include "dl_file.h"


/*===========================================================================
 *
 * Begin Local Variable Definitions
 *
 *=========================================================================*/
  DEFINE_FILE();

	/* Store the absolute Arena2 path for opening data files */
  char l_DFArena2Path[_MAX_PATH+2] = "";

	/* Names of DF regions */
  char l_DFRegionNames[62][33] = {
	"Alik'r Desert",			"Dragontail Mountains", 
	"Glenpoint Foothills*",			"Daggerfall Bluffs*",
 	"Yeorth Burrowland*",			"Dwynnen",
	"Ravennian Forest*",			"Devilrock*",
	"Malekna Forest*",			"Isle of Balfiera",
	"Bantha*",				"Dak'fron",
	"Islands in the Western Iliac Bay",	"Tamarilyn Point*",
	"Lainlyn Cliffs*",			"Bjoulsae River*",
	"Wrothgarian Mountains",		"Daggerfall",
	"Glenpoint",				"Betony",
	"Sentinel",				"Anticlere",
	"Lainlyn",				"Wayrest",
	"Gen Tem High Rock village*",		"Gen Rai Hammerfell village*",
	"Orsinium Area",			"Skeffington Wood*",
	"Hammerfell bay coast*",		"Hammerfell sea coast*",
	"High Rock bay coast*",			"High Rock sea coast",
	"Northmoor",				"Menevia",
	"Alcaire",				"Koegria",
	"Bhoriane",				"Kambria",
	"Phrygias",				"Urvaius",
	"Ykalon",				"Daenia",
	"Shalgora",				"Abibon-Gora",
	"Kairou",				"Pothago",
	"Myrkwasa",				"Ayasofya",
	"Tigonus",				"Kozanset",
	"Satakalaam",				"Totambu",
	"Mournoth",				"Ephesus",
	"Santaki",				"Antiphyllos",
	"Bergama",				"Gavaudon",
	"Tulune",				"Glenumbra Moors",
	"Ilessan Hills",			"Cybiades" 
   }; /* End l_DFRegionNames[] */

/*===========================================================================
 *		End of Local Variable Definitions
 *=========================================================================*/


/*===========================================================================
 *
 * Function - FILE* DFOpenFile (pFilename, pMode);
 *
 * Attempt to open a file in the given mode.  First checks the current
 * path, then the ARENA2 relative path, then any set CDROM path.  Returns
 * the file pointer on success, or NULL on any error.
 *
 * TODO: Properly get the valid paths by reading the Z.CFG file. 
 *
 *=========================================================================*/
FILE* DFOpenFile (const char* pFilename, const char* pMode) {
  DEFINE_FUNCTION("DFOpenFile()");
  FILE* pFileHandle;
  char  FileBuffer[_MAX_PATH*2 + 4];

	/* Ensure valid input */
  ASSERT(pFilename != NULL && pMode != NULL);

	/* Attempt to open in the current path */
  pFileHandle = OpenFile(pFilename, pMode);
  if (pFileHandle != NULL) return (pFileHandle);

	/* Attempt to open in the relative ARENA2 path */
  snprintf(FileBuffer, _MAX_PATH+16, "arena2\\%s", pFilename);
  pFileHandle = OpenFile(FileBuffer, pMode);
  if (pFileHandle != NULL) return (pFileHandle);

	/* Attempt to open in the stored path, if any */
  if (l_DFArena2Path[0] != NULL_CHAR) {
    snprintf(FileBuffer, _MAX_PATH*2+2, "%s%s", l_DFArena2Path, pFilename);
    pFileHandle = OpenFile(FileBuffer, pMode);
    if (pFileHandle != NULL) return (pFileHandle);
   }

	/* Attempt to open in a custom debug directory if all else fails */
#ifdef _DEBUG
  snprintf(FileBuffer, _MAX_PATH+32, "e:\\dagger\\arena2\\%s", pFilename);
  pFileHandle = OpenFile(FileBuffer, pMode);
  if (pFileHandle != NULL) return (pFileHandle);
#endif
  
	/* No file found */
  return (NULL);
 }
/*===========================================================================
 *		End of Function DFOpenFile()
 *=========================================================================*/


/*===========================================================================
 *
 * Function - const char* GetDFArena2Path (void);
 *
 * Returns the currently stored absolute Arena2 path.
 *
 *=========================================================================*/
const char* GetDFArena2Path (void) {
  return (l_DFArena2Path);
 }
/*===========================================================================
 *		End of Function char* GetDFArena2Path()
 *=========================================================================*/


/*===========================================================================
 *
 * Function - char* GetDFRegionName (Index);
 *
 * Return a valid Daggerfall region name based on the input region index.
 * Uses the local region array.  ASSERTs in DEBUG builds if passed an
 * invalid index.
 *
 *=========================================================================*/
char* GetDFRegionName (const int Index) {
  DEFINE_FUNCTION("GetDFRegionName()");

  ASSERT(Index >= 0 && Index < DF_MAX_REGIONS);
  return l_DFRegionNames[Index];
 }
/*===========================================================================
 *		End of Function GetDFRegionName()
 *=========================================================================*/


/*===========================================================================
 *
 * Function - boolean InitDFErrors (void);
 *
 * Adds any Daggerfall specific error codes to the custom error handler.
 * Called automatically when this module is included in the project.
 *
 *=========================================================================*/
boolean InitDFErrors (void) {

	/* General BSA error codes */
  ErrorDatabase.Add(DFERR_BSA_DIRTYPE,  "Invalid BSA directory type!");
  ErrorDatabase.Add(DFERR_BSA_NOTFOUND, "Could not find the specified BSA directory entry!");
  ErrorDatabase.Add(DFERR_BSA_READONLY, "BSA files can currently only be read from, not written!");
  ErrorDatabase.Add(DFERR_BSA_NUMFILES, "Number directory entries in BSA file is not valid!");

	/* 3D object error codes */
  ErrorDatabase.Add(DFERR_3D_READPASTEND,    "Read past the end of the Daggerfall 3D Object!");
  ErrorDatabase.Add(DFERR_3D_READPASTSTART,  "Read before the start of the Daggerfall 3D Object!");
  ErrorDatabase.Add(DFERR_3D_DATA2SUBRECORD, "Daggerfall 3D object data2 record section contains an subrecord size!");
  ErrorDatabase.Add(DFERR_3D_BADVERSION,     "Daggerfall 3D object is an unknown version!");
  ErrorDatabase.Add(DFERR_3D_BADHEADER,      "Could not read the Daggerfall 3D object header data!");
  ErrorDatabase.Add(DFERR_3D_BADPOINTS,      "Could not read the Daggerfall 3D object point data!");
  ErrorDatabase.Add(DFERR_3D_BADFACES,       "Could not read the Daggerfall 3D object face data!");
  ErrorDatabase.Add(DFERR_3D_BADNORMALS,     "Could not read the Daggerfall 3D object normal data!");
  ErrorDatabase.Add(DFERR_3D_BADDATA1,       "Could not read the Daggerfall 3D object data1 section!");
  ErrorDatabase.Add(DFERR_3D_BADDATA2,       "Could not read the Daggerfall 3D object data2 section!");
	
	/* IMG/CIF error codes */
  ErrorDatabase.Add(DFERR_IMG_READFILE,	 "Error reading Daggerfall IMG file data!");
  ErrorDatabase.Add(DFERR_IMG_IMAGESIZE, "Daggerfall IMG size is not valid!");
  ErrorDatabase.Add(DFERR_CIF_MAXIMAGES, "Maximum number of images in a Daggerfall CIF file exceeded!");

	/* Palette error codes */
  ErrorDatabase.Add(DFERR_COL_NUMENTRIES, "Daggerfall COL file contains an invalid number of palette colors!");

	/* Texture error codes */
  ErrorDatabase.Add(DFERR_TEXTURE_SUBIMAGES, "Invalid number of sub-images in Daggerfall Texture file!");
  ErrorDatabase.Add(DFERR_TEXTURE_IMAGESIZE, "Daggerfall texture image size is not valid!");
  ErrorDatabase.Add(DFERR_TEXTURE_BADHEIGHT, "Invalid image height found in Daggerfall texture file!");
  ErrorDatabase.Add(DFERR_TEXTURE_NUMIMAGES, "Invalid number of images in Daggerfall Texture file!");
  ErrorDatabase.Add(DFERR_TEXTURE_BADINDEX,  "Daggerfall texture index should range from 0 to 511!");

	/* RMB/Blocks.BSA error codes */
  ErrorDatabase.Add(DFERR_RMB_RECORDSIZE,  "Failed to read the correct size for the Daggerfall RMB file!");
  ErrorDatabase.Add(DFERR_BLOCKS_RMBINDEX, "Invalid RMB index received for Daggerfall BLOCKS.BSA file!");
  ErrorDatabase.Add(DFERR_RMB_CHARINDEX,   "Invalid Daggerfall RMB file character index received!");
  ErrorDatabase.Add(DFERR_BLOCKS_NOTRMB,   "The specified Daggerfall BLOCKS.BSA record is not a RMB type file!");
  ErrorDatabase.Add(DFERR_BLOCKS_NOTRDB,   "The specified Daggerfall BLOCKS.BSA record is not a RDB type file!");
  ErrorDatabase.Add(DFERR_BLOCKS_NOTRDI,   "The specified Daggerfall BLOCKS.BSA record is not a RDI type file!");

  return (TRUE);
 }

	/* Automatically add errors at startup */
static boolean DFPostErrors = InitDFErrors();
/*===========================================================================
 *		End of Function InitDFErrors()
 *=========================================================================*/


/*===========================================================================
 *
 * Function - void SetDFArena2Path (pPath);
 *
 * Store the absolute Arena2 path to the given value for later use when
 * opening data files.
 *
 *=========================================================================*/
void SetDFArena2Path (const char* pPath) {

	/* Check for special case of empty path */
  if (pPath == NULL) { 
    strcpy(l_DFArena2Path, "");
    return;
   }
  
	/* Store the path and ensure its terminated correctly */
  CreatePath(l_DFArena2Path, pPath, _MAX_PATH+1);
 }
/*===========================================================================
 *		End of Function SetDFArena2Path()
 *=========================================================================*/