/****************************************************************************
*
* FILE.C
*
* PROGRAMMER : Chris
*    VERSION : 00.00
*    CREATED : 04/06/98
*   MODIFIED : 04/06/98
*       TABS : 5
*
* DESCRIPTION
*	File IO
*
*****************************************************************************/

/*---------------------------------------------------------------------------
 *	Import Headers
\*--------------------------------------------------------------------------*/

#include <sys\types.h>
#include <libsn.h>
#include <string.h>
#include <stdio.h>
#include "typedefs.h"
#include "cd.h"
#include "file.h"
#include "load_lev.h"
#include "specific.h"

/*---------------------------------------------------------------------------
 *	Constants
\*--------------------------------------------------------------------------*/

//#define LOG

//#ifdef CD_LOAD
//#undef CD_LOAD
//#endif

/*---------------------------------------------------------------------------
 *	Externals
\*--------------------------------------------------------------------------*/

/*---------------------------------------------------------------------------
 *	Macros
\*--------------------------------------------------------------------------*/

#ifdef LOG
#define Log_(format,args...) DebugOut(format "\n" , ## args)
#else
#define Log_(args...)
#endif

/*---------------------------------------------------------------------------
 *	Local Functions
\*--------------------------------------------------------------------------*/

static void PrependPath(char* szDest, char* szSource)
{
#ifdef CD_LOAD
	strcpy(szDest, "\\");
#else
	strcpy(szDest, "");
#endif
	strcat(szDest, szSource);
}

/*---------------------------------------------------------------------------
 *	Public Functions
\*--------------------------------------------------------------------------*/

int FILE_Load(char *szFileName, void* pDest)
{
/* -------- CD */
#ifdef CD_LOAD
	char szNewFileName[64];

	Log_(__FUNCTION__ ": '%s'",szFileName);

	PrependPath(szNewFileName, szFileName);
	return CDFS_LoadFile(szNewFileName, pDest);
#else

/* -------- DOS */

	int nHandle;
	char szNewFileName[64];
	uint32 dwFileSize, dwBytesRead;

	Log_(__FUNCTION__ ": '%s'",szFileName);

	PrependPath(szNewFileName, szFileName);

#ifdef EZORAY
	printf("Open\n");
	if ((nHandle = PCopen0(szNewFileName, 0, 0)) < 0)
#else
	if ((nHandle = PCopen(szNewFileName, 0, 0)) < 0)
#endif
	{
		printf(__FUNCTION__ ": '%s' Could not open!\n",szFileName);
		S_ExitSystem("Can't open file");
	}

#ifdef EZORAY
	printf("Seek\n");
	dwFileSize = PClseek(nHandle, 0, 2);
	PClseek(nHandle, 0, 0);
	printf("Read\n");
	dwBytesRead = PCread0(nHandle, (char *)pDest, dwFileSize);
#else
	dwFileSize = PClseek(nHandle, 0, 2);
	PClseek(nHandle, 0, 0);
	dwBytesRead = PCread(nHandle, (char *)pDest, dwFileSize);
#endif

#ifdef EZORAY
	printf("Close\n");
	PCclose0(nHandle);
#else
	PCclose(nHandle);
#endif

	if (dwFileSize!=dwBytesRead)
	{
		Log_("dwFileSize(%x)!=dwBytesRead(%x)",(unsigned int)dwFileSize,(unsigned int)dwBytesRead);
		return FALSE;
	}
	return TRUE;
#endif
}

/** FILE_Save ************************************************/
int FILE_Save(char* szFileName, void* pSrc, uint32 dwLength)
{
#ifndef CD_LOAD
	int	nHandle;
	uint32 dwBytesWritten;

	Log_(__FUNCTION__ ": '%s'",szFileName);

#ifdef EZORAY
	nHandle = PCcreat0(szFileName, 0);
	PCclose0(nHandle);

	nHandle = PCopen0(szFileName, 1, 0);
	PClseek0(nHandle, 0, 0);

	dwBytesWritten = PCwrite0(nHandle, pSrc, dwLength);
	PCclose0(nHandle);
#else
	nHandle = PCcreat(szFileName, 0);
	PCclose(nHandle);

	nHandle = PCopen(szFileName, 1, 0);
	PClseek(nHandle, 0, 0);

	dwBytesWritten = PCwrite(nHandle, pSrc, dwLength);
	PCclose(nHandle);
#endif
	if (dwBytesWritten!=dwLength)
	{
		Log_("dwBytesWritten(%x)!=dwLength(%x)",(unsigned int)dwBytesWritten,(unsigned int)dwLength);
		return FALSE;
	}
#endif
	return TRUE;
}

/***** FILE_Length *********************************************/
uint32 FILE_Length(char* szFileName)
{
/* -------- CD */
#ifdef CD_LOAD
	char szNewFileName[64];

	Log_(__FUNCTION__ ": '%s'",szFileName);

	PrependPath(szNewFileName, szFileName);
	return CDFS_GetFileSize(szNewFileName);
#else

/* -------- DOS */
	int nHandle;
	uint32 dwFileSize;
	char szNewFileName[64];

	Log_(__FUNCTION__": '%s'", szFileName);

	PrependPath(szNewFileName, szFileName);

#ifdef EZORAY
	printf("Open\n");
	if ((nHandle = PCopen0(szNewFileName, 0, 0)) < 0)
#else
	if ((nHandle = PCopen(szNewFileName, 0, 0)) < 0)
#endif
	{
		printf(__FUNCTION__ ": '%s' Could not find!\n",szFileName);
		S_ExitSystem("Can't open file");
	}

#ifdef EZORAY
	printf("Seek\n");
	dwFileSize = PClseek(nHandle, 0, 2);
#else
	dwFileSize = PClseek(nHandle, 0, 2);
#endif

#ifdef EZORAY
	printf("Close\n");
	PCclose0(nHandle);
#else
	PCclose(nHandle);
#endif

	return dwFileSize;
#endif
}

/** FILE_Open **************************************************/
int FILE_Open(char* szFileName)
{
	char szNewFileName[64];

	Log_(__FUNCTION__ ": '%s'",szFileName);

	PrependPath(szNewFileName, szFileName);

/* -------- CD */
#ifdef CD_LOAD
	return (CDFS_OpenFile(szNewFileName) >= 0);
#else

/* -------- DOS */
#ifdef EZORAY
	printf("Open\n");
	return PCopen(szNewFileName, 0, 0);
#else
	return PCopen(szNewFileName, 0, 0);
#endif
#endif
}

/** FILE_Read **************************************************/
int FILE_Read(void* pDest, int nItemSize, int nItems, int nHandle)
{
/* -------- CD */

#ifdef CD_LOAD
	return CDFS_ReadBytes(pDest, nItemSize*nItems);
#else

/* -------- DOS */

	int nRetVal;
	int nAmount = nItemSize*nItems;

#ifdef EZORAY
	nRetVal = PCread0(nHandle, pDest, nAmount);
#else
	nRetVal = PCread(nHandle, pDest, nAmount);
#endif

	LOAD_Update(nAmount);

	return nRetVal;
#endif
}

/*** FILE_Close **************************************************/
void FILE_Close(int nHandle)
{
#ifndef CD_LOAD

	Log_(__FUNCTION__);


#ifdef EZORAY
	printf("Close\n");
	PCclose0(nHandle);
#else
	PCclose(nHandle);
#endif
#endif
}

/****************************************************************************
* RelocateModule
*
* SYNOPSIS
*	void RelocateModule(unsigned int *reloc, unsigned int base)
*
* PURPOSE
*	Relocates a code module
*
* INPUTS
*	reloc	= ptr to relocation data
*	base		= address of module to relocate
*
* RETURNS
*	Nothing
*/
void RelocateModule(uint32 Module, uint32 *RelocData)
{
#if 0
	unsigned int *puiRelAddr, uiAddr, uiAddrHi=0;
	unsigned short *usSaveHi = 0, *usSaveHi2 = 0;

	while (*RelocData!= 0xffffffff)
	{
		puiRelAddr = (unsigned int *) (Module + (*RelocData & ~3));

		switch (*RelocData++ & 3)
		{
			case 0:	// 32 bit
				*puiRelAddr += Module;
				break;
			case 1:	// ref hi
				if ( usSaveHi )
					usSaveHi2 = (unsigned short*)puiRelAddr;
				else
					usSaveHi = (unsigned short*)puiRelAddr;
				uiAddrHi = *RelocData++;
				break;
			case 2:	// ref lo
				uiAddr = uiAddrHi + Module;
				if (usSaveHi)
				{
					uiAddr += *usSaveHi<<16;
					*usSaveHi = (uiAddr>>16)+((short)uiAddr<0);
					usSaveHi = usSaveHi2;
					usSaveHi2 = NULL;
				}
				*(short*)puiRelAddr = uiAddr;
				uiAddrHi = 0;
				break;
			case 3:	// jmp
				*puiRelAddr += (Module<<4)>>6;
				break;
		}
	}
#else
	unsigned int *rel;

	while (*RelocData!= 0xffffffff)
	{
		rel = (unsigned int *) (Module + (*RelocData & ~3));

		switch (*RelocData++ & 3)
		{
			case 0:	// 32 bit
				*rel += Module;
				break;
			case 1:	// ref hi
				*(short *)rel = ((Module + *RelocData++) + 0x8000) >> 16;
				break;
			case 2:	// ref lo
				*(short *)rel = *(short *)rel + Module;
				break;
			case 3:	// jmp
				*rel += (Module<<4)>>6;
				break;
		}
	}
#endif
}


