#include "PalmType.h"
#include "PalmChip.h"
#include "p_util.h"

static XCHAR _iFileBufLen, _iFileSdramHi, _iFileSdramLo;
static XCHAR _pFileBuf[256];
static BOOLEAN _bWrite, _bRunning = FALSE;
static XLONG _lSize, _lSizeLimit;

BOOLEAN SoloFileOpen(UCHAR iSdramHi, BOOLEAN bWrite, ULONG lMaxSize)
{
	if (_bRunning)	return FALSE;

	_bWrite = bWrite;
	_iFileSdramHi = iSdramHi;
	_iFileSdramLo = 0;
	_iFileBufLen = 0;
	_lSize = 0;
	_lSizeLimit = lMaxSize;

	_bRunning = TRUE;
	return TRUE;
}

/*
ULONG SoloFileGetLimit()
{
	return _lSizeLimit;
}
*/

void SoloFileSetLimit(ULONG lMaxSize)
{
	_lSizeLimit = lMaxSize;
}

ULONG SoloFileClose()
{
	if (_bRunning)
	{
		_bRunning = FALSE;
		if (_bWrite)
		{	// Flush write
			p_memcpy_x2x((PXCHAR)Sdram_pDataCache, (PXCHAR)_pFileBuf, _iFileBufLen);
			SdramWrite(_iFileSdramHi, _iFileSdramLo, SRAM_DMA_HALF_DWORD);
		}
		_lSizeLimit = _lSize;
		return _lSize;
	}
	else
	{
		return 0;
	}
}

ULONG SoloFileGetSize()
{
	return _lSize;
}

void _AdjustFilePos()
{
	_iFileSdramLo ++;
	if (!_iFileSdramLo)
	{
		_iFileSdramHi ++;
	}
}

void _DoFileRead()
{
	SdramRead(_iFileSdramHi, _iFileSdramLo, SRAM_DMA_HALF_DWORD);
	_AdjustFilePos();
}

BOOLEAN _CheckReadFile()
{
	if (!_bRunning)		return FALSE;
	if (_bWrite)		return FALSE;
	if (_lSize >= _lSizeLimit)
	{
		SoloFileClose();	// end of file, close it automatically
		return FALSE;
	}
	return TRUE;
}

void SoloFileCloseRead()
{
	if (!_bRunning)		return;
	if (!_bWrite)	// only close read file
	{
		SoloFileClose();
	}
}

BOOLEAN SoloFileIsWriting()
{
	if (!_bRunning)	return FALSE;
	if (!_bWrite)	return FALSE;

	return TRUE;
}

BOOLEAN SoloFileIsRunning()
{
	return _bRunning;
}

BOOLEAN SoloFileRead(PXCHAR pDataBuf, UCHAR iLen)
{
	DCHAR iLength, iLength2;
	PXCHAR_D pBuf;

	if (!_CheckReadFile())	return FALSE;

	pBuf = pDataBuf;
	iLength = iLen;
	_lSize += iLength;
	if (!iLength)
	{
		_lSize += 256;
	}

	if (iLength && iLength <= _iFileBufLen)
	{
		p_memcpy_x2x(pBuf, _pFileBuf, iLength);
		_iFileBufLen -= iLength;
		if (_iFileBufLen)
		{
			p_memcpy_x2x((PXCHAR)_pFileBuf, (PXCHAR)(_pFileBuf+iLength), _iFileBufLen);
		}
	}
	else
	{
		_DoFileRead();
		p_memcpy_x2x(pBuf, _pFileBuf, _iFileBufLen);
		iLength2 = iLength - _iFileBufLen;
		p_memcpy_x2x((PXCHAR)(pBuf+_iFileBufLen), (PXCHAR)Sdram_pDataCache, iLength2);
		_iFileBufLen = 256-iLength2;
		p_memcpy_x2x((PXCHAR)_pFileBuf, (PXCHAR)(Sdram_pDataCache+iLength2), _iFileBufLen);
	}
	return TRUE;
}

/*
 BOOLEAN SoloFileSeek(ULONG lPos)
{
	DCHAR iLength;

	if (!_CheckReadFile())	return FALSE;

	_lSize = lPos;

	_iFileSdramHi += P_HIWORD(lPos);
	_iFileSdramLo = P_HIBYTE(P_LOWORD(lPos));

	iLength = P_LOBYTE(P_LOWORD(lPos));
	if (iLength)
	{
		_DoFileRead();
		_iFileBufLen = 256-iLength;
		p_memcpy_x2x((PXCHAR)_pFileBuf, (PXCHAR)(Sdram_pDataCache+iLength), _iFileBufLen);
	}

	return TRUE;
}
*/

void _DoFileWrite()
{
	SdramWrite(_iFileSdramHi, _iFileSdramLo, SRAM_DMA_HALF_DWORD);
	_AdjustFilePos();
}

BOOLEAN SoloFileWrite(PXCHAR pDataBuf, UCHAR iLen)
{
	DCHAR iLength, iLength2;
	PXCHAR_D pBuf;

	if (!_bRunning)		return FALSE;
	if (!_bWrite)		return FALSE;
	if (_lSize >= _lSizeLimit)	return FALSE;

	pBuf = pDataBuf;
	iLength = iLen;
	if (iLength)
	{
		_lSize += iLength;
		iLength2 = iLength + _iFileBufLen;
		if (iLength2)
		{
			if (iLength2 > _iFileBufLen)
			{
				p_memcpy_x2x((PXCHAR)(_pFileBuf+_iFileBufLen), pBuf, iLength);
				_iFileBufLen += iLength;
			}
			else
			{
				p_memcpy_x2x((PXCHAR)Sdram_pDataCache, (PXCHAR)_pFileBuf, _iFileBufLen);
				iLength2 = 256-_iFileBufLen;
				p_memcpy_x2x((PXCHAR)(Sdram_pDataCache+_iFileBufLen), pBuf, iLength2);
				_DoFileWrite();
				_iFileBufLen = iLength - iLength2;
				p_memcpy_x2x((PXCHAR)_pFileBuf, (PXCHAR)(pBuf+iLength2), _iFileBufLen);
			}
		}
		else
		{
			p_memcpy_x2x((PXCHAR)(_pFileBuf+_iFileBufLen), pBuf, iLength);
			p_memcpy_x2x((PXCHAR)Sdram_pDataCache, (PXCHAR)_pFileBuf, (UCHAR)256);
			_DoFileWrite();
			_iFileBufLen = 0;
		}
	}
	else // 256 bytes
	{
		_lSize += 256;
		if (_iFileBufLen)
		{
			p_memcpy_x2x((PXCHAR)Sdram_pDataCache, (PXCHAR)_pFileBuf, _iFileBufLen);
			iLength2 = 256-_iFileBufLen;
			p_memcpy_x2x((PXCHAR)(Sdram_pDataCache+_iFileBufLen), pBuf, iLength2);
			_DoFileWrite();
			p_memcpy_x2x((PXCHAR)_pFileBuf, (PXCHAR)(pBuf+iLength2), _iFileBufLen);
		}
		else
		{
			p_memcpy_x2x((PXCHAR)Sdram_pDataCache, pBuf, (UCHAR)256);
			_DoFileWrite();
		}
	}
	return TRUE;
}

BOOLEAN SoloFileWriteSdramCache(UCHAR iLen)
{
	DCHAR iLength;

	iLength = iLen;
	p_memcpy_x2x((PXCHAR)Sdram_pDataCache2, (PXCHAR)Sdram_pDataCache, iLength);
	return SoloFileWrite((PXCHAR)Sdram_pDataCache2, iLength);
}

/*
BOOLEAN SoloFileWriteLarge(PXCHAR pDataBuf, USHORT iLen)
{
	PXCHAR_D pBuf;
	DSHORT iLength;
	DCHAR iLength2;

	if (!_bRunning)		return FALSE;
	if (!_bWrite)		return FALSE;
//	if (_lSize >= _lSizeLimit)	return FALSE;

	pBuf = pDataBuf;
	iLength = iLen;

	_lSize += iLength;

	if (_iFileBufLen)
	{
		p_memcpy_x2x((PXCHAR)Sdram_pDataCache, (PXCHAR)_pFileBuf, _iFileBufLen);
		iLength2 = 256-_iFileBufLen;
		p_memcpy_x2x((PXCHAR)(Sdram_pDataCache+_iFileBufLen), pBuf, iLength2);
		_DoFileWrite();
		pBuf += iLength2;
		iLength -= iLength2;
	}

	while (iLength >= 256)
	{
		p_memcpy_x2x((PXCHAR)Sdram_pDataCache, pBuf, (UCHAR)256);
		_DoFileWrite();
		pBuf += 256;
		iLength -= 256;
	}

	iLength2 = (UCHAR)iLength;
	if (iLength2)
	{
		p_memcpy_x2x((PXCHAR)_pFileBuf, pBuf, iLength2);
	}
	_iFileBufLen = iLength2;
}
*/
