summaryrefslogtreecommitdiff
path: root/3dc/win95/media.hpp
diff options
context:
space:
mode:
authorRebellion Developments <rebellion@nomail>2000-03-16 11:25:00 +0100
committerPatryk Obara <dreamer.tan@gmail.com>2019-08-19 05:45:17 +0200
commit218ca90543758a20ac326e444ca0643174ca7384 (patch)
tree16bfe3e5307f9f515489000f28728224291a0e3b /3dc/win95/media.hpp
Import Aliens vs Predator - Gold (Build 116)
Source code release, imported from: https://www.gamefront.com/games/aliens-vs-predator-3/file/avp-gold-complete-source-code All text files were converted to Unix format.
Diffstat (limited to '3dc/win95/media.hpp')
-rw-r--r--3dc/win95/media.hpp681
1 files changed, 681 insertions, 0 deletions
diff --git a/3dc/win95/media.hpp b/3dc/win95/media.hpp
new file mode 100644
index 0000000..73f36b7
--- /dev/null
+++ b/3dc/win95/media.hpp
@@ -0,0 +1,681 @@
+#ifndef _INCLUDED_MEDIA_HPP_
+#define _INCLUDED_MEDIA_HPP_
+
+#if defined(_WIN32) || defined(WIN32) || defined(WINDOWS) || defined(_WINDOWS)
+ #define _MEDIA_WIN_TARGET
+ #include <windows.h>
+#endif // WIN32 || _WIN32 || WINDOWS || _WINDOWS
+
+#include <stdio.h>
+#include <conio.h>
+#include <limits.h>
+#include <string.h>
+
+class MediaMedium;
+
+// use this to read in simple data types
+// note especially that if the size of TYPE is greater than the
+// default buffer size, then the operation will fail
+// and the virtual end of file error flag will be set
+// - use ReadBlock instead
+template <class TYPE>
+void MediaRead(MediaMedium * pThis, TYPE * p);
+
+// use this to write simple data types
+// note especially that if the size of TYPE is greater than the
+// default buffer size, then the operation will fail
+// and the virtual end of file error flag will be set
+// - use WriteBlock instead
+template <class TYPE>
+void MediaWrite(MediaMedium * pThis, TYPE d);
+
+#ifdef __WATCOMC__
+template <class TYPE> class _Media_CompilerHack;
+#endif
+
+class MediaMedium
+{
+ protected:
+ // standard constructor
+ MediaMedium() : m_nRefCnt(1),
+ m_fError(0), m_nDefBufSize(1024),
+ m_nWriteBufPos(0), m_nReadBufPos(0),
+ m_nBufLenUsed(0), m_nBufSize(0),
+ m_pReadBuffer(NULL), m_pWriteBuffer(NULL) {}
+
+ virtual ~MediaMedium() {}
+
+ public:
+ // allow reference counting
+ unsigned AddRef() { return ++m_nRefCnt; }
+ unsigned Release() { if (0==(--m_nRefCnt)) { delete this; return 0;} else return m_nRefCnt; }
+
+ enum
+ {
+ // error code flags
+ MME_VEOFMET = 0x00000001 // virtual end of file met
+ ,MME_EOFMET = 0x00000002 // actual end of file met
+ ,MME_OPENFAIL = 0x00000004 // failed to open medium
+ ,MME_CLOSEFAIL = 0x00000008 // failed to close medium
+ ,MME_UNAVAIL = 0x00000010 // requested operation was not available
+ ,MME_IOERROR = 0x00000020 // read/write operation failed
+ };
+ unsigned m_fError;
+
+ unsigned m_nDefBufSize; // default read or write buffer sizes for buffering small objects
+
+ // flush read/write buffers. You should call this function after the last read or write operation on the object
+ // alternatively, derived (implementation) classes close methods should call this
+ void Flush()
+ {
+ if (m_pReadBuffer)
+ {
+ unsigned nBufStartPos = DoGetPos();
+ CloseReadBuffer(m_nReadBufPos > m_nBufLenUsed ? m_nReadBufPos : m_nBufLenUsed);
+ DoSetPos(nBufStartPos + m_nReadBufPos);
+ m_pReadBuffer = NULL;
+ m_nReadBufPos = 0;
+ }
+ else if (m_pWriteBuffer)
+ {
+ unsigned nBufStartPos = DoGetPos();
+ CloseWriteBuffer(m_nWriteBufPos > m_nBufLenUsed ? m_nWriteBufPos : m_nBufLenUsed);
+ DoSetPos(nBufStartPos + m_nWriteBufPos);
+ m_pWriteBuffer = NULL;
+ m_nWriteBufPos = 0;
+ }
+ m_nBufSize = 0;
+ m_nBufLenUsed = 0;
+ }
+
+ // use this to write a block of raw data
+ void WriteBlock(void const * pData, unsigned nSize)
+ {
+ Flush();
+ DoWriteBlock(pData,nSize);
+ }
+
+ // this may be faster, but will only work if the block size no more than the default buffer size
+ void WriteBufferedBlock(void const * pData, unsigned nSize)
+ {
+ if (m_nWriteBufPos + nSize <= m_nBufSize)
+ {
+ memcpy(static_cast<char *>(m_pWriteBuffer) + m_nWriteBufPos/sizeof(char), pData, nSize);
+ m_nWriteBufPos += nSize;
+ }
+ else
+ {
+ Flush();
+ m_pWriteBuffer = GetWriteBuffer(&m_nBufSize,m_nDefBufSize);
+ if (nSize <= m_nBufSize)
+ {
+ memcpy(m_pWriteBuffer, pData, nSize);
+ m_nWriteBufPos = nSize;
+ }
+ else
+ {
+ m_fError |= MME_VEOFMET;
+ }
+ }
+ }
+
+ // use this to read a block of raw data
+ void ReadBlock(void * pData, unsigned nSize)
+ {
+ Flush();
+ DoReadBlock(pData,nSize);
+ }
+
+ // this may be faster, but will only work if the block size no more than the default buffer size
+ void ReadBufferedBlock(void * pData, unsigned nSize)
+ {
+ if (m_nReadBufPos + nSize <= m_nBufSize)
+ {
+ memcpy(pData, static_cast<char const *>(m_pReadBuffer) + m_nReadBufPos/sizeof(char), nSize);
+ m_nReadBufPos += nSize;
+ }
+ else
+ {
+ Flush();
+ m_pReadBuffer = GetReadBuffer(&m_nBufSize,m_nDefBufSize);
+ if (nSize <= m_nBufSize)
+ {
+ memcpy(pData, m_pReadBuffer, nSize);
+ m_nReadBufPos = nSize;
+ }
+ else
+ {
+ m_fError |= MME_VEOFMET;
+ }
+ }
+ }
+
+ // move the 'file' pointer nOffset bytes
+ // this will not necessarily cause buffers to be flushed
+ // if the pointer can be moved within the current buffer,
+ // some of the buffer may be left uninitialized, and no
+ // error will occur, which otherwise might (particularly
+ // if the object has write access)
+ void MovePos(signed nOffset)
+ {
+ if (m_pReadBuffer)
+ {
+ if (nOffset>0 && m_nReadBufPos+nOffset<=m_nBufSize)
+ {
+ m_nReadBufPos+=nOffset;
+ return;
+ }
+ else if (nOffset<=0 && m_nReadBufPos>=static_cast<unsigned>(-nOffset))
+ {
+ if (m_nBufLenUsed < m_nReadBufPos) m_nBufLenUsed = m_nReadBufPos;
+ m_nReadBufPos+=nOffset;
+ return;
+ }
+ }
+ else if (m_pWriteBuffer)
+ {
+ if (nOffset>0 && m_nWriteBufPos+nOffset<=m_nBufSize)
+ {
+ m_nWriteBufPos+=nOffset;
+ return;
+ }
+ else if (nOffset<=0 && m_nWriteBufPos>=static_cast<unsigned>(-nOffset))
+ {
+ if (m_nBufLenUsed < m_nWriteBufPos) m_nBufLenUsed = m_nWriteBufPos;
+ m_nWriteBufPos+=nOffset;
+ return;
+ }
+ }
+ // else
+ Flush();
+ DoSetPos(DoGetPos()+nOffset);
+ }
+
+ // set the 'file' pointer
+ // you would normally only pass values which have been
+ // previously returned by a call to GetPos
+ // note that this will not necessarily cause buffers to be flushed
+ // if the pointer can be moved within the current buffer,
+ // some of the buffer may be left uninitialized, and no
+ // error will occur, which otherwise might (particularly
+ // if the object has write access)
+ void SetPos(unsigned nPos)
+ {
+ unsigned nNewBufPos = nPos - DoGetPos();
+ if (nNewBufPos <= m_nBufSize)
+ {
+ if (m_pReadBuffer)
+ {
+ if (m_nBufLenUsed < m_nReadBufPos) m_nBufLenUsed = m_nReadBufPos;
+ m_nReadBufPos = nNewBufPos;
+ }
+ else // pWriteBuffer
+ {
+ if (m_nBufLenUsed < m_nWriteBufPos) m_nBufLenUsed = m_nWriteBufPos;
+ m_nWriteBufPos = nNewBufPos;
+ }
+ }
+ else
+ {
+ Flush();
+ DoSetPos(nPos);
+ }
+ }
+
+ // get the 'file' pointer. The returned value
+ // can be used in a call to SetPos
+ unsigned GetPos()
+ {
+ return DoGetPos()+m_nReadBufPos+m_nWriteBufPos;
+ }
+
+ virtual unsigned GetRemainingSize();
+
+ private:
+ void * m_pWriteBuffer;
+ void const * m_pReadBuffer;
+ unsigned m_nReadBufPos;
+ unsigned m_nWriteBufPos;
+ unsigned m_nBufSize;
+ unsigned m_nBufLenUsed;
+
+ unsigned m_nRefCnt;
+
+ protected:
+
+ // the non-pure functions default implementation sets the unavailable error flag
+
+ // it is safe to assume that these four functions will be called in a logical order
+ // and that only one buffer (read or write) will be required at once
+
+ // this two functions may return NULL only if *pSize is set to zero
+ // *pSize should otherwise be set to the actual size of the buffer returned
+
+ // get a pointer to memory where data can be written to directly
+ virtual void * GetWriteBuffer(unsigned * pSize, unsigned nDesiredSize);
+
+ // get a pointer to memory where data can be read from directly
+ virtual void const * GetReadBuffer(unsigned * pSize, unsigned nDesiredSize);
+
+ // close the buffer 'allocated' above and assume nPosOffset bytes were transferred
+ // and that the 'file' pointer should be positioned at the end of the transferred data
+ virtual void CloseWriteBuffer(unsigned nPosOffset);
+ virtual void CloseReadBuffer(unsigned nPosOffset);
+
+ // transfer a block of data
+ // it is safe to assume that no buffer will be open
+ virtual void DoWriteBlock(void const * pData, unsigned nSize);
+ virtual void DoReadBlock(void * pData, unsigned nSize);
+
+ // if a buffer is open, should return pos at start of buffer
+ virtual unsigned DoGetPos() = 0;
+
+ // it is safe to assume that no buffer will be open
+ virtual void DoSetPos(unsigned nPos) = 0;
+
+ friend class MediaSection;
+
+ friend class _Media_CompilerHack;
+};
+
+#ifdef __WATCOMC__
+template <class TYPE>
+#endif
+class _Media_CompilerHack
+{
+ public:
+ #ifndef __WATCOMC__
+ template <class TYPE>
+ #endif
+ static inline void MediaRead(MediaMedium * pThis, TYPE * p)
+ {
+ if (pThis->m_nReadBufPos + sizeof(TYPE) <= pThis->m_nBufSize)
+ {
+ *p = *reinterpret_cast<TYPE const *>(static_cast<char const *>(pThis->m_pReadBuffer) + pThis->m_nReadBufPos/sizeof(char));
+
+ pThis->m_nReadBufPos += sizeof(TYPE);
+ }
+ else
+ {
+ pThis->Flush();
+ pThis->m_pReadBuffer = pThis->GetReadBuffer(&pThis->m_nBufSize,pThis->m_nDefBufSize);
+ if (sizeof(TYPE) <= pThis->m_nBufSize)
+ {
+ *p = *static_cast<TYPE const *>(pThis->m_pReadBuffer);
+ pThis->m_nReadBufPos = sizeof(TYPE);
+ }
+ else
+ {
+ pThis->m_fError |= MediaMedium::MME_VEOFMET;
+ }
+ }
+ }
+
+ #ifndef __WATCOMC__
+ template <class TYPE>
+ #endif
+ static inline void MediaWrite(MediaMedium * pThis, TYPE d)
+ {
+ if (pThis->m_nWriteBufPos + sizeof(TYPE) <= pThis->m_nBufSize)
+ {
+ *reinterpret_cast<TYPE *>(static_cast<char *>(pThis->m_pWriteBuffer) + pThis->m_nWriteBufPos/sizeof(char)) = d;
+
+ pThis->m_nWriteBufPos += sizeof(TYPE);
+ }
+ else
+ {
+ pThis->Flush();
+ pThis->m_pWriteBuffer = pThis->GetWriteBuffer(&pThis->m_nBufSize,pThis->m_nDefBufSize);
+ if (sizeof(TYPE) <= pThis->m_nBufSize)
+ {
+ *static_cast<TYPE *>(pThis->m_pWriteBuffer) = d;
+ pThis->m_nWriteBufPos = sizeof(TYPE);
+ }
+ else
+ {
+ pThis->m_fError |= MediaMedium::MME_VEOFMET;
+ }
+ }
+ }
+};
+
+// use this to read in simple data types
+// note especially that if the size of TYPE is greater than the
+// default buffer size, then the operation will fail
+// and the virtual end of file error flag will be set
+// - use ReadBlock instead
+template <class TYPE>
+inline void MediaRead(MediaMedium * pThis, TYPE * p)
+{
+ _Media_CompilerHack
+ #ifdef __WATCOMC__
+ <TYPE>
+ #endif
+ ::MediaRead(pThis,p);
+}
+
+// use this to write simple data types
+// note especially that if the size of TYPE is greater than the
+// default buffer size, then the operation will fail
+// and the virtual end of file error flag will be set
+// - use WriteBlock instead
+template <class TYPE>
+inline void MediaWrite(MediaMedium * pThis, TYPE d)
+{
+ _Media_CompilerHack
+ #ifdef __WATCOMC__
+ <TYPE>
+ #endif
+ ::MediaWrite(pThis,d);
+}
+
+#ifdef _MEDIA_WIN_TARGET
+
+class MediaWinFileMedium : public MediaMedium
+{
+ public:
+ MediaWinFileMedium() : m_hFile(INVALID_HANDLE_VALUE), m_nReadBufLen(0) {}
+
+ void Attach(HANDLE hFile)
+ {
+ m_hFile = hFile;
+ }
+ void Detach()
+ {
+ Flush();
+ m_hFile = INVALID_HANDLE_VALUE;
+ }
+
+ void Open(LPCTSTR pszFileName, DWORD dwDesiredAccess)
+ {
+ DWORD dwShareMode;
+ DWORD dwCreationDistribution;
+ switch (dwDesiredAccess & (GENERIC_READ|GENERIC_WRITE))
+ {
+ case 0:
+ dwShareMode = FILE_SHARE_READ|FILE_SHARE_WRITE;
+ dwCreationDistribution = OPEN_EXISTING;
+ break;
+ case GENERIC_READ:
+ dwShareMode = FILE_SHARE_READ;
+ dwCreationDistribution = OPEN_EXISTING;
+ break;
+ case GENERIC_WRITE:
+ dwShareMode = 0;
+ dwCreationDistribution = CREATE_ALWAYS;
+ break;
+ default: // GENERIC_WRITE|GENERIC_READ
+ dwCreationDistribution = OPEN_ALWAYS;
+ dwShareMode = 0;
+ }
+ m_hFile = CreateFile
+ (
+ pszFileName,
+ dwDesiredAccess,
+ dwShareMode,
+ NULL,
+ dwCreationDistribution,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL
+ );
+ if (INVALID_HANDLE_VALUE == m_hFile)
+ m_fError |= MME_OPENFAIL;
+ }
+ void Close()
+ {
+ if (INVALID_HANDLE_VALUE == m_hFile)
+ m_fError |= MME_CLOSEFAIL;
+ else
+ {
+ Flush();
+ if (!CloseHandle(m_hFile))
+ m_fError |= MME_CLOSEFAIL;
+ else
+ m_hFile = INVALID_HANDLE_VALUE;
+ }
+ }
+
+ ~MediaWinFileMedium()
+ {
+ // should already be closed...
+ Close();
+ }
+
+ virtual unsigned GetRemainingSize();
+
+ private:
+ HANDLE m_hFile;
+
+ char * m_pBuffer;
+ unsigned m_nReadBufLen;
+
+ protected:
+
+ // get a pointer to memory where data can be written to directly
+ virtual void * GetWriteBuffer(unsigned * pSize, unsigned nDesiredSize);
+
+ // get a pointer to memory where data can be read from directly
+ virtual void const * GetReadBuffer(unsigned * pSize, unsigned nDesiredSize);
+
+ // close the buffer allocated above and assume nPosOffset were transferred
+ virtual void CloseWriteBuffer(unsigned nPosOffset);
+ virtual void CloseReadBuffer(unsigned nPosOffset);
+
+ // transfer a block of data: the buffer should be closed
+ virtual void DoWriteBlock(void const * pData, unsigned nSize);
+ virtual void DoReadBlock(void * pData, unsigned nSize);
+
+ // if a buffer is open, should return pos at start of buffer
+ virtual unsigned DoGetPos();
+
+ // requires that no buffer is oben
+ virtual void DoSetPos(unsigned nPos);
+};
+
+#endif // _MEDIA_WIN_TARGET
+
+class MediaStdFileMedium : public MediaMedium
+{
+ public:
+ MediaStdFileMedium() : m_pFile(NULL), m_nReadBufLen(0) {}
+
+ void Attach(FILE * pFile)
+ {
+ m_pFile = pFile;
+ }
+ void Detach()
+ {
+ Flush();
+ m_pFile = NULL;
+ }
+
+ void Open(char const * pszFileName, char const * pszOpenMode)
+ {
+ m_pFile = fopen(pszFileName,pszOpenMode);
+ if (!m_pFile)
+ m_fError |= MME_OPENFAIL;
+ }
+ void Close()
+ {
+ if (!m_pFile)
+ m_fError |= MME_CLOSEFAIL;
+ else
+ {
+ Flush();
+ if (fclose(m_pFile))
+ m_fError |= MME_CLOSEFAIL;
+ else
+ m_pFile = NULL;
+ }
+ }
+
+ ~MediaStdFileMedium()
+ {
+ // should already be closed...
+ Close();
+ }
+
+ virtual unsigned GetRemainingSize();
+
+ private:
+ FILE * m_pFile;
+
+ char * m_pBuffer;
+ unsigned m_nReadBufLen;
+
+ protected:
+
+ // get a pointer to memory where data can be written to directly
+ virtual void * GetWriteBuffer(unsigned * pSize, unsigned nDesiredSize);
+
+ // get a pointer to memory where data can be read from directly
+ virtual void const * GetReadBuffer(unsigned * pSize, unsigned nDesiredSize);
+
+ // close the buffer allocated above and assume nPosOffset were transferred
+ virtual void CloseWriteBuffer(unsigned nPosOffset);
+ virtual void CloseReadBuffer(unsigned nPosOffset);
+
+ // transfer a block of data: the buffer should be closed
+ virtual void DoWriteBlock(void const * pData, unsigned nSize);
+ virtual void DoReadBlock(void * pData, unsigned nSize);
+
+ // if a buffer is open, should return pos at start of buffer
+ virtual unsigned DoGetPos();
+
+ // requires that no buffer is oben
+ virtual void DoSetPos(unsigned nPos);
+};
+
+class MediaMemoryReadMedium : public MediaMedium
+{
+ public:
+ MediaMemoryReadMedium() : m_pMem(NULL) {}
+
+ void Open(void const * p)
+ {
+ m_pMem = p;
+ m_nOffset = 0;
+ }
+
+ void Close()
+ {
+ if (m_pMem)
+ {
+ Flush();
+ m_pMem = NULL;
+ }
+ else
+ m_fError |= MME_CLOSEFAIL;
+ }
+
+ private:
+ void const * m_pMem;
+
+ protected:
+ unsigned m_nOffset;
+
+ // get a pointer to memory where data can be read from directly
+ virtual void const * GetReadBuffer(unsigned * pSize, unsigned nDesiredSize);
+
+ // close the buffer allocated above and assume nPosOffset were transferred
+ virtual void CloseReadBuffer(unsigned nPosOffset);
+
+ // transfer a block of data: the buffer should be closed
+ virtual void DoReadBlock(void * pData, unsigned nSize);
+
+ // if a buffer is open, should return pos at start of buffer
+ virtual unsigned DoGetPos();
+
+ // requires that no buffer is oben
+ virtual void DoSetPos(unsigned nPos);
+};
+
+class MediaMemoryMedium : public MediaMemoryReadMedium
+{
+ public:
+ MediaMemoryMedium() : m_pMem(NULL) {}
+
+ void Open(void * p)
+ {
+ m_pMem = p;
+ MediaMemoryReadMedium::Open(p);
+ }
+
+ void Close()
+ {
+ MediaMemoryReadMedium::Close();
+ m_pMem = NULL;
+ }
+
+ private:
+ void * m_pMem;
+
+ protected:
+
+ // get a pointer to memory where data can be written to directly
+ virtual void * GetWriteBuffer(unsigned * pSize, unsigned nDesiredSize);
+
+ // close the buffer allocated above and assume nPosOffset were transferred
+ virtual void CloseWriteBuffer(unsigned nPosOffset);
+
+ // transfer a block of data: the buffer should be closed
+ virtual void DoWriteBlock(void const * pData, unsigned nSize);
+};
+
+
+class MediaSection : public MediaMedium
+{
+ public:
+ MediaSection() : m_pMedium(NULL) {}
+
+ void Open(MediaMedium * pMedium, unsigned nMaxSize = UINT_MAX)
+ {
+ m_pMedium = pMedium;
+ m_nMaxSize = nMaxSize;
+ m_nPos = 0;
+ m_nUsedPos = 0;
+ }
+ void Close()
+ {
+ if (m_pMedium)
+ Flush();
+ if (m_nPos > m_nUsedPos) m_nUsedPos = m_nPos;
+ m_pMedium = NULL;
+ }
+ unsigned GetUsedSize() const
+ {
+ return (m_nPos > m_nUsedPos) ? m_nPos : m_nUsedPos;
+ }
+
+ virtual unsigned GetRemainingSize();
+
+ private:
+ MediaMedium * m_pMedium;
+ unsigned m_nMaxSize;
+ unsigned m_nPos;
+ unsigned m_nUsedPos;
+
+ protected:
+ // get a pointer to memory where data can be written to directly
+ virtual void * GetWriteBuffer(unsigned * pSize, unsigned nDesiredSize);
+
+ // get a pointer to memory where data can be read from directly
+ virtual void const * GetReadBuffer(unsigned * pSize, unsigned nDesiredSize);
+
+ // close the buffer allocated above and assume nPosOffset were transferred
+ virtual void CloseWriteBuffer(unsigned nPosOffset);
+ virtual void CloseReadBuffer(unsigned nPosOffset);
+
+ // transfer a block of data: the buffer should be closed
+ virtual void DoWriteBlock(void const * pData, unsigned nSize);
+ virtual void DoReadBlock(void * pData, unsigned nSize);
+
+ // if a buffer is open, should return pos at start of buffer
+ virtual unsigned DoGetPos();
+
+ // requires that no buffer is oben
+ virtual void DoSetPos(unsigned nPos);
+};
+
+
+#endif