Initial revision

This commit is contained in:
Steven Fuller 2001-07-01 00:55:22 +00:00 committed by Patryk Obara
parent 218ca90543
commit 2186d5f3f9
572 changed files with 2 additions and 29666 deletions

111
src/win95/advwin32.h Normal file
View file

@ -0,0 +1,111 @@
/*************************************************************
Module name: AdvWin32.H
Notices: Copyright (c) 1995 Jeffrey Richter
*************************************************************/
#ifndef ADVWIN32_H_INCLUDED
#define ADVWIN32_H_INCLUDED
/* Disable Visual C++ warnings which fire when reading Windows OS headers. */
#ifndef __WATCOMC__
/* Disable ridiculous warnings so that the code */
/* compiles cleanly using warning level 4. */
/* nonstandard extension 'single line comment' was used */
#pragma warning(disable: 4001)
// nonstandard extension used : nameless struct/union
#pragma warning(disable: 4201)
// nonstandard extension used : bit field types other than int
#pragma warning(disable: 4214)
// Note: Creating precompiled header
#pragma warning(disable: 4699)
// unreferenced inline function has been removed
#pragma warning(disable: 4514)
// unreferenced formal parameter
#pragma warning(disable: 4100)
// 'type' differs in indirection to slightly different base
// types from 'other type'
#pragma warning(disable: 4057)
// named type definition in parentheses
#pragma warning(disable: 4115)
// nonstandard extension used : benign typedef redefinition
#pragma warning(disable: 4209)
// conditional expression is constant : used to differentiate between internal and external versions
#pragma warning(disable: 4127)
// comma operator in array index, disabled due to assertions in array indicies
#pragma warning(disable: 4709)
// assignment operator could not be generated, disable as often the operator isn't used.
#pragma warning(disable: 4512)
// 'function' selected for automatic inline expansion - when a function not declared inline was inlined: well done compiler, aren't you clever!
#pragma warning(disable: 4711)
// 'function' not expanded.
#pragma warning(disable: 4710)
#pragma warning(disable: 4032)
#pragma warning(disable: 4702)
/////////////////////////////////////////////////////////////
// Create an ARRAY_SIZE macro that returns the number of
// elements in an array. This is a handy macro that I use
// frequently throughout the sample applications.
#define ARRAY_SIZE(Array) \
(sizeof(Array) / sizeof((Array)[0]))
/////////////////////////////////////////////////////////////
// Create a BEGINTHREADEX macro that calls the C run-time's
// _beginthreadex function. The C run-time library doesn't
// want to have any reliance on Win32 data types such as
// HANDLE. This means that a Win32 programmer needs to cast
// the return value to a HANDLE. This is terribly inconvenient,
// so I have created this macro to perform the casting.
typedef unsigned (__stdcall *PTHREAD_START) (void *);
#define BEGINTHREADEX(lpsa, cbStack, lpStartAddr, \
lpvThreadParm, fdwCreate, lpIDThread) \
((HANDLE)_beginthreadex( \
(void *) (lpsa), \
(unsigned) (cbStack), \
(PTHREAD_START) (lpStartAddr), \
(void *) (lpvThreadParm), \
(unsigned) (fdwCreate), \
(unsigned *) (lpIDThread)))
/////////////////////////////////////////////////////////////
// Compile all CONTEXT structures to use 32-bit members
// instead of 16-bit members. Currently, the only sample
// application that requires this is TInjLib.16 in order
// for it to work correctly on the DEC Alpha AXP.
#define _PORTABLE_32BIT_CONTEXT
#endif /* ifndef __WATCOMC__ */
/////////////////////////////////////////////////////////////
// Force all EXEs/DLLs to use STRICT type checking.
#ifndef STRICT
#define STRICT 1
#endif
#endif /* ifndef ADVWIN32_H_INCLUDED */
////////////////////////// End Of File //////////////////////

390
src/win95/alt_tab.cpp Normal file
View file

@ -0,0 +1,390 @@
#ifndef DB_LEVEL
#define DB_LEVEL 5
#endif
#include "db.h"
#ifndef HT_FAIL
#define HT_FAIL db_msg1
#endif
#include "hash_tem.hpp"
#ifdef _CPPRTTI
#include <typeinfo>
#endif
#include "awTexLd.h"
#include "alt_tab.h"
template <class DX_PTR>
class AltTabRestore
{
public:
virtual ~AltTabRestore(){}
virtual void DoRestore(DX_PTR * pDxGraphic) = 0;
};
template <class DX_PTR>
class AltTabAwRestore : public AltTabRestore<DX_PTR>
{
public:
AltTabAwRestore(AW_BACKUPTEXTUREHANDLE hBackup) : m_hBackup(hBackup) {}
private:
AW_BACKUPTEXTUREHANDLE m_hBackup;
protected:
virtual void DoRestore(DX_PTR * pDxGraphic);
};
void AltTabAwRestore<DDSurface>::DoRestore(DDSurface * pSurface)
{
DDSurface * pNewSurface = AwCreateSurface("rtf",m_hBackup,pSurface,AW_TLF_PREVSRCALL);
// should have succeeded
db_assert1(pNewSurface);
// should return the same pointer!
db_assert1(pNewSurface == pSurface);
// don't need both references
pNewSurface->Release();
}
void AltTabAwRestore<D3DTexture>::DoRestore(D3DTexture * pTexture)
{
D3DTexture * pNewTexture = AwCreateTexture("rtf",m_hBackup,pTexture,AW_TLF_PREVSRCALL);
// should have succeeded
db_assert1(pNewTexture);
// should return the same pointer!
db_assert1(pNewTexture == pTexture);
// don't need both references
pNewTexture->Release();
}
template <class DX_PTR>
class AltTabUserRestore : public AltTabRestore<DX_PTR>
{
public:
typedef void (* PFN_RESTORE) (DX_PTR * pDxGraphic, void * pUser);
#ifdef NDEBUG
AltTabUserRestore(PFN_RESTORE pfnRestore, void * pUser) : m_pfnRestore(pfnRestore), m_pUser(pUser) {}
#else
AltTabUserRestore(PFN_RESTORE pfnRestore, void * pUser, char const * pszFuncName) : m_pfnRestore(pfnRestore), m_pUser(pUser), m_pszFuncName(pszFuncName) {}
#endif
private:
PFN_RESTORE m_pfnRestore;
void * m_pUser;
char const * m_pszFuncName;
protected:
virtual void DoRestore(DX_PTR * pDxGraphic);
};
template <class DX_PTR>
void AltTabUserRestore<DX_PTR>::DoRestore(DX_PTR * pDxGraphic)
{
#ifdef _CPPRTTI
db_logf4(("\t\tCalling User Restore Function %s = %p (%s * = %p, void * = %p)",m_pszFuncName,m_pfnRestore,typeid(*pDxGraphic).name(),pDxGraphic,m_pUser));
#else
db_logf4(("\t\tCalling User Restore Function %s = %p (IUnknown * = %p, void * = %p)",m_pszFuncName,m_pfnRestore,pDxGraphic,m_pUser));
#endif
m_pfnRestore(pDxGraphic, m_pUser);
}
template <class DX_PTR>
struct AltTabEntry
{
DX_PTR * m_pDxGraphic;
AltTabRestore<DX_PTR> * m_pRestore;
#ifndef NDEBUG
char const * m_pszFile;
unsigned m_nLine;
char * m_pszDebugString;
#endif
inline bool operator == (AltTabEntry const & rEntry) const
{ return m_pDxGraphic == rEntry.m_pDxGraphic; }
inline bool operator != (AltTabEntry const & rEntry) const
{ return ! operator == (rEntry); }
friend inline HashFunction(AltTabEntry const & rEntry)
{ return HashFunction(rEntry.m_pDxGraphic); }
};
struct AltTabLists
{
HashTable<AltTabEntry<D3DTexture> > m_listTextures;
HashTable<AltTabEntry<DDSurface> > m_listSurfaces;
};
#ifdef NDEBUG
static AltTabLists g_atlists;
#else
static
struct AltTabDebugLists : AltTabLists
{
~AltTabDebugLists()
{
// destructor for derived class will be called before destructor
// for base class, so we can make assersions about the base class:
// everything *should* have been removed from these lists before exiting
if (m_listSurfaces.Size())
{
db_logf1(("ERROR: AltTab lists still referring to %u surface(s) on exiting",m_listSurfaces.Size()));
unsigned i = 1;
for
(
HashTable<AltTabEntry<DDSurface> >::ConstIterator itSurfaces(m_listSurfaces);
!itSurfaces.Done(); itSurfaces.Next()
)
{
db_logf1(("\t%u. Included in line %u of %s (details: %s)",i++,itSurfaces.Get().m_nLine,itSurfaces.Get().m_pszFile,itSurfaces.Get().m_pszDebugString ? itSurfaces.Get().m_pszDebugString : "n/a"));
}
}
else
{
db_logf1(("OK on exiting: AltTab surface lists are clean"));
}
if (m_listTextures.Size())
{
db_logf1(("ERROR: AltTab lists still referring to %u texture(s) on exiting",m_listTextures.Size()));
unsigned i = 1;
for
(
HashTable<AltTabEntry<D3DTexture> >::ConstIterator itTextures(m_listTextures);
!itTextures.Done(); itTextures.Next()
)
{
db_logf1(("\t%u. Included in line %u of %s (details: %s)",i++,itTextures.Get().m_nLine,itTextures.Get().m_pszFile,itTextures.Get().m_pszDebugString ? itTextures.Get().m_pszDebugString : "n/a"));
}
}
else
{
db_logf1(("OK on exiting: AltTab texture lists are clean"));
}
}
}
g_atlists;
#endif
#ifdef NDEBUG
void ATIncludeTexture(D3DTexture * pTexture, AW_BACKUPTEXTUREHANDLE hBackup)
#else
void _ATIncludeTexture(D3DTexture * pTexture, AW_BACKUPTEXTUREHANDLE hBackup, char const * pszFile, unsigned nLine, char const * pszDebugString)
#endif
{
db_assert1(pTexture);
db_assert1(hBackup);
HashTable<AltTabEntry<D3DTexture> >::Node * pNewNode = g_atlists.m_listTextures.NewNode();
pNewNode->d.m_pDxGraphic = pTexture;
pNewNode->d.m_pRestore = new AltTabAwRestore<D3DTexture>(hBackup);
#ifndef NDEBUG
pNewNode->d.m_pszFile = pszFile;
pNewNode->d.m_nLine = nLine;
if (pszDebugString)
{
pNewNode->d.m_pszDebugString = new char [strlen(pszDebugString)+1];
strcpy(pNewNode->d.m_pszDebugString,pszDebugString);
}
else
pNewNode->d.m_pszDebugString = NULL;
#endif
g_atlists.m_listTextures.AddAsserted(pNewNode);
}
#ifdef NDEBUG
void ATIncludeSurface(DDSurface * pSurface, AW_BACKUPTEXTUREHANDLE hBackup)
#else
void _ATIncludeSurface(DDSurface * pSurface, AW_BACKUPTEXTUREHANDLE hBackup, char const * pszFile, unsigned nLine, char const * pszDebugString)
#endif
{
db_assert1(pSurface);
db_assert1(hBackup);
HashTable<AltTabEntry<DDSurface> >::Node * pNewNode = g_atlists.m_listSurfaces.NewNode();
pNewNode->d.m_pDxGraphic = pSurface;
pNewNode->d.m_pRestore = new AltTabAwRestore<DDSurface>(hBackup);
#ifndef NDEBUG
pNewNode->d.m_pszFile = pszFile;
pNewNode->d.m_nLine = nLine;
if (pszDebugString)
{
pNewNode->d.m_pszDebugString = new char [strlen(pszDebugString)+1];
strcpy(pNewNode->d.m_pszDebugString,pszDebugString);
}
else
pNewNode->d.m_pszDebugString = NULL;
#endif
g_atlists.m_listSurfaces.AddAsserted(pNewNode);
}
#ifdef NDEBUG
void ATIncludeTextureEx(D3DTexture * pTexture, AT_PFN_RESTORETEXTURE pfnRestore, void * pUser)
#else
void _ATIncludeTextureEx(D3DTexture * pTexture, AT_PFN_RESTORETEXTURE pfnRestore, void * pUser, char const * pszFile, unsigned nLine, char const * pszFuncName, char const * pszDebugString)
#endif
{
db_assert1(pTexture);
db_assert1(pfnRestore);
HashTable<AltTabEntry<D3DTexture> >::Node * pNewNode = g_atlists.m_listTextures.NewNode();
pNewNode->d.m_pDxGraphic = pTexture;
#ifndef NDEBUG
pNewNode->d.m_pRestore = new AltTabUserRestore<D3DTexture>(pfnRestore,pUser,pszFuncName);
pNewNode->d.m_pszFile = pszFile;
pNewNode->d.m_nLine = nLine;
if (pszDebugString)
{
pNewNode->d.m_pszDebugString = new char [strlen(pszDebugString)+1];
strcpy(pNewNode->d.m_pszDebugString,pszDebugString);
}
else
pNewNode->d.m_pszDebugString = NULL;
#else
pNewNode->d.m_pRestore = new AltTabUserRestore<D3DTexture>(pfnRestore,pUser);
#endif
g_atlists.m_listTextures.AddAsserted(pNewNode);
}
#ifdef NDEBUG
void ATIncludeSurfaceEx(DDSurface * pSurface, AT_PFN_RESTORESURFACE pfnRestore, void * pUser)
#else
void _ATIncludeSurfaceEx(DDSurface * pSurface, AT_PFN_RESTORESURFACE pfnRestore, void * pUser, char const * pszFile, unsigned nLine, char const * pszFuncName, char const * pszDebugString)
#endif
{
db_assert1(pSurface);
db_assert1(pfnRestore);
HashTable<AltTabEntry<DDSurface> >::Node * pNewNode = g_atlists.m_listSurfaces.NewNode();
pNewNode->d.m_pDxGraphic = pSurface;
#ifndef NDEBUG
pNewNode->d.m_pRestore = new AltTabUserRestore<DDSurface>(pfnRestore,pUser,pszFuncName);
pNewNode->d.m_pszFile = pszFile;
pNewNode->d.m_nLine = nLine;
if (pszDebugString)
{
pNewNode->d.m_pszDebugString = new char [strlen(pszDebugString)+1];
strcpy(pNewNode->d.m_pszDebugString,pszDebugString);
}
else
pNewNode->d.m_pszDebugString = NULL;
#else
pNewNode->d.m_pRestore = new AltTabUserRestore<DDSurface>(pfnRestore,pUser);
#endif
g_atlists.m_listSurfaces.AddAsserted(pNewNode);
}
void ATRemoveTexture(D3DTexture * pTexture)
{
db_assert1(pTexture);
AltTabEntry<D3DTexture> ateRemove;
ateRemove.m_pDxGraphic = pTexture;
AltTabEntry<D3DTexture> const * pEntry = g_atlists.m_listTextures.Contains(ateRemove);
db_assert1(pEntry);
db_assert1(pEntry->m_pRestore);
delete pEntry->m_pRestore;
#ifndef NDEBUG
if (pEntry->m_pszDebugString)
delete[] pEntry->m_pszDebugString;
#endif
g_atlists.m_listTextures.RemoveAsserted(ateRemove);
}
void ATRemoveSurface(DDSurface * pSurface)
{
db_assert1(pSurface);
AltTabEntry<DDSurface> ateRemove;
ateRemove.m_pDxGraphic = pSurface;
AltTabEntry<DDSurface> const * pEntry = g_atlists.m_listSurfaces.Contains(ateRemove);
db_assert1(pEntry);
db_assert1(pEntry->m_pRestore);
delete pEntry->m_pRestore;
#ifndef NDEBUG
if (pEntry->m_pszDebugString)
delete[] pEntry->m_pszDebugString;
#endif
g_atlists.m_listSurfaces.RemoveAsserted(ateRemove);
}
void ATOnAppReactivate()
{
db_log1("ATOnAppReactivate() called");
// surfaces
for
(
HashTable<AltTabEntry<DDSurface> >::ConstIterator itSurfaces(g_atlists.m_listSurfaces);
!itSurfaces.Done(); itSurfaces.Next()
)
{
DDSurface * pSurface = itSurfaces.Get().m_pDxGraphic;
db_logf5(("\tIs surface %p lost?? [included at line %u of %s (details: %s)]",pSurface,itSurfaces.Get().m_nLine,itSurfaces.Get().m_pszFile,itSurfaces.Get().m_pszDebugString ? itSurfaces.Get().m_pszDebugString : "n/a"));
HRESULT hResult = pSurface->IsLost();
if (DDERR_SURFACELOST == hResult)
{
db_logf4(("\t\tSurface %p is lost - restoring",pSurface));
hResult = pSurface->Restore();
if (DD_OK == hResult)
{
db_logf5(("\t\tRestore() returned DD_OK",pSurface));
db_assert1(itSurfaces.Get().m_pRestore);
itSurfaces.Get().m_pRestore->DoRestore(pSurface);
}
else
{
db_logf1(("\t\tERROR [%p->Restore()] %s",pSurface,AwDxErrorToString(hResult)));
}
}
else if (DD_OK != hResult)
{
db_logf1(("\t\tERROR [%p->IsLost()] %s",pSurface,AwDxErrorToString(hResult)));
}
else
{
db_logf5(("\t\tSurface %p wasn't lost",pSurface));
}
}
// textures
for
(
HashTable<AltTabEntry<D3DTexture> >::ConstIterator itTextures(g_atlists.m_listTextures);
!itTextures.Done(); itTextures.Next()
)
{
D3DTexture * pTexture = itTextures.Get().m_pDxGraphic;
db_logf5(("\tIs texture %p lost?? [included at line %u of %s (details: %s)]",pTexture,itTextures.Get().m_nLine,itTextures.Get().m_pszFile,itTextures.Get().m_pszDebugString ? itTextures.Get().m_pszDebugString : "n/a"));
DDSurface * pSurface;
HRESULT hResult = pTexture->QueryInterface(GUID_DD_SURFACE,reinterpret_cast<void * *>(&pSurface));
if (DD_OK != hResult)
{
db_logf1(("\t\tERROR [%p->QueryInterface(GUID_DD_SURFACE,%p)] %s",pTexture,&pSurface,AwDxErrorToString(hResult)));
}
else
{
hResult = pSurface->IsLost();
if (DDERR_SURFACELOST == hResult)
{
db_logf4(("\t\tTexture %p is lost - restoring",pTexture));
hResult = pSurface->Restore();
if (DD_OK == hResult)
{
db_logf5(("\t\tRestore() returned DD_OK",pTexture));
db_assert1(itTextures.Get().m_pRestore);
itTextures.Get().m_pRestore->DoRestore(pTexture);
}
else
{
db_logf1(("\t\tERROR [%p->Restore()] %s",pTexture,AwDxErrorToString(hResult)));
}
}
else if (DD_OK != hResult)
{
db_logf1(("\t\tERROR [%p->IsLost()] %s",pTexture,AwDxErrorToString(hResult)));
}
else
{
db_logf5(("\t\tTexture %p wasn't lost",pTexture));
}
// don't need this reference anymore
pSurface->Release();
}
}
db_log1("ATOnAppReactivate() returning");
}

47
src/win95/alt_tab.h Normal file
View file

@ -0,0 +1,47 @@
/*
JH - 18/02/98
Deal with lost surfaces and textures - restore them when the application is re-activated
*/
#ifndef _INCLUDED_ALT_TAB_H_
#define _INCLUDED_ALT_TAB_H_
#include "aw.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef void (* AT_PFN_RESTORETEXTURE) (D3DTexture * pTexture, void * pUser);
typedef void (* AT_PFN_RESTORESURFACE) (DDSurface * pSurface, void * pUser);
#ifdef NDEBUG
extern void ATIncludeTexture(D3DTexture * pTexture, AW_BACKUPTEXTUREHANDLE hBackup);
extern void ATIncludeTextureEx(D3DTexture * pTexture, AT_PFN_RESTORETEXTURE pfnRestore, void * pUser);
extern void ATIncludeSurface(DDSurface * pSurface, AW_BACKUPTEXTUREHANDLE hBackup);
extern void ATIncludeSurfaceEx(DDSurface * pSurface, AT_PFN_RESTORESURFACE pfnRestore, void * pUser);
#else
extern void _ATIncludeTexture(D3DTexture * pTexture, AW_BACKUPTEXTUREHANDLE hBackup, char const * pszFile, unsigned nLine, char const * pszDebugString);
extern void _ATIncludeTextureEx(D3DTexture * pTexture, AT_PFN_RESTORETEXTURE pfnRestore, void * pUser, char const * pszFile, unsigned nLine, char const * pszFuncName, char const * pszDebugString);
extern void _ATIncludeSurface(DDSurface * pSurface, AW_BACKUPTEXTUREHANDLE hBackup, char const * pszFile, unsigned nLine, char const * pszDebugString);
extern void _ATIncludeSurfaceEx(DDSurface * pSurface, AT_PFN_RESTORESURFACE pfnRestore, void * pUser, char const * pszFile, unsigned nLine, char const * pszFuncName, char const * pszDebugString);
#define ATIncludeTexture(p,h) _ATIncludeTexture(p,h,__FILE__,__LINE__,NULL)
#define ATIncludeTextureEx(p,f,u) _ATIncludeTextureEx(p,f,u,__FILE__,__LINE__,#f ,NULL)
#define ATIncludeSurface(p,h) _ATIncludeSurface(p,h,__FILE__,__LINE__,NULL)
#define ATIncludeSurfaceEx(p,f,u) _ATIncludeSurfaceEx(p,f,u,__FILE__,__LINE__,#f ,NULL)
#define ATIncludeTextureDb(p,h,d) _ATIncludeTexture(p,h,__FILE__,__LINE__,d)
#define ATIncludeTextureExDb(p,f,u,d) _ATIncludeTextureEx(p,f,u,__FILE__,__LINE__,#f ,d)
#define ATIncludeSurfaceDb(p,h,d) _ATIncludeSurface(p,h,__FILE__,__LINE__,d)
#define ATIncludeSurfaceExDb(p,f,u,d) _ATIncludeSurfaceEx(p,f,u,__FILE__,__LINE__,#f ,d)
#endif
extern void ATRemoveTexture(D3DTexture * pTexture);
extern void ATRemoveSurface(DDSurface * pSurface);
extern void ATOnAppReactivate();
#ifdef __cplusplus
}
#endif
#endif /* ! _INCLUDED_ALT_TAB_H_ */

270
src/win95/animchnk.cpp Normal file
View file

@ -0,0 +1,270 @@
#include "animchnk.hpp"
//macro for helping to force inclusion of chunks when using libraries
FORCE_CHUNK_INCLUDE_IMPLEMENT(animchnk)
RIF_IMPLEMENT_DYNCREATE("TEXTANIM",Animation_Chunk)
Animation_Chunk::Animation_Chunk(Chunk_With_Children* parent)
: Chunk(parent, "TEXTANIM")
{
NumPolys=0;
AnimList=0;
}
Animation_Chunk::Animation_Chunk(Chunk_With_Children* parent,const char* data,size_t /*datasize*/)
: Chunk(parent, "TEXTANIM")
{
NumPolys=*((int*)data);
data+=4;
if(NumPolys)
{
AnimList=(TEXANIM**)malloc(NumPolys*sizeof(TEXANIM*));
for(int i=0;i<NumPolys;i++)
{
AnimList[i]=new TEXANIM;
TEXANIM* ta=AnimList[i];
ta->poly=*((int*)data);
data+=4;
ta->ID=*((int*)data);
data+=4;
ta->NumSeq=*((int*)data);
data+=4;
ta->NumVerts=*((int*)data);
data+=4;
ta->AnimFlags=*((int*)data);
data+=4;
ta->Identifier=*((int*)data);
data+=4;
ta->CurSeq=0;
ta->Seq=new FrameList*[ta->NumSeq];
for(int j=0;j<ta->NumSeq;j++)
{
ta->Seq[j]=new FrameList(ta);
FrameList* fl=ta->Seq[j];
fl->Speed=*((int*)data);
data+=4;
fl->Flags=*((int*)data);
data+=4;
fl->NumFrames=*((int*)data);
data+=4;
fl->spare1=*((int*)data);
data+=4;
fl->spare2=*((int*)data);
data+=4;
fl->CurFrame=0;
fl->Textures=new int[fl->NumFrames];
fl->UVCoords=new int[(2*ta->NumVerts)*fl->NumFrames];
for(int k=0;k<fl->NumFrames;k++)
{
fl->Textures[k]=*((int*)data);
data+=4;
}
for(k=0;k<(2*ta->NumVerts)*fl->NumFrames;k++)
{
fl->UVCoords[k]=*((int*)data);
data+=4;
}
}
}
}
else
AnimList=0;
}
Animation_Chunk::~Animation_Chunk()
{
for(int i=0;i<NumPolys;i++)
{
delete AnimList[i];
}
free(AnimList);
}
size_t Animation_Chunk::size_chunk()
{
chunk_size=12+4;
for(int i=0;i<NumPolys;i++)
{
chunk_size+=24;
TEXANIM* ta=AnimList[i];
for(int j=0;j<ta->NumSeq;j++)
{
chunk_size+=20;
chunk_size+=4*(1+2*ta->NumVerts)*ta->Seq[j]->NumFrames;
}
}
return chunk_size;
}
BOOL Animation_Chunk::output_chunk (HANDLE &hand)
{
unsigned long junk;
BOOL ok;
char * data_block;
data_block = this->make_data_block_from_chunk();
ok = WriteFile (hand, (long *) data_block, (unsigned long) chunk_size, &junk, 0);
delete [] data_block;
if (!ok) return FALSE;
return TRUE;
}
void Animation_Chunk::fill_data_block(char* data_start)
{
strncpy (data_start, identifier, 8);
data_start += 8;
*((int *) data_start) = chunk_size;
data_start += 4;
*(int*)data_start=NumPolys;
data_start+=4;
for(int i=0;i<NumPolys;i++)
{
TEXANIM* ta=AnimList[i];
*(int*)data_start=ta->poly;
data_start+=4;
*(int*)data_start=ta->ID;
data_start+=4;
*(int*)data_start=ta->NumSeq;
data_start+=4;
*(int*)data_start=ta->NumVerts;
data_start+=4;
*(int*)data_start=ta->AnimFlags;
data_start+=4;
*(int*)data_start=ta->Identifier;
data_start+=4;
for(int j=0;j<ta->NumSeq;j++)
{
FrameList* fl=ta->Seq[j];
*(int*)data_start=fl->Speed;
data_start+=4;
*(int*)data_start=fl->Flags;
data_start+=4;
*(int*)data_start=fl->NumFrames;
data_start+=4;
*(int*)data_start=fl->spare1;
data_start+=4;
*(int*)data_start=fl->spare2;
data_start+=4;
for(int k=0;k<fl->NumFrames;k++)
{
*(int*)data_start=fl->Textures[k];
data_start+=4;
}
for(k=0;k<(2*ta->NumVerts)*fl->NumFrames;k++)
{
*(int*)data_start=fl->UVCoords[k];
data_start+=4;
}
}
}
}
FrameList::FrameList(TEXANIM* p)
{
Speed=65536;
Flags=0;
NumFrames=0;
CurFrame=-1;
parent=p;
Textures=0;
UVCoords=0;
spare1=spare2=0;
}
FrameList::FrameList(TEXANIM* p,FrameList* fl,int* conv)
{
Speed=fl->Speed;
Flags=fl->Flags;
NumFrames=fl->NumFrames;
parent=p;
Textures=new int[NumFrames];
UVCoords=new int[NumFrames*2*p->NumVerts];
spare1=fl->spare1;
spare2=fl->spare2;
if(conv)
{
for(int i=0;i<NumFrames;i++)
{
Textures[i]=conv[fl->Textures[i]];
}
}
else
{
for(int i=0;i<NumFrames;i++)
{
Textures[i]=fl->Textures[i];
}
}
for(int i=0;i<NumFrames*2*p->NumVerts;i++)
{
UVCoords[i]=fl->UVCoords[i];
}
CurFrame=0;
}
FrameList::~FrameList()
{
delete [] Textures;
delete UVCoords;
}
TEXANIM::TEXANIM()
{
shape=0;
NumSeq=0;
CurSeq=-1;
Seq=0;
NumVerts=3;
AnimFlags=Identifier=0;
}
TEXANIM::TEXANIM(TEXANIM* ta)
{
shape=0;
NumSeq=0;
CurSeq=-1;
Seq=0;
NumVerts=3;
AnimFlags=Identifier=0;
CopyAnimData(ta,0);
}
TEXANIM::~TEXANIM()
{
for(int i=0;i<NumSeq;i++)
{
delete Seq[i];
}
delete [] Seq;
}
void TEXANIM::CopyAnimData(TEXANIM* ta,int*conv)
{
shape=ta->shape;
poly=ta->poly;
ID=ta->ID;
NumSeq=ta->NumSeq;
CurSeq=0;
Seq=new FrameList*[NumSeq];
NumVerts=ta->NumVerts;
AnimFlags=ta->AnimFlags;
Identifier=ta->Identifier;
for(int i=0;i<NumSeq;i++)
{
Seq[i]=new FrameList(this,ta->Seq[i],conv);
}
}

88
src/win95/animchnk.hpp Normal file
View file

@ -0,0 +1,88 @@
#ifndef _animchnk_hpp
#define _animchnk_hpp
#include "chunk.hpp"
#include "Chnktype.hpp"
struct TEXANIM;
class Animation_Chunk : public Chunk
{
public :
Animation_Chunk(Chunk_With_Children* parent,const char*,size_t);
Animation_Chunk(Chunk_With_Children* parent);
~Animation_Chunk();
virtual BOOL output_chunk (HANDLE &hand);
virtual size_t size_chunk();
virtual void fill_data_block(char* data_start);
int NumPolys; //with animation in this shape
TEXANIM** AnimList;
};
#define txa_flag_nointerptofirst 0x80000000
struct FrameList
{
~FrameList();
FrameList(TEXANIM*);
#if InterfaceEngine
FrameList(TEXANIM* p,FrameList* templ);
#endif
FrameList(TEXANIM* p,FrameList* fl,int* conv);
int Speed;
int Flags;
int NumFrames;
int CurFrame;
TEXANIM* parent;
int* Textures;
int* UVCoords;
int spare1,spare2;
#if InterfaceEngine
void CopyToSID(int shape,int poly);
void CopyFromSID(int shape,int poly);
void AddFrame();
void RemoveFrame();
#endif
};
#define AnimFlag_NotPlaying 0x00000001
struct TEXANIM
{
TEXANIM(TEXANIM*);
TEXANIM();
~TEXANIM();
#if InterfaceEngine
TEXANIM(int s,int p,int id);
//construct a TEXANIM using templ as a template.
TEXANIM(int s,int p,TEXANIM* templ);
#endif
int shape;
int poly;
int NumVerts;
int ID;
int NumSeq;//number of sequences
int CurSeq;
int AnimFlags;
int Identifier;
FrameList** Seq;
#if InterfaceEngine
void ChangeFrame(int newseq,int newframe);
void AddSeq();
void RemoveSeq();
void CopySeq(int seq_num);
#endif
void CopyAnimData(TEXANIM* ta,int* conv);
};
#endif

593
src/win95/animobs.cpp Normal file
View file

@ -0,0 +1,593 @@
#include "hierchnk.hpp"
#include "Animobs.hpp"
#include "list_tem.hpp"
#include <math.h>
//macro for helping to force inclusion of chunks when using libraries
FORCE_CHUNK_INCLUDE_IMPLEMENT(animobs)
RIF_IMPLEMENT_DYNCREATE("OBASEQFR",Object_Animation_Sequence_Frame_Chunk)
void Object_Animation_Sequence_Frame_Chunk::fill_data_block (char *data_start)
{
strncpy (data_start, identifier, 8);
data_start += 8;
*((int *) data_start) = chunk_size;
data_start += 4;
*((float *) data_start) = orientation.x;
data_start += 4;
*((float *) data_start) = orientation.y;
data_start += 4;
*((float *) data_start) = orientation.z;
data_start += 4;
*((float *) data_start) = orientation.w;
data_start += 4;
*((int *) data_start) = transform.x;
data_start += 4;
*((int *) data_start) = transform.y;
data_start += 4;
*((int *) data_start) = transform.z;
data_start += 4;
*((int *) data_start) = at_frame_no;
data_start += 4;
*((int *) data_start) = frame_ref_no;
data_start += 4;
*((int *) data_start) = flags;
data_start += 4;
*(int*) data_start=num_extra_data;
data_start+=4;
for (int i=0; i<num_extra_data; i++)
{
*((int *) data_start) = extra_data[i];
data_start += 4;
}
}
#if UseOldChunkLoader
Object_Animation_Sequence_Frame_Chunk::Object_Animation_Sequence_Frame_Chunk (Object_Animation_Sequence_Chunk * parent,const char *data_start, size_t)
: Chunk (parent, "OBASEQFR")
{
orientation.x = -(*(double *) data_start);
data_start += 8;
orientation.y = -(*(double *) data_start);
data_start += 8;
orientation.z = -(*(double *) data_start);
data_start += 8;
orientation.w = (*(double *) data_start);
data_start += 8;
transform.x = *((double *) data_start);
data_start += 8;
transform.y = *((double *) data_start);
data_start += 8;
transform.z = *((double *) data_start);
data_start += 8;
at_frame_no = *((int *) data_start);
data_start += 4;
frame_ref_no = *((int *) data_start);
data_start += 4;
flags = *((int *) data_start);
data_start += 4;
num_extra_data=0;
extra_data=0;
}
#else
Object_Animation_Sequence_Frame_Chunk::Object_Animation_Sequence_Frame_Chunk (Chunk_With_Children * parent,const char *data_start, size_t)
: Chunk (parent, "OBASEQFR")
{
orientation.x = *((float *) data_start);
data_start += 4;
orientation.y = *((float *) data_start);
data_start += 4;
orientation.z = *((float *) data_start);
data_start += 4;
orientation.w = *((float *) data_start);
data_start += 4;
transform.x = *((int *) data_start);
data_start += 4;
transform.y = *((int *) data_start);
data_start += 4;
transform.z = *((int *) data_start);
data_start += 4;
at_frame_no = *((int *) data_start);
data_start += 4;
frame_ref_no = *((int *) data_start);
data_start += 4;
flags = *((int *) data_start);
data_start += 4;
num_extra_data=*(int*) data_start;
data_start+=4;
if(num_extra_data)
extra_data=new int[num_extra_data];
else
extra_data=0;
for (int i=0; i<num_extra_data; i++)
{
extra_data[i] = *((int *) data_start);
data_start += 4;
}
}
#endif
void Object_Animation_Sequence_Frame_Chunk::set_sound_index(int ind)
{
if(ind>=0 && ind<=127)
{
flags &=~HierarchyFrame_SoundIndexMask;
flags |= (ind<<24);
}
}
RIF_IMPLEMENT_DYNCREATE("OBASEQHD",Object_Animation_Sequence_Header_Chunk)
void Object_Animation_Sequence_Header_Chunk::fill_data_block (char *data_start)
{
strncpy (data_start, identifier, 8);
data_start += 8;
*((int *) data_start) = chunk_size;
data_start += 4;
*((int *) data_start) = num_frames;
data_start += 4;
*((int *) data_start) = sequence_number;
data_start += 4;
*((int *) data_start) = sub_sequence_number;
data_start += 4;
*(int*)data_start=num_extra_data;
data_start+=4;
for (int i=0; i<num_extra_data; i++)
{
*((int *) data_start) = extra_data[i];
data_start += 4;
}
if (sequence_name)
{
sprintf (data_start, "%s", sequence_name);
}
else
{
*data_start = 0;
}
}
Object_Animation_Sequence_Header_Chunk::~Object_Animation_Sequence_Header_Chunk()
{
if (sequence_name)
delete sequence_name;
if(extra_data)
delete extra_data;
}
#if UseOldChunkLoader
Object_Animation_Sequence_Header_Chunk::Object_Animation_Sequence_Header_Chunk (Chunk_With_Children * parent,const char * data_start, size_t)
: Chunk (parent, "OBASEQHD"), sequence_name (0)
{
num_frames = *((int *) data_start);
data_start += 4;
sequence_number = *((int *) data_start);
data_start += 4;
sub_sequence_number = *((int *) data_start);
data_start += 4;
num_extra_data=0;
extra_data=0;
data_start+=40;
if (strlen(data_start))
{
sequence_name = new char [strlen(data_start) + 1];
strcpy (sequence_name, data_start);
}
}
#else
Object_Animation_Sequence_Header_Chunk::Object_Animation_Sequence_Header_Chunk (Chunk_With_Children * parent,const char * data_start, size_t)
: Chunk (parent, "OBASEQHD"), sequence_name (0)
{
num_frames = *((int *) data_start);
data_start += 4;
sequence_number = *((int *) data_start);
data_start += 4;
sub_sequence_number = *((int *) data_start);
data_start += 4;
num_extra_data=*(int*) data_start;
data_start+=4;
if(num_extra_data)
extra_data=new int[num_extra_data];
else
extra_data=0;
for (int i=0; i<num_extra_data; i++)
{
extra_data[i] = *((int *) data_start);
data_start += 4;
}
if (strlen(data_start))
{
sequence_name = new char [strlen(data_start) + 1];
strcpy (sequence_name, data_start);
}
}
#endif
Object_Animation_Sequence_Header_Chunk * Object_Animation_Sequence_Chunk::get_header()
{
return(Object_Animation_Sequence_Header_Chunk *) lookup_single_child("OBASEQHD");
}
void Object_Animation_Sequence_Chunk::get_frames(List <Object_Animation_Sequence_Frame_Chunk*> *pList)
{
List <Chunk *> cl;
lookup_child ("OBASEQFR",cl);
for (LIF<Chunk *> cli(&cl); !cli.done(); cli.next())
{
pList->add_entry((Object_Animation_Sequence_Frame_Chunk *)cli());
}
}
////////////////////////////////
RIF_IMPLEMENT_DYNCREATE("OBANSEQS",Object_Animation_Sequences_Chunk)
void Object_Animation_Sequences_Chunk::list_sequences(List <Object_Animation_Sequence_Chunk *> * pList)
{
List <Chunk *> cl;
lookup_child ("OBANSEQC",cl);
for (LIF<Chunk *> cli(&cl); !cli.done(); cli.next())
{
pList->add_entry((Object_Animation_Sequence_Chunk *)cli());
}
}
Object_Animation_Sequence_Chunk::Object_Animation_Sequence_Chunk(Object_Animation_Sequences_Chunk* parent,Object_Animation_Sequence_Chunk* template_seq,ChunkQuat & orient ,ChunkVectorInt & trans)
:Chunk_With_Children (parent, "OBANSEQC")
{
Object_Animation_Sequence_Header_Chunk* template_header=template_seq->get_header();
Object_Animation_Sequence_Header_Chunk* header=new Object_Animation_Sequence_Header_Chunk(this);
header->num_frames=65536;
header->sequence_number=template_header->sequence_number;
header->sub_sequence_number=template_header->sub_sequence_number;
header->sequence_name=new char[strlen(template_header->sequence_name)+1];
strcpy(header->sequence_name,template_header->sequence_name);
Object_Animation_Sequence_Frame_Chunk* oasfc=new Object_Animation_Sequence_Frame_Chunk(this);
oasfc->orientation=orient;
oasfc->transform=trans;
oasfc->at_frame_no=0;
oasfc->frame_ref_no=0;
//see if template sequence is a delta sequence
List<Object_Animation_Sequence_Frame_Chunk*> framelist;
template_seq->get_frames(&framelist);
while(framelist.size())
{
if(framelist.first_entry()->flags & HierarchyFrameFlag_DeltaFrame)
{
oasfc->flags=HierarchyFrameFlag_DeltaFrame;
break;
}
framelist.delete_first_entry();
}
}
Object_Animation_Sequence_Chunk * Object_Animation_Sequences_Chunk::get_sequence (int num, int subnum)
{
List <Object_Animation_Sequence_Chunk *> seq_list;
list_sequences(&seq_list);
for (LIF<Object_Animation_Sequence_Chunk *> sli(&seq_list); !sli.done(); sli.next())
{
Object_Animation_Sequence_Header_Chunk * oashc = sli()->get_header();
if (oashc)
{
if (oashc->sequence_number == num && oashc->sub_sequence_number == subnum)
{
break;
}
}
}
if (!sli.done())
{
return(sli());
}
else
{
return(0);
}
}
int Object_Animation_Sequence_Chunk::get_sequence_time()
{
Object_Animation_Sequence_Time_Chunk* time_chunk=(Object_Animation_Sequence_Time_Chunk*)lookup_single_child("OBASEQTM");
if(time_chunk)
{
return time_chunk->sequence_time;
}
return 0;
}
int Object_Animation_Sequence_Chunk::get_sequence_speed()
{
Object_Animation_Sequence_Speed_Chunk* speed_chunk=(Object_Animation_Sequence_Speed_Chunk*)lookup_single_child("OBASEQSP");
if(speed_chunk)
{
return speed_chunk->sequence_speed;
}
return 0;
}
BOOL Object_Animation_Sequence_Chunk::get_sequence_vector(ChunkVectorFloat* direction)
{
if(!direction) return FALSE;
//default direction is forwards
direction->x=0;
direction->y=0;
direction->z=1;
Object_Animation_Sequence_Speed_Chunk* speed_chunk=(Object_Animation_Sequence_Speed_Chunk*)lookup_single_child("OBASEQSP");
if(speed_chunk)
{
double radian_angle=(speed_chunk->angle/360.0)*2*3.1415278;
direction->x =(float) sin(radian_angle);
direction->z =(float) cos(radian_angle);
return TRUE;
}
else
{
return FALSE;
}
}
int Object_Animation_Sequence_Chunk::get_sequence_flags()
{
Object_Animation_Sequence_Flags_Chunk* flag_chunk=(Object_Animation_Sequence_Flags_Chunk*)lookup_single_child("OBASEQFL");
if(flag_chunk)
{
return flag_chunk->flags;
}
return 0;
}
void Object_Animation_Sequence_Chunk::set_sequence_flags(int new_flags)
{
//find existing flag_chunk , or create a new one
Object_Animation_Sequence_Flags_Chunk* flag_chunk=(Object_Animation_Sequence_Flags_Chunk*)lookup_single_child("OBASEQFL");
if(flag_chunk)
{
//set the flags
flag_chunk->flags = new_flags;
}
else
{
//create a new chunk then
new Object_Animation_Sequence_Flags_Chunk(this,new_flags);
}
}
Hierarchy_Bounding_Box_Chunk* Object_Animation_Sequence_Chunk::get_bounding_box()
{
return (Hierarchy_Bounding_Box_Chunk*)lookup_single_child("HIERBBOX");
}
////////////////////////////////////////////////////////////////////////////////
/*--------------------------------------**
** Object_Animation_Sequence_Time_Chunk **
**--------------------------------------*/
RIF_IMPLEMENT_DYNCREATE("OBASEQTM",Object_Animation_Sequence_Time_Chunk)
Object_Animation_Sequence_Time_Chunk::Object_Animation_Sequence_Time_Chunk (Chunk_With_Children * parent,const char * data_start, size_t)
: Chunk (parent, "OBASEQTM")
{
sequence_time=*(unsigned int*) data_start;
}
void Object_Animation_Sequence_Time_Chunk::fill_data_block(char* data_start)
{
strncpy (data_start, identifier, 8);
data_start += 8;
*((int *) data_start) = chunk_size;
data_start += 4;
*(unsigned int*) data_start = sequence_time;
}
////////////////////////////////////////////////////////////////////////////////
/*---------------------------------------**
** Object_Animation_Sequence_Speed_Chunk **
**---------------------------------------*/
RIF_IMPLEMENT_DYNCREATE("OBASEQSP",Object_Animation_Sequence_Speed_Chunk)
Object_Animation_Sequence_Speed_Chunk::Object_Animation_Sequence_Speed_Chunk (Chunk_With_Children * parent,const char * data, size_t)
: Chunk (parent, "OBASEQSP")
{
CHUNK_EXTRACT(sequence_speed,int)
CHUNK_EXTRACT(angle,int)
CHUNK_EXTRACT(spare,int)
}
void Object_Animation_Sequence_Speed_Chunk::fill_data_block(char* data)
{
CHUNK_FILL_START
CHUNK_FILL(sequence_speed,int)
CHUNK_FILL(angle,int)
CHUNK_FILL(spare,int)
}
////////////////////////////////////////////////////////////////////////////////
/*---------------------------------------**
** Object_Animation_Sequence_Flags_Chunk **
**---------------------------------------*/
RIF_IMPLEMENT_DYNCREATE("OBASEQFL",Object_Animation_Sequence_Flags_Chunk)
Object_Animation_Sequence_Flags_Chunk::Object_Animation_Sequence_Flags_Chunk (Chunk_With_Children * parent,const char * data, size_t)
: Chunk (parent, "OBASEQFL")
{
CHUNK_EXTRACT(flags,int)
}
void Object_Animation_Sequence_Flags_Chunk::fill_data_block(char* data)
{
CHUNK_FILL_START
CHUNK_FILL(flags,int)
}
////////////////////////////////////////////////////////////////////////////////
RIF_IMPLEMENT_DYNCREATE("OBANALLS",Object_Animation_All_Sequence_Chunk)
Object_Animation_All_Sequence_Chunk::Object_Animation_All_Sequence_Chunk(Chunk_With_Children* parent)
:Chunk(parent,"OBANALLS")
{
num_sequences=0;
sequences=0;
}
Object_Animation_All_Sequence_Chunk::Object_Animation_All_Sequence_Chunk(Chunk_With_Children * const parent,const char * data, const size_t)
:Chunk(parent,"OBANALLS")
{
num_sequences=*(int*)data;
data+=4;
if(num_sequences) sequences=new Object_Animation_Sequence[num_sequences];
else sequences=0;
for(int i=0;i<num_sequences;i++)
{
Object_Animation_Sequence* seq=&sequences[i];
seq->num_frames=*(int*)data;
data+=4;
seq->sequence_number=*(int*)data;
data+=4;
seq->sub_sequence_number=*(int*)data;
data+=4;
seq->sequence_time=*(int*)data;
data+=4;
if(seq->num_frames) seq->frames=new Object_Animation_Frame[seq->num_frames];
else seq->frames=0;
for(unsigned j=0;j<seq->num_frames;j++)
{
seq->frames[j]=*(Object_Animation_Frame*)data;
data+=sizeof(Object_Animation_Frame);
}
}
}
void Object_Animation_All_Sequence_Chunk::fill_data_block(char* data)
{
strncpy (data, identifier, 8);
data += 8;
*((int *) data) = chunk_size;
data += 4;
*(int*)data=num_sequences;
data+=4;
for(int i=0;i<num_sequences;i++)
{
Object_Animation_Sequence* seq=&sequences[i];
*(int*)data=seq->num_frames;
data+=4;
*(int*)data=seq->sequence_number;
data+=4;
*(int*)data=seq->sub_sequence_number;
data+=4;
*(int*)data=seq->sequence_time;
data+=4;
for(unsigned j=0;j<seq->num_frames;j++)
{
*(Object_Animation_Frame*)data=seq->frames[j];
data+=sizeof(Object_Animation_Frame);
}
}
}
size_t Object_Animation_All_Sequence_Chunk::size_chunk()
{
chunk_size=12+4;
chunk_size+=num_sequences*16;
for(int i=0;i<num_sequences;i++)
{
chunk_size+=sequences[i].num_frames*sizeof(Object_Animation_Frame);
}
return chunk_size;
}
////////////////////////////////////////////////////////////////////////////////
//loader for Object_Animation_Sequences_Chunk
CHUNK_WITH_CHILDREN_LOADER("OBANSEQS",Object_Animation_Sequences_Chunk)
//Object_Animation_Sequence_Chunk
RIF_IMPLEMENT_DYNCREATE("OBANSEQC",Object_Animation_Sequence_Chunk)
//loader for Object_Animation_Sequence_Chunk
CHUNK_WITH_CHILDREN_LOADER("OBANSEQC",Object_Animation_Sequence_Chunk)

286
src/win95/animobs.hpp Normal file
View file

@ -0,0 +1,286 @@
#ifndef _animobs_hpp
#define _animobs_hpp 1
#include "chunk.hpp"
#include "chnktype.hpp"
class Object_Animation_Sequence_Header_Chunk;
class Object_Animation_Sequence_Frame_Chunk;
class Object_Animation_Sequence_Chunk;
class Hierarchy_Bounding_Box_Chunk;
class Object_Animation_Sequences_Chunk : public Chunk_With_Children
{
public:
Object_Animation_Sequences_Chunk (Chunk_With_Children * parent)
: Chunk_With_Children (parent, "OBANSEQS")
{}
Object_Animation_Sequences_Chunk (Chunk_With_Children * const parent,const char *, const size_t);
void list_sequences(List <Object_Animation_Sequence_Chunk *> * pList);
Object_Animation_Sequence_Chunk * get_sequence (int num, int sub_num);
private:
friend class Object_Chunk;
friend class Object_Hierarchy_Chunk;
};
class Object_Animation_Sequence_Chunk : public Chunk_With_Children
{
public:
Object_Animation_Sequence_Chunk (Object_Animation_Sequences_Chunk * parent)
: Chunk_With_Children (parent, "OBANSEQC")
{}
Object_Animation_Sequence_Chunk (Chunk_With_Children * const parent,const char *, const size_t);
//creates sequence of one frame ,with name taken from template_seq
Object_Animation_Sequence_Chunk(Object_Animation_Sequences_Chunk * parent,Object_Animation_Sequence_Chunk* template_seq,ChunkQuat& orient,ChunkVectorInt& trans);
Object_Animation_Sequence_Header_Chunk * get_header();
void get_frames(List <Object_Animation_Sequence_Frame_Chunk *>* );
int get_sequence_time(); //gets time in ms
int get_sequence_speed(); //gets movement speed in mm/second
//get (normalised) direction of movement for sequence
//if no direction has been set then returns false , and sets direction to a forward vector
BOOL get_sequence_vector(ChunkVectorFloat* direction);
//getting and setting flags for this sequence
int get_sequence_flags();
void set_sequence_flags(int new_flags);
Hierarchy_Bounding_Box_Chunk* get_bounding_box(); //gets the chunk with the bounding box for the sequence
private:
friend class Object_Animation_Sequences_Chunk;
};
#define HierarchyFrameFlag_DeltaFrame 0x80000000
#define HierarchyFrame_SoundIndexMask 0x7f000000
#define HierarchyFrame_FlagMask 0x00ffffff
class Object_Animation_Sequence_Frame_Chunk : public Chunk
{
public:
Object_Animation_Sequence_Frame_Chunk (Object_Animation_Sequence_Chunk * parent)
: Chunk (parent, "OBASEQFR"), at_frame_no (-1), frame_ref_no (-1)
{
ChunkQuat identity = {0,0,0,1};
orientation = identity;
transform.x = 0;
transform.y = 0;
transform.z = 0;
flags =0;
num_extra_data=0;
extra_data=0;
}
Object_Animation_Sequence_Frame_Chunk (Chunk_With_Children * parent,const char *, size_t);
~Object_Animation_Sequence_Frame_Chunk(){if(extra_data) delete extra_data;}
ChunkQuat orientation;
ChunkVectorInt transform;
signed long at_frame_no; //frame start time (0-65535)
signed long frame_ref_no; //frame index number
int flags;
int num_extra_data;
int* extra_data;
virtual void fill_data_block (char *);
virtual size_t size_chunk ()
{
return(chunk_size = 12 + 4*4 + 3*4 + 4 + 4 + 8+4*num_extra_data);
}
void set_sound_index(int ind);
int get_sound_index(){return ((flags & HierarchyFrame_SoundIndexMask )>>24);}
private:
friend class Object_Animation_Sequence_Chunk;
};
class Object_Animation_Sequence_Header_Chunk : public Chunk
{
public:
Object_Animation_Sequence_Header_Chunk(Chunk_With_Children * parent)
: Chunk (parent, "OBASEQHD"), num_frames (0), sequence_number (-1),
sub_sequence_number (-1), sequence_name (0)
{
num_extra_data=0;
extra_data=0;
}
Object_Animation_Sequence_Header_Chunk (Chunk_With_Children * parent,const char *, size_t);
~Object_Animation_Sequence_Header_Chunk();
unsigned long num_frames;
signed long sequence_number;
signed long sub_sequence_number;
int num_extra_data;
int* extra_data;
char * sequence_name;
virtual void fill_data_block (char *);
virtual size_t size_chunk ()
{
if (sequence_name)
{
return(chunk_size = 12 + 16 + 4*num_extra_data + strlen(sequence_name) + 4 - strlen(sequence_name)%4);
}
else
{
return(chunk_size = 12 + 16 + 4*num_extra_data + 4);
}
}
private:
friend class Object_Animation_Sequence_Chunk;
};
class Object_Animation_Sequence_Time_Chunk : public Chunk
{
public :
Object_Animation_Sequence_Time_Chunk(Chunk_With_Children* parent)
: Chunk (parent,"OBASEQTM") , sequence_time(0)
{
}
Object_Animation_Sequence_Time_Chunk (Chunk_With_Children * parent,const char *, size_t);
unsigned int sequence_time; //in milliseconds
virtual void fill_data_block (char *);
virtual size_t size_chunk (){ return chunk_size=16;}
private:
friend class Object_Animation_Sequence_Chunk;
};
class Object_Animation_Sequence_Speed_Chunk : public Chunk
{
public :
Object_Animation_Sequence_Speed_Chunk(Chunk_With_Children* parent)
: Chunk (parent,"OBASEQSP") , sequence_speed(0) ,angle(0),spare(0)
{
}
Object_Animation_Sequence_Speed_Chunk (Chunk_With_Children * parent,const char *, size_t);
int sequence_speed; //in mm/second
int angle; //in degrees (mainly for tools use)
int spare;
virtual void fill_data_block (char *);
virtual size_t size_chunk (){ return chunk_size=24;}
private:
friend class Object_Animation_Sequence_Chunk;
};
#define MummySequenceFlag_UpperSequence 0x00000001
#define MummySequenceFlag_LowerSequence 0x00000002
#define SequenceFlag_Loops 0x00000004
#define SequenceFlag_NoLoop 0x00000008
#define SequenceFlag_NoInterpolation 0x00000010
#define SequenceFlag_HalfFrameRate 0x00000020
class Object_Animation_Sequence_Flags_Chunk : public Chunk
{
public :
Object_Animation_Sequence_Flags_Chunk(Chunk_With_Children* parent,int _flags)
: Chunk (parent,"OBASEQFL") , flags(_flags)
{
}
Object_Animation_Sequence_Flags_Chunk (Chunk_With_Children * parent,const char *, size_t);
int flags;
virtual void fill_data_block (char *);
virtual size_t size_chunk (){ return chunk_size=16;}
};
struct Object_Animation_Frame
{
ChunkQuat orientation;
ChunkVectorInt transform;
signed long at_frame_no; //frame start time (0-65535)
int flags;
int get_sound_index(){return ((flags & HierarchyFrame_SoundIndexMask )>>24);}
};
struct Object_Animation_Sequence
{
~Object_Animation_Sequence(){delete [] frames;}
unsigned long num_frames;
signed long sequence_number;
signed long sub_sequence_number;
unsigned int sequence_time; //in milliseconds
Object_Animation_Frame* frames;
};
#define Get_Object_Animation_All_Sequence_Chunk(parent) (Object_Animation_All_Sequence_Chunk*)(parent)->lookup_single_child("OBANALLS")
//a more compact version of the sequence and frame data
//this format isn't recognized by any of the tools however.
class Object_Animation_All_Sequence_Chunk : public Chunk
{
public:
Object_Animation_All_Sequence_Chunk (Chunk_With_Children * parent);
Object_Animation_All_Sequence_Chunk (Chunk_With_Children * const parent,const char *, const size_t);
~Object_Animation_All_Sequence_Chunk () {delete [] sequences;}
virtual void fill_data_block (char *);
virtual size_t size_chunk ();
int num_sequences;
Object_Animation_Sequence* sequences;
};
#endif

21
src/win95/aw.h Normal file
View file

@ -0,0 +1,21 @@
#ifndef _INCLUDED_AW_H_
#define _INCLUDED_AW_H_
#include <d3d.h>
typedef IDirectDraw DDObject;
typedef IDirect3DDevice D3DDevice;
typedef IDirect3DTexture D3DTexture;
typedef IDirectDrawSurface DDSurface;
typedef IDirectDrawPalette DDPalette;
#define GUID_D3D_TEXTURE IID_IDirect3DTexture
#define GUID_DD_SURFACE IID_IDirectDrawSurface
typedef DDSURFACEDESC DD_SURFACE_DESC;
typedef DDSCAPS DD_S_CAPS;
struct AwBackupTexture;
typedef struct AwBackupTexture * AW_BACKUPTEXTUREHANDLE;
#endif /* _INCLUDED_AW_H_ */

192
src/win95/awbmpld.cpp Normal file
View file

@ -0,0 +1,192 @@
#include "advwin32.h"
#ifndef DB_LEVEL
#define DB_LEVEL 4
#endif
#include "db.h"
#include "awTexLd.hpp"
// BMP Loader
class AwBmpLoader : public AwTl::TypicalTexFileLoader
{
protected:
virtual void LoadHeaderInfo(MediaMedium * pMedium);
virtual AwTl::Colour * GetPalette();
virtual bool AreRowsReversed();
virtual void LoadNextRow(AwTl::PtrUnion pRow);
WORD bmp_bitdepth;
DWORD bmp_offset;
DWORD bmp_headsize;
unsigned bmp_filepitchpad;
unsigned bmp_bitmask;
MediaMedium * m_pMedium;
};
void AwBmpLoader::LoadHeaderInfo(MediaMedium * pMedium)
{
m_pMedium = pMedium; // store for later
db_log4("\tLoading a BMP file");
pMedium->MovePos(+10); // 2 bytes BM (magic) and 4 bytes bmp_filesize and 4 bytes reserved
MediaRead(pMedium,&bmp_offset);
MediaRead(pMedium,&bmp_headsize);
// 12 for OS/2 1.x 40 for Windows, 64 for OS/2 2.x
if (12 != bmp_headsize && 40 != bmp_headsize && 64 != bmp_headsize)
{
awTlLastErr = AW_TLE_BADFILEFORMAT;
db_logf3(("AwCreateTexture(): ERROR: BMP_headersize (%u) is not a recognized BMP format",bmp_headsize));
}
#if DB_LEVEL >= 4
switch (bmp_headsize)
{
case 12:
db_log4("\tBMP format is OS/2 1.x");
break;
case 40:
db_log4("\tBMP format is Windows 3.x");
break;
case 64:
db_log4("\tBMP format is OS/2 2.x");
}
#endif
if (bmp_headsize >= 40)
{
DWORD width, height;
MediaRead(pMedium,&width);
MediaRead(pMedium,&height);
m_nWidth = width;
m_nHeight = height;
}
else
{
WORD width, height;
MediaRead(pMedium,&width);
MediaRead(pMedium,&height);
m_nWidth = width;
m_nHeight = height;
}
// next WORD is planes and should == 1
WORD bmp_planes = 0; // ALEX: added in initialization to prevent compiler warnings
MediaRead(pMedium,&bmp_planes);
if (1!=bmp_planes)
{
awTlLastErr = AW_TLE_BADFILEDATA;
db_log3("AwCreateTexture(): ERROR: BMP_planes should be 1");
}
MediaRead(pMedium,&bmp_bitdepth);
db_logf4(("\tBMP_bitdepth is %hd",bmp_bitdepth));
if (1!=bmp_bitdepth && 2!=bmp_bitdepth && 4!=bmp_bitdepth && 8!=bmp_bitdepth && 24!=bmp_bitdepth)
{
awTlLastErr = AW_TLE_BADFILEDATA;
db_logf3(("AwCreateTexture(): ERROR: BMP_bitdepth (%u) should be 1,2,4,8 or 24",bmp_bitdepth));
}
if (bmp_headsize >= 40)
{
// next DWORD is compression, not supported so only accept 0
DWORD compression = 0;
MediaRead(pMedium,&compression);
if (compression)
{
db_log3("AwCreateTexture(): ERROR: Cannont read compressed BMP files");
awTlLastErr = AW_TLE_BADFILEFORMAT;
}
// DWORD bmp_size - ignored, 2xDWORDS ignored
pMedium->MovePos(+12);
DWORD palette_size = 0; // ALEX: added in initialization to prevent compiler warnings
MediaRead(pMedium,&palette_size);
m_nPaletteSize = palette_size;
// skip to the start of the palette if there would be one
pMedium->MovePos(bmp_headsize-36);
}
else
{
m_nPaletteSize = 0;
}
bmp_offset -= (bmp_headsize+14);
if (!m_nPaletteSize && bmp_bitdepth<=8)
m_nPaletteSize = 1<<bmp_bitdepth;
if (m_nPaletteSize)
bmp_offset -= bmp_headsize >= 40 ? m_nPaletteSize*4 : m_nPaletteSize*3;
db_logf4(("\tBMP_palettesize is %u",m_nPaletteSize));
bmp_filepitchpad = (~(m_nWidth*bmp_bitdepth-1))/8 & 3;
db_logf4(("\tBMP has %u bytes padding per row",bmp_filepitchpad));
bmp_bitmask = (1<<bmp_bitdepth)-1;
}
AwTl::Colour * AwBmpLoader::GetPalette()
{
db_assert1(m_nPaletteSize);
db_assert1(m_pPalette);
if (m_nPaletteSize > 256)
{
awTlLastErr = AW_TLE_BADFILEDATA;
db_log3("AwCreateTexture(): ERROR: BMP_palettesize is too large");
}
else
{
AwTl::Colour * pmP = m_pPalette;
for (unsigned pc = m_nPaletteSize; pc; --pc,++pmP)
{
MediaRead(m_pMedium,&pmP->b);
MediaRead(m_pMedium,&pmP->g);
MediaRead(m_pMedium,&pmP->r);
if (bmp_headsize >= 40) m_pMedium->MovePos(+1);
}
}
// skip to the start of the pixel data
m_pMedium->MovePos(bmp_offset);
return m_pPalette;
}
bool AwBmpLoader::AreRowsReversed()
{
return true;
}
void AwBmpLoader::LoadNextRow(AwTl::PtrUnion pRow)
{
if (m_nPaletteSize)
{
unsigned shift = 0;
BYTE byte = 0; // Not needed.
for (unsigned colcount = m_nWidth; colcount; --colcount)
{
if (!shift)
{
shift = 8;
MediaRead(m_pMedium, &byte);
}
shift -= bmp_bitdepth;
*pRow.byteP++ = static_cast<BYTE>(byte>>shift & bmp_bitmask);
}
}
else
{
for (unsigned colcount = m_nWidth; colcount; --colcount)
{
MediaRead(m_pMedium,&pRow.colourP->b);
MediaRead(m_pMedium,&pRow.colourP->g);
MediaRead(m_pMedium,&pRow.colourP->r);
++pRow.colourP;
}
}
m_pMedium->MovePos(bmp_filepitchpad);
}
#ifdef _MSC_VER
// VC5.0 tries to compile out code that is in a library
// and it thinks isn't being used
#line 186
#endif
AWTEXLD_IMPLEMENT_DYNCREATE("BM",AwBmpLoader)

507
src/win95/awiffld.cpp Normal file
View file

@ -0,0 +1,507 @@
#include "advwin32.h"
#ifndef DB_LEVEL
#define DB_LEVEL 4
#endif
#include "db.h"
#ifndef DB_COMMA
#define DB_COMMA ,
#endif
#pragma warning(disable: 4701)
#include "awTexLd.hpp"
#pragma warning(default: 4701)
#include "iff.hpp"
#include "iff_ILBM.hpp"
#include "list_tem.hpp"
#include <limits.h>
// conversion functors for IFF loader
class AwIffConvNull
{
public:
static inline unsigned DoConv (unsigned const * _colP, AwTl::Colour const * db_code1(DB_COMMA unsigned))
{
db_assert1(AwTl::pixelFormat.palettizedB);
return *_colP;
}
};
class AwIffConvNonTransp : public AwTl::Colour::ConvNonTransp
{
public:
static inline unsigned DoConv(unsigned const * pCol, AwTl::Colour const * pPalette db_code1(DB_COMMA unsigned nPaletteSize))
{
db_assert1(pPalette);
db_onlyassert1(*pCol < nPaletteSize);
return AwTl::Colour::ConvNonTransp::DoConv(&pPalette[*pCol]);
}
};
class AwIffConvTransp
{
public:
static unsigned iTranspCol; // the index of the transparent colour
static unsigned rawTranspCol; // the value of a transparent pixel on the surface
static inline unsigned DoConv(unsigned const * pCol, AwTl::Colour const * pPalette db_code1(DB_COMMA unsigned nPaletteSize))
{
using namespace AwTl;
if (*pCol == iTranspCol) return rawTranspCol;
unsigned rv = AwIffConvNonTransp::DoConv(pCol,pPalette db_code1(DB_COMMA nPaletteSize));
if (rv != rawTranspCol) return rv;
// make the colour non-transparent (nb: only an occasional case)
// OK, Here's the plan:
// First, suppose that I were to decrease either the Red, Green or Blue
// component in order to make the colour non-transparent.
// Taking Red as an example, I'll work out what the resultant red value
// will be if I decrease red to achieve a non-transparent colour
// I'll compare this to the actual red value of the colour in question
// The lower the difference, the better it'll be (ie. closer to the
// original colour).
// Obviously, I'll do the same for Green and Blue
// Then I'll repeat the process but this time considering increasing
// the components.
// I'll then have six values which are scores (the lower the better)
// for what colour component to change and how to change it.
// If any of the components cannot be decreased (ie. their resulting
// value is already zero) or increased (ie. their resulting value
// is at maximum), then I'll set the corresponding score to
// UINT_MAX so that that colour-changing operation won't be selected
// (because that'll be the one that buggers everything up).
unsigned nRedDiffDown =
(pPalette[*pCol].r < 1<<pixelFormat.redRightShift ) ? UINT_MAX
: (pPalette[*pCol].r & (1<<pixelFormat.redRightShift )-1) + ((1<<pixelFormat.redRightShift )+1)/2;
unsigned nGreenDiffDown =
(pPalette[*pCol].g < 1<<pixelFormat.greenRightShift) ? UINT_MAX
: (pPalette[*pCol].g & (1<<pixelFormat.greenRightShift)-1) + ((1<<pixelFormat.greenRightShift)+1)/2;
unsigned nBlueDiffDown =
(pPalette[*pCol].b < 1<<pixelFormat.blueRightShift ) ? UINT_MAX
: (pPalette[*pCol].b & (1<<pixelFormat.blueRightShift )-1) + ((1<<pixelFormat.blueRightShift )+1)/2;
unsigned nRedDiffUp =
(pPalette[*pCol].r >= (255 & ~((1<<pixelFormat.redRightShift )-1) ) ? UINT_MAX
: (1<<pixelFormat.redRightShift )*3/2 - (pPalette[*pCol].r & (1<<pixelFormat.redRightShift )-1));
unsigned nGreenDiffUp =
(pPalette[*pCol].g >= (255 & ~((1<<pixelFormat.greenRightShift)-1) ) ? UINT_MAX
: (1<<pixelFormat.greenRightShift)*3/2 - (pPalette[*pCol].g & (1<<pixelFormat.greenRightShift)-1));
unsigned nBlueDiffUp =
(pPalette[*pCol].b >= (255 & ~((1<<pixelFormat.blueRightShift )-1) ) ? UINT_MAX
: (1<<pixelFormat.blueRightShift )*3/2 - (pPalette[*pCol].b & (1<<pixelFormat.blueRightShift )-1));
// Pick lowest value and do the business
Colour colAdj = pPalette[*pCol];
#if defined(_MSC_VER) && _MSC_VER >= 1100
// VC5.0 gives inane warnings when += type operators
// are used on types smaller than int (even with
// explicit casting!)
#pragma warning(disable:4244)
#endif
if
(
nBlueDiffUp <= nBlueDiffDown
&& nBlueDiffUp <= nRedDiffUp
&& nBlueDiffUp <= nRedDiffDown
&& nBlueDiffUp <= nGreenDiffUp
&& nBlueDiffUp <= nGreenDiffDown
)
{
colAdj.b += static_cast<unsigned char>(1<<pixelFormat.blueRightShift);
}
else if
(
nBlueDiffDown <= nRedDiffUp
&& nBlueDiffDown <= nRedDiffDown
&& nBlueDiffDown <= nGreenDiffUp
&& nBlueDiffDown <= nGreenDiffDown
)
{
colAdj.b -= static_cast<unsigned char>(1<<pixelFormat.blueRightShift);
}
else if
(
nRedDiffUp <= nRedDiffDown
&& nRedDiffUp <= nGreenDiffUp
&& nRedDiffUp <= nGreenDiffDown
)
{
colAdj.r += static_cast<unsigned char>(1<<pixelFormat.redRightShift);
}
else if
(
nRedDiffDown <= nGreenDiffUp
&& nRedDiffDown <= nGreenDiffDown
)
{
colAdj.r -= static_cast<unsigned char>(1<<pixelFormat.redRightShift);
}
else if (nGreenDiffUp <= nGreenDiffDown)
{
colAdj.g += static_cast<unsigned char>(1<<pixelFormat.greenRightShift);
}
else
{
colAdj.g -= static_cast<unsigned char>(1<<pixelFormat.greenRightShift);
}
#if defined(_MSC_VER) && _MSC_VER == 1100
// VC5.0 gives inane warnings when += type operators
// are used on types smaller than int (even with
// explicit casting!)
#pragma warning(default:4244)
#endif
return Colour::ConvNonTransp::DoConv(&colAdj);
}
};
unsigned AwIffConvTransp::iTranspCol;
unsigned AwIffConvTransp::rawTranspCol;
// IFF Loader
class AwIffLoader : public AwTl::TexFileLoader
{
public:
AwIffLoader() : m_pPalette(NULL), m_bDecoding(false) {}
protected:
virtual ~AwIffLoader();
virtual void LoadHeaderInfo(MediaMedium * pMedium);
virtual unsigned GetNumColours();
virtual unsigned GetMinPaletteSize();
virtual bool HasTransparentMask(bool bDefault);
virtual void AllocateBuffers(bool bWantBackup, unsigned nMaxPaletteSize);
virtual void OnBeginRestoring(unsigned nMaxPaletteSize);
virtual AwTl::Colour * GetPalette();
virtual AwTl::PtrUnion GetRowPtr(unsigned nRow);
virtual void LoadNextRow(AwTl::PtrUnion pRow);
virtual void ConvertRow(AwTl::PtrUnion pDest, unsigned nDestWidth, AwTl::PtrUnionConst pSrc, unsigned nSrcOffset, unsigned nSrcWidth, AwTl::Colour * pPalette db_code1(DB_COMMA unsigned nPaletteSize));
virtual DWORD GetTransparentColour();
virtual void OnFinishLoading(bool bSuccess);
virtual void OnFinishRestoring(bool bSuccess);
virtual AwBackupTexture * CreateBackupTexture();
private:
static bool Enumerator(IFF::Chunk * pChunk, void * pData);
// list of chunks found by enumerator
List<IFF::IlbmBodyChunk *> m_listBodyChunks;
// smallest and largest palette sizes of versions of this image
unsigned m_nMaxPaletteSize;
unsigned m_nMinPaletteSize;
// buffer for palette -
// since the IFF cmap table is in a different format to what the Aw loaders require
// (maybe should think about standardizing the data types?)
AwTl::Colour * m_pPalette;
// iff data
IFF::File m_ifData;
IFF::IlbmBmhdChunk * m_pHdr;
IFF::IlbmCmapChunk * m_pCmap;
IFF::IlbmBodyChunk * m_pBody;
bool m_bDecoding;
};
AwIffLoader::~AwIffLoader()
{
if (m_pPalette) delete[] m_pPalette;
}
void AwIffLoader::LoadHeaderInfo(MediaMedium * pMedium)
{
db_log4("\tLoading an IFF file");
while (m_listBodyChunks.size())
m_listBodyChunks.delete_first_entry();
if (!m_ifData.Load(pMedium) || !m_ifData.GetContents())
{
if (NO_ERROR == (awTlLastWinErr = GetLastError()))
awTlLastErr = AW_TLE_BADFILEDATA;
else
awTlLastErr = AW_TLE_CANTREADFILE;
db_log3("AwCreateTexture(): ERROR: IFF file load failed");
}
else
{
m_nMinPaletteSize = UINT_MAX;
m_nMaxPaletteSize = 0;
m_ifData.GetContents()->EnumChildren("ILBM","BODY",Enumerator,this);
}
}
unsigned AwIffLoader::GetNumColours()
{
return m_nMaxPaletteSize;
}
unsigned AwIffLoader::GetMinPaletteSize()
{
return m_nMinPaletteSize;
}
void AwIffLoader::AllocateBuffers(bool /*bWantBackup*/, unsigned nMaxPaletteSize)
{
// we will need to allocate buffers when restoring as well as first-time loading
// so allocate buffers in OnBeginRestoring() which we'll call here
OnBeginRestoring(nMaxPaletteSize);
}
bool AwIffLoader::Enumerator(IFF::Chunk * pChunk, void * pData)
{
db_assert1(pChunk);
db_assert1(pData);
AwIffLoader * pThis = static_cast<AwIffLoader *>(pData);
IFF::Chunk * pCmap = pChunk->GetProperty("CMAP");
IFF::Chunk * pHdr = pChunk->GetProperty("BMHD");
if (pCmap && pHdr) // must have these two properties
{
unsigned nThisPaletteSize = static_cast<IFF::IlbmCmapChunk *>(pCmap)->nEntries;
db_logf4(("\tfound a %u colour %scompressed IFF body chunk",nThisPaletteSize,static_cast<IFF::IlbmBmhdChunk *>(pHdr)->eCompression ? "" : "un"));
pThis->m_listBodyChunks.add_entry(static_cast<IFF::IlbmBodyChunk *>(pChunk));
if (nThisPaletteSize < pThis->m_nMinPaletteSize)
pThis->m_nMinPaletteSize = nThisPaletteSize;
if (nThisPaletteSize > pThis->m_nMaxPaletteSize)
pThis->m_nMaxPaletteSize = nThisPaletteSize;
}
else db_log3("AwCreateTexture(): WARNING: IFF body chunk found with insufficient associated property chunks");
return true; // continue enumeration
}
void AwIffLoader::OnBeginRestoring(unsigned nMaxPaletteSize)
{
using namespace AwTl;
if (m_listBodyChunks.size())
{
// if decodeing, m_pBody will be valid
if (m_bDecoding)
{
m_pBody->EndDecode();
m_bDecoding = false;
}
m_pBody = NULL;
unsigned nBestPaletteSize = 0;
for (LIF<IFF::IlbmBodyChunk *> itChunks(&m_listBodyChunks); !itChunks.done(); itChunks.next())
{
IFF::IlbmCmapChunk * pCmap = static_cast<IFF::IlbmCmapChunk *>(itChunks()->GetProperty("CMAP"));
db_assert1(pCmap);
if ((!nMaxPaletteSize || pCmap->nEntries <= nMaxPaletteSize) && pCmap->nEntries > nBestPaletteSize)
{
m_pBody = itChunks();
m_pCmap = pCmap;
nBestPaletteSize = pCmap->nEntries;
}
}
if (m_pBody)
{
m_pHdr = static_cast<IFF::IlbmBmhdChunk *>(m_pBody->GetProperty("BMHD"));
// delete old buffers
if (m_pPalette) delete[] m_pPalette;
// allocate buffer for palette, make it extra big to cope with corrupt files
unsigned nAllocPaletteSize = m_pCmap->nEntries;
unsigned nAllocPaletteSizeShift = 0;
while (0!=(nAllocPaletteSize >>= 1))
{
++nAllocPaletteSizeShift;
}
m_pPalette = new Colour [2<<nAllocPaletteSizeShift]; // prevent corrupt data causing a crash
//m_pPalette = new Colour [m_pCmap->nEntries];
// copy the palette
for (unsigned i=0; i<m_pCmap->nEntries; ++i)
{
// hacked testa
m_pPalette[i].r = m_pCmap->pTable[i].r;
m_pPalette[i].g = m_pCmap->pTable[i].g;
m_pPalette[i].b = m_pCmap->pTable[i].b;
}
// set the width height and palette size in the base class
m_nPaletteSize = m_pCmap->nEntries;
m_nWidth = m_pHdr->width;
m_nHeight = m_pHdr->height;
// prepare to decode the data
m_pBody->BeginDecode();
m_bDecoding = true;
// set the transparent mask colours
switch (m_pHdr->eMasking)
{
case IFF::IlbmBmhdChunk::MASK_NONE:
break;
case IFF::IlbmBmhdChunk::MASK_TRANSPARENTCOL:
AwIffConvTransp::iTranspCol = m_pHdr->iTranspCol;
if (pixelFormat.palettizedB)
AwIffConvTransp::rawTranspCol = AwIffConvTransp::iTranspCol;
else
AwIffConvTransp::rawTranspCol =
static_cast<unsigned>(m_pPalette[AwIffConvTransp::iTranspCol].r)>>pixelFormat.redRightShift<<pixelFormat.redLeftShift
|static_cast<unsigned>(m_pPalette[AwIffConvTransp::iTranspCol].g)>>pixelFormat.greenRightShift<<pixelFormat.greenLeftShift
|static_cast<unsigned>(m_pPalette[AwIffConvTransp::iTranspCol].b)>>pixelFormat.blueRightShift<<pixelFormat.blueLeftShift;
break;
default:
db_log3("AwCreateTexture(): ERROR: IFF mask field wrong");
awTlLastErr = AW_TLE_BADFILEDATA;
}
}
else
{
awTlLastErr = AW_TLE_CANTPALETTIZE; // no suitable chunk found
db_log3("AwCreateTexture(): ERROR: No suitable IFF body chunk found");
}
}
else
{
awTlLastErr = AW_TLE_BADFILEDATA;
db_log3("AwCreateTexture(): ERROR: IFF file not loaded or contains no image data");
}
}
AwTl::Colour * AwIffLoader::GetPalette()
{
return m_pPalette;
}
bool AwIffLoader::HasTransparentMask(bool bDefault)
{
if (m_listBodyChunks.size())
{
IFF::IlbmBmhdChunk * pHdr = static_cast<IFF::IlbmBmhdChunk *>(m_listBodyChunks.first_entry()->GetProperty("BMHD"));
db_assert1(pHdr);
return (IFF::IlbmBmhdChunk::MASK_TRANSPARENTCOL == pHdr->eMasking);
}
else
return bDefault;
}
DWORD AwIffLoader::GetTransparentColour()
{
return AwIffConvTransp::rawTranspCol;
}
AwTl::PtrUnion AwIffLoader::GetRowPtr(unsigned /*nRow*/)
{
// the iff object has an internal buffer to which a pointer
// is returned when we decode each row
// unfortunately we have to cast constness away, but never mind
return const_cast<unsigned *>(m_pBody->DecodeNextRow());
}
void AwIffLoader::LoadNextRow(AwTl::PtrUnion /*pRow*/)
{
// GetRowPtr() has called DecodeNextRow()
// which has filled in the data already
// so do nothing here
}
void AwIffLoader::ConvertRow(AwTl::PtrUnion pDest, unsigned nDestWidth, AwTl::PtrUnionConst pSrc, unsigned nSrcOffset, unsigned nSrcWidth, AwTl::Colour * pPalette db_code1(DB_COMMA unsigned nPaletteSize))
{
using namespace AwTl;
// we have overridden this function for two reasons:
// 1. The data type for each texel in the row is unsigned int
// to allow for the fact that all images are palettized
// with no limit on the palette size. The default
// implementation would assume BYTE (unsigned char)
// 2. The transparency flag and colour is stored in the
// file and the transparency flag passed to AwCreateTexture()
// is ignored. The transparent colour does not have to be 0,0,0
// either
db_assert1(pPalette);
db_assert1(pPalette == m_pPalette);
// we can still use GenericConvertRow though, using the conversion functors above
if (pixelFormat.palettizedB)
{
GenericConvertRow<AwIffConvNull,unsigned>::Do(pDest, nDestWidth, pSrc.uintP+nSrcOffset, nSrcWidth);
}
else
{
switch (m_pHdr->eMasking)
{
case IFF::IlbmBmhdChunk::MASK_NONE:
GenericConvertRow<AwIffConvNonTransp,unsigned>::Do(pDest, nDestWidth, pSrc.uintP+nSrcOffset, nSrcWidth, pPalette db_code1(DB_COMMA nPaletteSize));
break;
case IFF::IlbmBmhdChunk::MASK_TRANSPARENTCOL:
GenericConvertRow<AwIffConvTransp,unsigned>::Do(pDest, nDestWidth, pSrc.uintP+nSrcOffset, nSrcWidth, pPalette db_code1(DB_COMMA nPaletteSize));
break;
default:
db_log3("AwCreateTexture(): ERROR: IFF mask field wrong");
awTlLastErr = AW_TLE_BADFILEDATA;
}
}
}
void AwIffLoader::OnFinishLoading(bool /*bSuccess*/)
{
if (m_bDecoding)
{
m_pBody->EndDecode();
m_bDecoding = false;
}
}
void AwIffLoader::OnFinishRestoring(bool /*bSuccess*/)
{
if (m_bDecoding)
{
m_pBody->EndDecode();
m_bDecoding = false;
}
}
AwBackupTexture * AwIffLoader::CreateBackupTexture()
{
// use the same object for restoring
AddRef();
return this;
}
// Valid file ID fields: 'FORM' 'LIST' 'CAT ' - we can load them all
#ifdef _MSC_VER
// VC5.0 tries to compile out code that is in a library
// and it thinks isn't being used
#line 427
#endif
AWTEXLD_IMPLEMENT_DYNCREATE("FORM",AwIffLoader)
AWTEXLD_IMPLEMENT_DYNCREATE("LIST",AwIffLoader)
AWTEXLD_IMPLEMENT_DYNCREATE("CAT ",AwIffLoader)

239
src/win95/awpnmld.cpp Normal file
View file

@ -0,0 +1,239 @@
#include "advwin32.h"
#ifndef DB_LEVEL
#define DB_LEVEL 4
#endif
#include "db.h"
#include "awTexLd.hpp"
// PNM loaders
class AwPnmLoader : public AwTl::TypicalTexFileLoader
{
protected:
void _AWTL_VARARG ParseHeader(unsigned nFields,...);
MediaMedium * m_pMedium;
};
void _AWTL_VARARG AwPnmLoader::ParseHeader(unsigned nFields,...)
{
va_list ap;
va_start(ap,nFields);
m_pMedium->MovePos(+2); // skip past magic
BYTE c = 0;
while (nFields)
{
unsigned * fieldP = va_arg(ap,unsigned *);
bool comment = false;
bool done = false;
do
{
MediaRead(m_pMedium, &c);
switch (c)
{
case '\n':
comment = false;
break;
case '#':
comment = true;
break;
default:
if (!comment && !isspace(c))
done = true;
}
}
while (!done);
char bufA[512];
char * bufP = bufA;
do
{
*bufP++ = c;
MediaRead(m_pMedium, &c);
}
while (!isspace(c));
*bufP = 0;
*fieldP = atoi(bufA);
-- nFields;
}
// c should now be a newline character
if ('\n'!=c)
awTlLastErr = AW_TLE_BADFILEDATA;
va_end(ap);
}
class AwPpmLoader : public AwPnmLoader
{
protected:
virtual void LoadHeaderInfo(MediaMedium * pMedium);
virtual AwTl::Colour * GetPalette();
virtual void LoadNextRow(AwTl::PtrUnion pRow);
unsigned pm_maxval;
};
void AwPpmLoader::LoadHeaderInfo(MediaMedium * pMedium)
{
m_pMedium = pMedium;
db_log4("\tLoading a PPM file");
ParseHeader(3,&m_nWidth,&m_nHeight,&pm_maxval);
db_logf4(("\tPPM_maxval is %u",pm_maxval));
if (pm_maxval > 255)
{
awTlLastErr = AW_TLE_BADFILEFORMAT;
db_log3("AwCreateTexture(): PPM_maxval too large");
}
m_nPaletteSize = 0;
}
AwTl::Colour * AwPpmLoader::GetPalette()
{
// never palettized
return NULL;
}
void AwPpmLoader::LoadNextRow(AwTl::PtrUnion pRow)
{
if (pm_maxval != 255)
for (unsigned colcount = m_nWidth; colcount; --colcount)
{
BYTE byte;
MediaRead(m_pMedium,&byte);
pRow.colourP->r = static_cast<BYTE>(static_cast<unsigned>(byte)*255/pm_maxval);
MediaRead(m_pMedium,&byte);
pRow.colourP->g = static_cast<BYTE>(static_cast<unsigned>(byte)*255/pm_maxval);
MediaRead(m_pMedium,&byte);
pRow.colourP->b = static_cast<BYTE>(static_cast<unsigned>(byte)*255/pm_maxval);
++pRow.colourP;
}
else
for (unsigned colcount = m_nWidth; colcount; --colcount)
{
MediaRead(m_pMedium,&pRow.colourP->r);
MediaRead(m_pMedium,&pRow.colourP->g);
MediaRead(m_pMedium,&pRow.colourP->b);
++pRow.colourP;
}
}
class AwPgmLoader : public AwPnmLoader
{
protected:
virtual void LoadHeaderInfo(MediaMedium * pMedium);
virtual AwTl::Colour * GetPalette();
virtual void LoadNextRow(AwTl::PtrUnion pRow);
unsigned pm_maxval;
};
void AwPgmLoader::LoadHeaderInfo(MediaMedium * pMedium)
{
m_pMedium = pMedium;
db_log4("\tLoading a PGM file");
ParseHeader(3,&m_nWidth,&m_nHeight,&pm_maxval);
db_logf4(("\tPGM_maxval is %u",pm_maxval));
if (pm_maxval > 255)
{
awTlLastErr = AW_TLE_BADFILEFORMAT;
db_log3("AwCreateTexture(): PGM_maxval too large");
}
m_nPaletteSize = pm_maxval+1;
}
AwTl::Colour * AwPgmLoader::GetPalette()
{
db_assert1(m_nPaletteSize);
db_assert1(m_pPalette);
unsigned step8 = (256*255)/pm_maxval;
unsigned val8 = 127;
AwTl::Colour * pmP = m_pPalette;
for (unsigned pc = m_nPaletteSize; pc; --pc,++pmP,val8+=step8)
pmP->r = pmP->g = pmP->b = static_cast<BYTE>(val8/256);
return m_pPalette;
}
void AwPgmLoader::LoadNextRow(AwTl::PtrUnion pRow)
{
m_pMedium->ReadBlock(pRow,m_nWidth);
}
class AwPbmLoader : public AwPnmLoader
{
protected:
virtual void LoadHeaderInfo(MediaMedium * pMedium);
virtual AwTl::Colour * GetPalette();
virtual void LoadNextRow(AwTl::PtrUnion pRow);
};
void AwPbmLoader::LoadHeaderInfo(MediaMedium * pMedium)
{
m_pMedium = pMedium;
db_log4("\tLoading a PBM file");
ParseHeader(2,&m_nWidth,&m_nHeight);
m_nPaletteSize = 2;
}
AwTl::Colour * AwPbmLoader::GetPalette()
{
db_assert1(m_nPaletteSize);
db_assert1(m_pPalette);
m_pPalette[0].r = 0;
m_pPalette[0].g = 0;
m_pPalette[0].b = 0;
m_pPalette[1].r = 255;
m_pPalette[1].g = 255;
m_pPalette[1].b = 255;
return m_pPalette;
}
void AwPbmLoader::LoadNextRow(AwTl::PtrUnion pRow)
{
unsigned shift = 0;
BYTE byte = 0;
for (unsigned colcount = m_nWidth; colcount; --colcount)
{
if (!shift)
{
shift = 8;
MediaRead(m_pMedium,&byte);
byte = (BYTE) ~byte;
}
--shift;
*pRow.byteP++ = static_cast<BYTE>(byte>>shift & 1);
}
}
#ifdef _MSC_VER
// VC5.0 tries to compile out code that is in a library
// and it thinks isn't being used
#line 228
#endif
AWTEXLD_IMPLEMENT_DYNCREATE("P6",AwPpmLoader)
AWTEXLD_IMPLEMENT_DYNCREATE("P5",AwPgmLoader)
AWTEXLD_IMPLEMENT_DYNCREATE("P4",AwPbmLoader)

2974
src/win95/awtexld.cpp Normal file

File diff suppressed because it is too large Load diff

565
src/win95/awtexld.h Normal file
View file

@ -0,0 +1,565 @@
#ifndef _INCLUDED_AWTEXLD_H_
#define _INCLUDED_AWTEXLD_H_
#include <windows.h>
#include <d3d.h>
/*********************************************/
/* Note: */
/* */
/* This header file contains typedefs for */
/* DDObject */
/* D3DDevice */
/* D3DTexture */
/* D3DSurface */
/* and #defines for their corresponding IIDs */
/* GUID_DD_SURFACE */
/* GUID_D3D_TEXTURE */
/* */
/* They are currently typedeffed as follows */
/* typedef IDirectDraw2 DDObject; */
/* typedef IDirect3DDevice D3DDevice; */
/* typedef IDirect3DTexture D3DTexture; */
/* typedef IDirect3DSurface DDSurface; */
/*********************************************/
#include "aw.h"
/***********************************************************************************/
/* awTexLd.h - Author: Jake Hotson */
/* */
/* Loading of textures into D3D surfaces */
/* requires DirectX 5 or later */
/* requires db.c and db.h */
/* also requires */
/* Watcom C++ 11.0 or later */
/* or Microsoft Visual C++ 5.0 or later */
/* or another suitable compiler */
/* */
/* Load any known file format */
/* Microsoft bitmap (.BMP) */
/* OS/2 1.x bitmap (.BMP) */
/* OS/2 2.x bitmap (.BMP) */
/* Portable Bitmap (.PBM) */
/* Portable Graymap (.PGM) */
/* Portable Pixelmap (.PPM) */
/* */
/* Load from various media */
/* File name */
/* Windows file handle */
/* Raw file data in memory */
/* */
/* Load into any given texture format provided a conversion is possible */
/* Pad to the required size that the driver will accept */
/* */
/* Optional handling of transparency */
/* Use alpha bits if available */
/* Otherwise chroma keying to be used */
/* Transparency colour is RGB(0,0,0) for non palettized data */
/* Or index 0 in palettized data */
/* */
/* Optional storing of processed raw data */
/* Use internal format independent of DirectX */
/* Function to reload from this data into a possibly different texture format */
/* */
/* Five optional levels of diagnostics possible */
/* 1. Logs when a function returns because of an error */
/* 2. Logs the nature of the error */
/* 3. Logs immediately when an error occurs */
/* 4. Logs information as data is parsed, and when main functions are called */
/* 5. Logs success of every small subsection of code */
/* */
/* Maximum error reporting */
/* */
/* Optimal Loading Speed */
/***********************************************************************************/
/* Version 2.1 */
#define AW_TL_VERSION 210 /* Preprocessor constant can be used to determine the version of this code */
/*
Version History:
----------------
version AW_TL_VERSION
0.9 090 Incomplete & May still contain bugs
0.91 091 AW_TLF_CHROMAKEY flag, and 't' option supported. Fewer bugs
0.92 092 Slightly more debug code
0.93 093 Using typedefs DDObject, D3DDevice, D3DTexture
1.0 100 Assumed to be bug-free
1.1 110 Internal redesign with interface to support any file format
1.2 120 Allow for loading into Direct Draw surfaces which are not textures
1.21 121 Two extra format flags to get width and height of actual image (as opposed to DD/D3D surface)
1.22 122 Split up the initialization function AwSetD3DDevice() into DD part and D3D part
1.3 130 New function: AwGetTextureSize()
1.31 131 New format flag for a callback function for when video mem runs out
1.4 140 Support for loading image split into several surfaces/textures and for loading surfaces as textures
1.5 150 Multiple texture format support
2.0 200 Beginning support for DX 6.0 - new AwSet..Format functions take LPDDPIXELFORMAT not LPDDSURFACEDESC
2.1 210 AW_TLF_CHECKLOST and AW_TLF_SKIPNOTLOST flags added
*/
/**********************************************/
/* Handle C++ linkage and optional parameters */
/**********************************************/
#ifdef __cplusplus
extern "C" {
#define _AWTL_DEFAULTPARM(v) = (v)
#else /* ! __cplusplus */
#define _AWTL_DEFAULTPARM(v)
#endif /* ? __cplusplus */
#ifdef _MSC_VER
#define _AWTL_VARARG __cdecl
#else
#define _AWTL_VARARG
#endif
/******************************/
/* return codes & error codes */
/******************************/
typedef
enum AwTlErc
{
/* General Errors */
AW_TLE_OK /* apparent success */
, AW_TLE_DXERROR /* unexpected DirectX error - see awTlLastDxErr */
, AW_TLE_BADPARMS /* parameters passed to function were invalid, or requested unsupported functionality */
, AW_TLE_NOINIT /* initialization functions have not been successfully called */
/* File reading errors */
, AW_TLE_CANTOPENFILE /* file open failed - see awTlLastWinErr for the Windows error code */
, AW_TLE_CANTREADFILE /* unexpected error reading file - see awTlLastWinErr for the Windows error code */
, AW_TLE_EOFMET /* unexpected end of file encountered */
, AW_TLE_BADFILEFORMAT /* file format identifier not recognized */
, AW_TLE_BADFILEDATA /* file data not consistent */
/* Conversion errors */
, AW_TLE_CANTPALETTIZE /* texture format is palettized; file data is not */
, AW_TLE_IMAGETOOLARGE /* image size is larger in one or both dimensions than maximum texture size */
, AW_TLE_CANTRELOAD /* loading a new texture into an existing surface failed because the existing surface is an unsuitable size, etc. */
}
AW_TL_ERC;
extern AW_TL_ERC awTlLastErr;
extern HRESULT awTlLastDxErr;
extern DWORD awTlLastWinErr;
#ifdef NDEBUG
#define AwTlErrorToString ThisIsADebugFunction! /* generate compiler error */
#define AwDxErrorToString ThisIsADebugFunction! /* generate compiler error */
#define AwWinErrorToString ThisIsADebugFunction! /* generate compiler error */
#else /* ! NDEBUG */
extern char const * AwTlErrorToString(AW_TL_ERC _AWTL_DEFAULTPARM(awTlLastErr));
extern char const * AwDxErrorToString(HRESULT _AWTL_DEFAULTPARM(awTlLastDxErr));
extern char const * AwWinErrorToString(DWORD _AWTL_DEFAULTPARM(awTlLastWinErr));
#endif /* ? NDEBUG */
/*********/
/* Flags */
/*********/
enum
{
AW_TLF_DEFAULT = 0x00000000U /* no flags set */
, AW_TLF_TRANSP = 0x00000001U /* src data has transparency */
, AW_TLF_PREVSRC = 0x00000002U /* in AwRestoreTexture, use previously stored source data flags (AW_TLF_TRANSP only) */
, AW_TLF_COMPRESS = 0x00000004U /* use ALLOCONLOAD flag */
, AW_TLF_CHROMAKEY = 0x00000008U /* use chroma keying for transparency when the texture format has an alpha channel */
, AW_TLF_VIDMEM = 0x00000010U /* use Video memory for surfaces which are not textures */
, AW_TLF_PREVSRCALL = 0x00000020U /* in AwRestoreTexture, use ALL previously stored flags, except AW_TLF_CHECKLOST and AW_TLF_SKIPNOTLOST */
, AW_TLF_TEXTURE = 0x00000040U /* in AwCreateSurface, create a surface in the texture format with the texture flag set */
, AW_TLF_MINSIZE = 0x00000080U /* with the 'a' option, ensure all surfaces/textures created are at least as big as the rectangle specified even if the rect is partially off the image */
, AW_TLF_CHECKLOST = 0x00000100U /* checks for lost surfaces and calls restore on them */
, AW_TLF_SKIPNOTLOST = 0x00000200U /* if the above flag also is specified, does not bother trying to restore surfaces which weren't lost */
, _AW_TLF_FORCE32BITENUM = 0x0fffffffU /* probably entirely unnecessary */
};
/*********/
/* Types */
/*********/
/* a callback function */
typedef int (* AW_TL_PFN_CALLBACK) (void *);
/* Structure for receiving specific regions of an image in a surface or texture.
* A pointer to an array of thise structures is passed to the AwCreate...
* functions if the 'a' format specifier is used. The fields 'left', 'right',
* 'top' and 'bottom' specify the rectangle to cut out of the image being loaded
* and must be valid. In AwCreateSurface, the 'pSurface' field is used and is a
* pointer to the Direct Draw surface created; in AwCreateTexture, the
* 'pTexture' field is used and is a pointer to the Direct 3D texture created.
* If an error occurs all the pointers in the array will be set to NULL. The
* 'width' and 'height' fields will be filled in with the width and height of
* the surface or texture that is created. If the rectangle specified is
* completely outsided the main image, the width and height will be set to zero,
* and the pointer field will be set to NULL, but this does not constitute an
* error. If the 't' option is used, the pointer fields are assumed to be valid
* textures or surfaces into which to load the new textures or surfaces. If the
* pointer is NULL, the structure is ignored. The pointers will remain unchanged
* even in the event of an error or a rectangle specified outside the main
* image, though the width and height will still be set to zero.
*/
struct AwCreateGraphicRegion
{
unsigned left, top, right, bottom; /* rectangle to cut from the original image */
unsigned width, height; /* width and height of the resulting surface or texture */
union /* DDSurface or D3DTexture pointer depending on the context used */
{
DDSurface * pSurface; /* Direct Draw Surface object pointer */
D3DTexture * pTexture; /* Direct 3D Texture object pointer */
};
};
/* typedef to save typing 'struct' when not using C++ */
typedef struct AwCreateGraphicRegion AW_CREATEGRAPHICREGION;
/********************/
/* Public functions */
/********************/
/* AwSetD3DDevice(DDObject * _ddP, D3DDevice * _d3ddeviceP)
Description:
Tells the texture loaders about the DirectDraw and
Direct3D setup. You must call this function before
loading any textures, and also every time you change
the DirectDraw or Direct3D device setup.
As of v1.22 this function is overloaded and only
available to C++ programmers.
Parameters:
_ddP
Pointer to the DirectDraw object obtained from
a call to DirectDrawCreate().
_d3ddeviceP
Pointer to the Direct3DDevice object obtained
from its GUID which is the lpGuid parameter in
a call to a D3DENUMDEVICESCALLBACK function for
your chosen driver.
Returns:
AW_TLE_OK if the function completed successfully;
AW_TLE_BADPARMS if the parameters passed to the
function were incorrect
AW_TLE_DXERROR if a DirectX SDK call failed
*/
#ifdef __cplusplus
extern "C++" AW_TL_ERC AwSetD3DDevice(DDObject * _ddP, D3DDevice * _d3ddeviceP);
#endif
/* AwSetDDObject(DDObject * _ddP)
AwSetD3DDevice(D3DDevice * _d3ddeviceP)
Description:
These functions together do what the two parameter
version of AwSetD3DDevice(), above, does. You
needn't call AwSetD3DDevice() if you are only
loading direct draw surfaces. The parameters and
return values are as described above.
*/
extern AW_TL_ERC AwSetD3DDevice(D3DDevice * _d3ddeviceP);
extern AW_TL_ERC AwSetDDObject(DDObject * _ddP);
/* AwSetTextureFormat2(LPDDPIXELFORMAT _ddpfP)
Description:
Informs the texture loaders of the currently slected
texture format. You must call this function before
loading any textures, and also every time you change
the texture format.
Parameters:
_ddpfP
Pointer to a DDPIXELFORMAT structure which
describes the texture format.
Returns:
AW_TLE_OK if the function completed successfully;
AW_TLE_BADPARMS if the parameters passed to the
function were incorrect
*/
extern AW_TL_ERC AwSetTextureFormat2(LPDDPIXELFORMAT _ddpfP);
#define AwSetTextureFormat(_descP) (AwSetTextureFormat2((_descP) ? &(_descP)->ddpfPixelFormat : NULL))
/* AwSetAdditionalTextureFormat2(LPDDPIXELFORMAT _ddpfP, unsigned _maxAlphaBits, int _canDoTransp, unsigned _maxColours)
Description:
Informs the texture loaders an additional texture
format that should be used in certain cases. After
a call to AwSetTextureFormat, there are no
additional formats. Each additional format that you
want to make available should be set with a call to
this function. When a texture is being loaded, the
additional formats are considered in the order that
they were set (ie. the order in which the calls to
this function were made). For each format
considered, if it could be used for the image and
the image's specification passes the tests for this
format, the format will replace the previously
chosen format (either the base format set by
AwSetTextureFormat or an earlier additional format
whose conditions of use were also met).
Parameters:
_ddpfP
Pointer to a DDPIXELFORMAT structure which
describes the texture format.
_maxAlphaBits
Specifies that this format should only be used
for images that do not have more bits of alpha
information than this value.
_canDoTransp
If zero, specifies that this format should not
be used for images which have a transparent
colour.
_maxColours
Specifies that this format should only be used
for images that do not contain more unique
colours than this value. If this value is zero,
the format can be used for images with any
number of colours. If this value is non-zero,
this format will not be used for images whose
number of unique colours cannot be determined.
Returns:
AW_TLE_OK if the function completed successfully;
AW_TLE_NOINIT if AwSetTextureFormat was not
previously called.
AW_TLE_BADPARMS if the parameters passed to the
function were incorrect
*/
extern AW_TL_ERC AwSetAdditionalTextureFormat2(LPDDPIXELFORMAT _ddpfP, unsigned _maxAlphaBits, int _canDoTransp, unsigned _maxColours);
#define AwSetAdditionalTextureFormat(_descP, _maxAlphaBits, _canDoTransp, _maxColours) (AwSetAdditionalTextureFormat2((_descP) ? &(_descP->ddpfPixelFormat) : NULL,_maxAlphaBits,_canDoTransp,_maxColours))
/* AwSetSurfaceFormat2(LPDDPIXELFORMAT _ddpfP)
Description:
As for AwSetTextureFormat but tells AwCreateSurface()
what format surfaces for blitting should be in
*/
extern AW_TL_ERC AwSetSurfaceFormat2(LPDDPIXELFORMAT _ddpfP);
#define AwSetSurfaceFormat(_descP) (AwSetSurfaceFormat2((_descP) ? &(_descP)->ddpfPixelFormat : NULL))
/* AwGetTextureSize(unsigned * _widthP, unsigned * _heightP, unsigned _width, unsigned _height)
Description:
Calculates the size required for a texture on the
current driver, given a minimum size required to
hold the proposed image.
Parameters:
_widthP
Pointer to a variable which will receive the
width required for a Direct 3D texture.
_heightP
Pointer to a variable which will receive the
height.
_width
Minimum width required for the proposed image.
_height
Minimum height required.
Returns:
AW_TLE_OK if the required Direct 3D texture size was
calculated;
AW_TLE_IMAGETOOLARGE if the driver specifies a
maximum texture size which is less than the size
that would be required to hold an image of the
proposed size;
AW_TLE_NOINIT if driver information was unavailable
because initialization functions weren't called.
*/
extern AW_TL_ERC AwGetTextureSize(unsigned * _widthP, unsigned * _heightP, unsigned _width, unsigned _height);
/* AwCreateTexture(char const * _argFormatS, ...)
Description:
Creates a Direct3D texture for use by the device
renderer. The exact functionality is determined by
the first argument which is a format specifier
string.
Parameters:
_argFormatS
Pointer to a null terminated string which
specifies the order, types and interpretations
of the other parameters. Each character in the
string corresponds to a parameter passed to the
function, and the parameters are parsed in the
same order as their format specifiers appear in
the string. For clarity, upper case letters are
used to indicate paramters which are pointers to
data that will be filled in by the function, and
lower case letters are used for parameters which
are simply data to be used by the function.
The following specifiers are permitted:
s The next argument is of type 'LPCTSTR' and is a
pointer to a ASCII or UNICODE string which is
the filename of an image file to load.
h The next argument is of type 'HANDLE' and is a
Windows file handle with its file pointer set to
the start of an image file's data.
p The next argument is of type 'void const *' and
is a pointer to an image file's data in memory.
r The next argument is of type
'AW_BACKUPTEXTUREHANDLE' and is used to restore
a previously loaded texture, possibly with the
texture format or Direct3D device having
changed.
x The next argument is of type 'unsigned' and is
the maximum number of bytes that should be read
from a file or memory. If parsing the file data
would cause more bytes to be read than this
value, the function fails and the error is
'AW_TLE_EOFMET'. This may be useful in
conjunction with format specifier 'm' in order
to prevent a general protection (GP) fault.
N The next argument is of type 'unsigned *' and
points to a variable which will receive the
number of bytes which are actually read from a
file or memory. This value will be filled in
even if the function fails (unless the error is
'AW_TLE_BADPARMS').
f The next argument is of type 'unsigned' and can
be any combination of 'AW_TLF_...' flags (above)
which control special functionality.
W The next argument is of type 'unsigned *' and
points to a variable which will receive the
width of the texture that is created.
H The next argument is of type 'unsigned *' and
points to a variable which will receive the
height of the texture that is created.
X The next argument is of type 'unsigned *' and
points to a variable which will receive the
width of the original image.
Y The next argument is of type 'unsigned *' and
points to a variable which will receive the
height of the original image.
B The next argument is of type
'AW_BACKUPTEXTUREHANDLE *' and points to a
variable which will receive a handle that can
later be used with format specifier 'r' in a
call to this function in order to avoid
reloading from a file an image that has
previously been loaded. This value will be
filled in only if the function succeeds. When
you no longer need this handle, you should
deallocate the memory associated with it by
calling 'AwDestroyBackupTexture()'.
t The next argument is of type 'D3DTexture *'
and is used to load the new texture into an
existing texture surface. The parameter is NOT
Release()d; you should do this yourself. This is
only guaranteed to work if the new texture is of
the same height and pitch as the previous one
and compression is not used on either.
c The next two arguments indicate a callback
function which will be called if a texture cannot
be created due to insufficient video memory. The
idea is to allow the callee to free some video
memory and request further attempts at creating
the texture. The first of the two arguments is of
type AW_TL_PFN_CALLBACK and is a function pointer
to the function that would be called. This
function takes one parameter of type 'void *'
which is an implementation-specific value, and
returns type 'int', which is non-zero if another
attempt at creating the texture should be made.
If the callback function returns zero, then the
texture load will be aborted. The second of the
two arguments is of type 'void *' and is the
implementation-specific value passed to the
callback function.
a The next two arguments indicate an array of
rectangles to cut out of the original image and
create textures for each rectangle. The first of
these two arguments is of type 'unsigned' and is
the size of the array. The second argument is of
type 'AW_CREATEGRAPHICREGION *' and points to an
array of AwCreateGraphicRegion structs, each
indicating a region to cut out of the original
image and create a texture for. In this case, the
function always returns NULL, and you should test
for failure by examining awTlLastErr. The 't'
option, if used, must appear after 'a' in the
format string, and does not correspond to any
parameter, since the texture into which to
reload will be specified for each region in
the array of structures. The 'W' and 'H' options
will be ignored. For more information, see the
definition of this structure above.
There are some restrictions on parameters:
Exactly one of 's', 'h', 'p' or 'r' must be
used.
Neither 'x' nor 'N' may be used with 'r'.
'r' cannot be used with 'B'.
Neither 'W' or 'H' should be used with 'a'.
Each specifier should be used only once.
't' may not appear before 'a'.
There are no other restriction on the order
that the parameters occur.
Returns:
A valid D3DTexture * if the function succeeds;
awTlLastErr will also be AW_TLE_OK
NULL if the function fails. awTlLastErr will be
AW_TLE_BADPARMS if the parameters were
incorrect, or any other error code if the
parameters were correct but another error
occurred.
*/
extern D3DTexture * _AWTL_VARARG AwCreateTexture(char const * _argFormatS, ...);
/* AwCreateSurface(char const * _argFormatS, ...)
Description:
As for AwCreateTexture(), but returns a pointer to
a newly created direct draw surface which is not a
texture
Parameters:
_argFormatS
As AwCreateTexture(), except
t The next argument is of type 'DDSurface *'
*/
extern DDSurface * _AWTL_VARARG AwCreateSurface(char const * _argFormatS, ...);
/* AwDestroyBackupTexture(AW_BACKUPTEXTUREHANDLE _bH)
Description:
Deallocates the memory associated with a backup
texture handle, created by a call to
'AwCreateTexture()' with a 'B' specifier. The handle
cannot be used after this.
Parameters:
_bH
The handle whose associated memory should be
deallocated.
Returns:
AW_TLE_OK if the function succeeds.
AW_TLE_BADPARMS if the handle was not valid.
*/
extern AW_TL_ERC AwDestroyBackupTexture(AW_BACKUPTEXTUREHANDLE _bH);
/* End Wrappers */
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* ! _INCLUDED_AWTEXLD_H_ */

507
src/win95/awtexld.hpp Normal file
View file

@ -0,0 +1,507 @@
#ifndef _INCLUDED_AWTEXLD_HPP_
#define _INCLUDED_AWTEXLD_HPP_
#include "awTexLd.h"
#include "media.hpp"
#include "db.h"
#ifndef DB_COMMA
#define DB_COMMA ,
#endif
// Nasty hack to touch the classes so MSVC++ doesn't discards them.
#ifdef _MSC_VER
extern class AwTlRegisterLoaderClass_AwBmpLoader_187 rlcAwBmpLoader_187;
extern class AwTlRegisterLoaderClass_AwIffLoader_428 rlcAwIffLoader_428;
extern class AwTlRegisterLoaderClass_AwIffLoader_429 rlcAwIffLoader_429;
extern class AwTlRegisterLoaderClass_AwIffLoader_430 rlcAwIffLoader_430;
extern class AwTlRegisterLoaderClass_AwPpmLoader_229 rlcAwPpmLoader_229;
extern class AwTlRegisterLoaderClass_AwPgmLoader_230 rlcAwPgmLoader_230;
extern class AwTlRegisterLoaderClass_AwPbmLoader_231 rlcAwPbmLoader_231;
extern class RegisterChunkClassIlbmBmhdChunk_4 rccIlbmBmhdChunk_4;
extern class RegisterChunkClassIlbmCmapChunk_5 rccIlbmCmapChunk_5;
extern class RegisterChunkClassIlbmBodyChunk_6 rccIlbmBodyChunk_6;
extern class RegisterChunkClassIlbmGrabChunk_7 rccIlbmGrabChunk_7;
#endif
namespace AwTl {
#define CANT_HAPPEN db_msgf1(("AwCreateTexture(): (Line %u) CAN'T HAPPEN!",__LINE__));
/*********************************/
/* Pixel format global structure */
/*********************************/
struct PixelFormat
{
PixelFormat() : validB(false){}
bool palettizedB : 1;
bool alphaB : 1;
bool validB : 1;
unsigned bitsPerPixel;
unsigned redLeftShift;
unsigned redRightShift;
unsigned greenLeftShift;
unsigned greenRightShift;
unsigned blueLeftShift;
unsigned blueRightShift;
DDPIXELFORMAT ddpf;
};
// DO SOMTHING ABOUT THIS
extern PixelFormat pixelFormat;
class CreateTextureParms;
/********************/
/* Colour structure */
/********************/
struct Colour
{
BYTE r,g,b;
class ConvNonTransp
{
public:
static inline unsigned DoConv (Colour const * _colP, Colour const * = NULL db_code1(DB_COMMA unsigned = 0))
{
return
static_cast<unsigned>(_colP->r)>>pixelFormat.redRightShift<<pixelFormat.redLeftShift
|static_cast<unsigned>(_colP->g)>>pixelFormat.greenRightShift<<pixelFormat.greenLeftShift
|static_cast<unsigned>(_colP->b)>>pixelFormat.blueRightShift<<pixelFormat.blueLeftShift
|pixelFormat.ddpf.dwRGBAlphaBitMask
;
}
static inline unsigned DoConv(BYTE const * _colP, Colour const * _paletteP db_code1(DB_COMMA unsigned _paletteSize))
{
db_assert1(_paletteP);
db_onlyassert1(*_colP < _paletteSize);
return DoConv(&_paletteP[*_colP]);
}
};
class ConvTransp
{
private:
static inline unsigned MakeNonTranspCol(Colour const * _colP)
{
unsigned rv = ConvNonTransp::DoConv(_colP);
if (rv) return rv;
// make one of r,g or b in the output == 1, choose the one which is closest to the input
unsigned rdiff = (1<<pixelFormat.redRightShift) - _colP->r;
unsigned bdiff = (1<<pixelFormat.blueRightShift) - _colP->b;
unsigned gdiff = (1<<pixelFormat.greenRightShift) - _colP->g;
if (bdiff<=rdiff && bdiff<=gdiff)
return 1<<pixelFormat.blueLeftShift;
else if (rdiff<=gdiff)
return 1<<pixelFormat.redLeftShift;
else
return 1<<pixelFormat.greenLeftShift;
}
public:
static inline unsigned DoConv (Colour const * _colP, Colour const * = NULL db_code1(DB_COMMA unsigned = 0))
{
if (!_colP->b && !_colP->r && !_colP->g)
//return pixelFormat.alphaB ? pixelFormat.ddsd.ddpfPixelFormat.dwRBitMask|pixelFormat.ddsd.ddpfPixelFormat.dwGBitMask|pixelFormat.ddsd.ddpfPixelFormat.dwBBitMask : 0;
return 0;
else
return MakeNonTranspCol(_colP);
}
static inline unsigned DoConv(BYTE const * _colP, Colour const * _paletteP db_code1(DB_COMMA unsigned _paletteSize))
{
db_assert1(_paletteP);
db_onlyassert1(*_colP < _paletteSize);
if (!*_colP)
//return pixelFormat.alphaB ? pixelFormat.ddsd.ddpfPixelFormat.dwRBitMask|pixelFormat.ddsd.ddpfPixelFormat.dwGBitMask|pixelFormat.ddsd.ddpfPixelFormat.dwBBitMask : 0;
return 0;
else
return MakeNonTranspCol(&_paletteP[*_colP]);
}
};
class ConvNull
{
public:
static inline unsigned DoConv (BYTE const * _colP, Colour const * db_code1(DB_COMMA unsigned = 0))
{
db_assert1(pixelFormat.palettizedB);
return *_colP;
}
};
};
/*****************/
/* Pointer union */
/*****************/
union SurfUnion
{
D3DTexture * textureP;
DDSurface * surfaceP;
void * voidP;
SurfUnion(){}
SurfUnion(D3DTexture * p) : textureP(p){}
SurfUnion(DDSurface * p) : surfaceP(p){}
};
union PtrUnion
{
void * voidP;
char * charP;
signed char * scharP;
unsigned char * ucharP;
BYTE * byteP;
short * shortP;
unsigned short * ushortP;
WORD * wordP;
signed * intP;
unsigned * uintP;
DWORD * dwordP;
long * longP;
unsigned long * ulongP;
Colour * colourP;
inline PtrUnion(){}
inline PtrUnion(void * _voidP):voidP(_voidP){}
inline operator void * () const { return voidP; }
};
union PtrUnionConst
{
void const * voidP;
char const * charP;
signed char const * scharP;
unsigned char const * ucharP;
BYTE const * byteP;
short const * shortP;
unsigned short const * ushortP;
WORD const * wordP;
signed const * intP;
unsigned const * uintP;
DWORD const * dwordP;
long const * longP;
unsigned long const * ulongP;
Colour const * colourP;
inline PtrUnionConst(){}
inline PtrUnionConst(void const * _voidP):voidP(_voidP){}
inline PtrUnionConst(PtrUnion _uP):voidP(_uP.voidP){}
inline operator void const * () const { return voidP; }
};
/***************************************/
/* Generic copying to surface function */
/***************************************/
template<class CONVERT, class SRCTYPE>
class GenericConvertRow
{
public:
static void Do (PtrUnion _dstRowP, unsigned _dstWidth, SRCTYPE const * _srcRowP, unsigned _srcWidth, Colour const * _paletteP = NULL db_code1(DB_COMMA unsigned _paletteSize = 0));
};
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable: 4701)
#endif
template<class CONVERT, class SRCTYPE>
void GenericConvertRow<CONVERT, SRCTYPE>::Do (PtrUnion _dstRowP, unsigned _dstWidth, SRCTYPE const * _srcRowP, unsigned _srcWidth, Colour const * _paletteP db_code1(DB_COMMA unsigned _paletteSize))
{
switch (pixelFormat.bitsPerPixel)
{
default:
CANT_HAPPEN
case 16:
{
db_assert1(!pixelFormat.palettizedB);
for (unsigned colcount = _srcWidth; colcount; --colcount)
{
*_dstRowP.wordP++ = static_cast<WORD>(CONVERT::DoConv(_srcRowP++,_paletteP db_code1(DB_COMMA _paletteSize)));
}
if (_srcWidth<_dstWidth)
*_dstRowP.wordP = static_cast<WORD>(CONVERT::DoConv(_srcRowP-1,_paletteP db_code1(DB_COMMA _paletteSize)));
break;
}
case 24:
{
db_assert1(!pixelFormat.palettizedB);
union { DWORD dw; BYTE b[3]; } u;
for (unsigned colcount = _srcWidth; colcount; --colcount)
{
u.dw = static_cast<DWORD>(CONVERT::DoConv(_srcRowP++,_paletteP db_code1(DB_COMMA _paletteSize)));
*_dstRowP.byteP++ = u.b[0];
*_dstRowP.byteP++ = u.b[1];
*_dstRowP.byteP++ = u.b[2];
}
if (_srcWidth<_dstWidth)
{
*_dstRowP.byteP++ = u.b[0];
*_dstRowP.byteP++ = u.b[1];
*_dstRowP.byteP = u.b[2];
}
}
case 32:
{
db_assert1(!pixelFormat.palettizedB);
for (unsigned colcount = _srcWidth; colcount; --colcount)
{
*_dstRowP.dwordP++ = static_cast<DWORD>(CONVERT::DoConv(_srcRowP++,_paletteP db_code1(DB_COMMA _paletteSize)));
}
if (_srcWidth<_dstWidth)
*_dstRowP.dwordP = static_cast<DWORD>(CONVERT::DoConv(_srcRowP-1,_paletteP db_code1(DB_COMMA _paletteSize)));
break;
}
case 8:
{
for (unsigned colcount = _srcWidth; colcount; --colcount)
{
*_dstRowP.byteP++ = static_cast<BYTE>(CONVERT::DoConv(_srcRowP++,_paletteP db_code1(DB_COMMA _paletteSize)));
}
if (_srcWidth<_dstWidth)
*_dstRowP.byteP = static_cast<BYTE>(CONVERT::DoConv(_srcRowP-1,_paletteP db_code1(DB_COMMA _paletteSize)));
break;
}
case 1:
case 2:
db_assert1(pixelFormat.palettizedB);
case 4:
{
unsigned shift=0;
unsigned val;
--_dstRowP.byteP; // decrement here because we increment before the first write
for (unsigned colcount = _srcWidth; colcount; --colcount)
{
val = CONVERT::DoConv(_srcRowP++,_paletteP db_code1(DB_COMMA _paletteSize));
if (!shift)
*++_dstRowP.byteP = static_cast<BYTE>(val);
else
*_dstRowP.byteP |= static_cast<BYTE>(val<<shift);
shift += pixelFormat.bitsPerPixel;
shift &= 7;
}
if (_srcWidth<_dstWidth)
{
if (!shift)
*++_dstRowP.byteP = static_cast<BYTE>(val);
else
*_dstRowP.byteP |= static_cast<BYTE>(val<<shift);
}
break;
}
}
}
#ifdef _MSC_VER
#pragma warning(pop)
#endif
// reference counting support
class RefCntObj
{
public:
unsigned AddRef() { return ++m_nRefCnt; }
unsigned Release() { if (0==(--m_nRefCnt)) { delete this; return 0;} else return m_nRefCnt; }
protected:
virtual ~RefCntObj(){
#ifndef NDEBUG
DbForget(this);
#endif
}
RefCntObj() : m_nRefCnt(1){
#ifndef NDEBUG
DbRemember(this);
#endif
}
RefCntObj(RefCntObj const &) : m_nRefCnt(1){
#ifndef NDEBUG
DbRemember(this);
#endif
}
RefCntObj & operator = (RefCntObj const &){ return *this;}
private:
unsigned m_nRefCnt;
#ifndef NDEBUG
friend void DbRemember(RefCntObj * pObj);
friend void DbForget(RefCntObj * pObj);
friend class AllocList;
#endif
};
SurfUnion LoadFromParams(CreateTextureParms *);
} // namespace AwTl
struct AwBackupTexture : public AwTl::RefCntObj
{
public:
AwTl::SurfUnion Restore(AwTl::CreateTextureParms const & rParams);
protected:
AwTl::SurfUnion CreateTexture(AwTl::CreateTextureParms const & rParams);
void ChoosePixelFormat(AwTl::CreateTextureParms const & rParams);
virtual ~AwBackupTexture(){}
// return the number of unique colours in the image or zero if this cannot be determined
virtual unsigned GetNumColours() = 0;
// return the smallest palette size that is available for the image
virtual unsigned GetMinPaletteSize() = 0;
// return true if the image has a single transparent colour
virtual bool HasTransparentMask(bool bDefault);
// called when a backup texture is about to be used for restoring, but after the above two functions have been called
virtual void OnBeginRestoring(unsigned nMaxPaletteSize);
virtual AwTl::Colour * GetPalette() = 0;
virtual bool AreRowsReversed();
virtual AwTl::PtrUnion GetRowPtr(unsigned nRow) = 0;
virtual void LoadNextRow(AwTl::PtrUnion pRow) = 0;
virtual void ConvertRow(AwTl::PtrUnion pDest, unsigned nDestWidth, AwTl::PtrUnionConst pSrc, unsigned nSrcOffset, unsigned nSrcWidth, AwTl::Colour * pPalette db_code1(DB_COMMA unsigned nPaletteSize));
virtual DWORD GetTransparentColour();
virtual void OnFinishRestoring(bool bSuccess);
// metrics
unsigned m_nWidth;
unsigned m_nHeight;
unsigned m_nPaletteSize; // 0 inicates no palette
unsigned m_fFlags;
private:
bool m_bTranspMask;
friend AwTl::SurfUnion AwTl::LoadFromParams(AwTl::CreateTextureParms *);
};
namespace AwTl {
class TypicalBackupTexture : public ::AwBackupTexture
{
public:
TypicalBackupTexture(AwBackupTexture const & rBase, PtrUnion * ppPixMap, Colour * pPalette)
: AwBackupTexture(rBase)
, m_ppPixMap(ppPixMap)
, m_pPalette(pPalette)
{}
virtual ~TypicalBackupTexture()
{
if (m_pPalette)
{
delete[] m_pPalette;
if (m_ppPixMap)
{
delete[] m_ppPixMap->byteP;
delete[] m_ppPixMap;
}
}
else
{
if (m_ppPixMap)
{
delete[] m_ppPixMap->colourP;
delete[] m_ppPixMap;
}
}
}
virtual Colour * GetPalette();
virtual PtrUnion GetRowPtr(unsigned nRow);
virtual void LoadNextRow(PtrUnion pRow);
// note: the palette size member must be set in
// LoadHeaderInfo() for these functions to work correctly
virtual unsigned GetNumColours();
virtual unsigned GetMinPaletteSize();
private:
PtrUnion * m_ppPixMap;
Colour * m_pPalette;
};
class TexFileLoader : public AwBackupTexture
{
public:
SurfUnion Load(MediaMedium * pMedium, CreateTextureParms const & rParams);
protected:
// standard constructor
// & destructor
// Interface Functions. Each overridden version should set awTlLastErr
// when an error occurs
// Called to set the width and height members; the palette size member can also be safely set at this point.
// Neither the width height or palette size members need actually be set until AllocateBuffers returns
virtual void LoadHeaderInfo(MediaMedium * pMedium) = 0;
// should ensure that the palette size is set
virtual void AllocateBuffers(bool bWantBackup, unsigned nMaxPaletteSize) = 0;
virtual void OnFinishLoading(bool bSuccess);
virtual AwBackupTexture * CreateBackupTexture() = 0;
};
class TypicalTexFileLoader : public TexFileLoader
{
protected:
TypicalTexFileLoader() : m_pRowBuf(NULL), m_ppPixMap(NULL), m_pPalette(NULL) {}
virtual ~TypicalTexFileLoader();
virtual unsigned GetNumColours();
virtual unsigned GetMinPaletteSize();
virtual void AllocateBuffers(bool bWantBackup, unsigned nMaxPaletteSize);
virtual PtrUnion GetRowPtr(unsigned nRow);
virtual AwBackupTexture * CreateBackupTexture();
Colour * m_pPalette;
private:
PtrUnion * m_ppPixMap;
PtrUnion m_pRowBuf;
};
extern void RegisterLoader(char const * pszMagic, AwTl::TexFileLoader * (* pfnCreate) () );
} // namespace AwTl
#define AWTEXLD_IMPLEMENT_DYNCREATE(pszMagic, tokenClassName) _AWTEXLD_IMPLEMENT_DYNCREATE_LINE_EX(pszMagic,tokenClassName,__LINE__)
#define _AWTEXLD_IMPLEMENT_DYNCREATE_LINE_EX(pszMagic, tokenClassName, nLine) _AWTEXLD_IMPLEMENT_DYNCREATE_LINE(pszMagic,tokenClassName,nLine)
#define _AWTEXLD_IMPLEMENT_DYNCREATE_LINE(pszMagic,tokenClassName,nLine) \
AwTl::TexFileLoader * AwTlCreateClassObject ##_## tokenClassName ##_## nLine () { \
return new tokenClassName; \
} \
class AwTlRegisterLoaderClass ##_## tokenClassName ##_## nLine { \
public: AwTlRegisterLoaderClass ##_## tokenClassName ##_## nLine () { \
AwTl::RegisterLoader(pszMagic, AwTlCreateClassObject ##_## tokenClassName ##_## nLine); \
} \
} rlc ## tokenClassName ##_## nLine;
#endif // ! _INCLUDED_AWTEXLD_HPP_

964
src/win95/bmpnames.cpp Normal file
View file

@ -0,0 +1,964 @@
#include <string.h>
#include "bmpnames.hpp"
#include "mishchnk.hpp"
#if engine
#define UseLocalAssert No
#include "ourasert.h"
#define assert(x) GLOBALASSERT(x)
#else
#if cencon
#include "ccassert.h"
#else
#include <assert.h>
#endif
#endif
#ifdef cencon
#define new my_new
#endif
//macro for helping to force inclusion of chunks when using libraries
FORCE_CHUNK_INCLUDE_IMPLEMENT(bmpnames)
BMP_Name::BMP_Name (const char * fname, int const gbnc_version)
: flags((BMPN_Flags)DEFAULT_BMPN_FLAGS), index(0), version_num (gbnc_version << BMPNAME_PARENT_VER_SHIFT), priority (DEFAULT_BMPN_PRIORITY), transparency_colour_union(0), enum_id(0)
#if cencon
, md5val(0)
#endif
{
filename = new char [strlen(fname)+1];
strcpy (filename, fname);
}
BMP_Name::BMP_Name (const char * fname)
: flags((BMPN_Flags)DEFAULT_BMPN_FLAGS), index(0), version_num (0), priority (DEFAULT_BMPN_PRIORITY), transparency_colour_union(0), enum_id(0)
#if cencon
, md5val(0)
#endif
{
filename = new char [strlen(fname)+1];
strcpy (filename, fname);
}
BMP_Name::~BMP_Name ()
{
if (filename)
delete [] filename;
}
BMP_Name::BMP_Name (const BMP_Name & bn)
{
if (&bn == this) return;
filename = new char [strlen(bn.filename)+1];
strcpy (filename, bn.filename);
flags = bn.flags;
index = bn.index;
version_num = bn.version_num;
enum_id = bn.enum_id;
priority = bn.priority;
transparency_colour_union = bn.transparency_colour_union;
#if cencon
md5val = bn.md5val;
#endif
}
void BMP_Name::Validate(void)
{
if (flags & ChunkBMPFlag_PriorityAndTransparencyAreValid) return;
priority = DEFAULT_BMPN_PRIORITY;
flags = (BMPN_Flags)(flags | DEFAULT_BMPN_FLAGS);
}
const BMP_Name & BMP_Name::operator=(const BMP_Name & bn)
{
if (&bn == this) return(*this);
if (filename)
delete [] filename;
filename = new char [strlen(bn.filename)+1];
strcpy (filename, bn.filename);
flags = bn.flags;
index = bn.index;
version_num = bn.version_num;
enum_id = bn.enum_id;
priority = bn.priority;
transparency_colour_union = bn.transparency_colour_union;
#if cencon
md5val = bn.md5val;
#endif
return(*this);
}
BOOL operator==(const BMP_Name &o1, const BMP_Name &o2)
{
if (o1.filename && o2.filename) return _stricmp(o1.filename,o2.filename) ? FALSE : TRUE;
else return &o1 == &o2;
}
BOOL operator!=(const BMP_Name &o1, const BMP_Name &o2)
{
if (o1.filename && o2.filename) return _stricmp(o1.filename,o2.filename) ? TRUE : FALSE;
else return &o1 != &o2;
}
///////////////////////////////////////
// Class Chunk_With_BMPs functions
Chunk_With_BMPs::Chunk_With_BMPs (Chunk_With_Children * parent, const char * const ident, const char * bdata, size_t /*bsize*/)
: Chunk (parent, ident), max_index (0)
{
int temp = *(int *)bdata;
int num = temp & 0xffff;
int ver_num = temp >> 16 & 0xffff; // the remains of a previous mistake - not really necessary anymore
bdata += 4;
for (int i=0; i<num; i++)
{
int f,i,d1,d2,d3;
f = *((int *)bdata);
bdata += 4;
i = *((int *)bdata);
bdata += 4;
d1 = *((int *)bdata);
bdata += 4;
d2 = *((int *)bdata);
bdata += 4;
d3 = *((int *)bdata);
bdata += 4;
BMP_Name bn (bdata);
bdata += (4-strlen(bn.filename)%4) + strlen(bn.filename);
bn.flags = (BMPN_Flags)f;
bn.index = i;
bn.version_num = d1 & BMPNAME_VERSION_NUM_MASK;
bn.enum_id = (int)((unsigned int)d1 >> BMPNAME_ENUMID_SHIFT);
bn.priority = d2;
bn.transparency_colour_union = d3;
max_index = max (bn.index, max_index);
bmps.add_entry (bn);
}
if (ver_num)
{
set_version_num(ver_num);
}
}
size_t Chunk_With_BMPs::size_chunk ()
{
int sz = 12 + 4;
for (LIF<BMP_Name> bl(&bmps); !bl.done(); bl.next())
{
sz += (4-strlen(bl().filename)%4) + strlen(bl().filename) + 20;
}
chunk_size = sz;
return (chunk_size);
}
void Chunk_With_BMPs::fill_data_block (char * data_start)
{
strncpy (data_start, identifier, 8);
data_start += 8;
*((int *) data_start) = chunk_size;
data_start += 4;
*((int *) data_start) = bmps.size();
data_start += 4;
for (LIF<BMP_Name> bl(&bmps); !bl.done(); bl.next())
{
*((int *) data_start) = bl().flags;
data_start += 4;
*((int *) data_start) = bl().index;
data_start += 4;
*((int *) data_start) = bl().version_num & BMPNAME_VERSION_NUM_MASK | bl().enum_id << BMPNAME_ENUMID_SHIFT;
data_start += 4;
*((int *) data_start) = bl().priority;
data_start += 4;
*((int *) data_start) = bl().transparency_colour_union;
data_start += 4;
strcpy (data_start, bl().filename);
data_start += (4-strlen(bl().filename)%4) + strlen(bl().filename);
}
}
int Chunk_With_BMPs::get_version_num(void)
{
if (parent)
{
List<Chunk *> verlist;
parent->lookup_child("BMNAMVER",verlist);
while (verlist.size()>1)
{
Chunk * v1 = verlist.first_entry();
Chunk * v2 = verlist[1];
if (((BMP_Names_Version_Chunk *)v1)->version_num > ((BMP_Names_Version_Chunk *)v2)->version_num)
{
delete verlist.last_entry();
verlist.delete_last_entry();
}
else
{
delete v1;
verlist.delete_first_entry();
}
}
if (verlist.size())
{
int rv = ((BMP_Names_Version_Chunk *)verlist.first_entry())->version_num;
return rv;
}
}
return 0;
}
void Chunk_With_BMPs::set_version_num(int v)
{
if (parent)
{
List<Chunk *> verlist;
parent->lookup_child("BMNAMVER",verlist);
while (verlist.size()>1)
{
Chunk * v1 = verlist.first_entry();
Chunk * v2 = verlist[1];
if (((BMP_Names_Version_Chunk *)v1)->version_num > ((BMP_Names_Version_Chunk *)v2)->version_num)
{
delete verlist.last_entry();
verlist.delete_last_entry();
}
else
{
delete v1;
verlist.delete_first_entry();
}
}
if (verlist.size())
{
((BMP_Names_Version_Chunk *)verlist.first_entry())->version_num = v;
return;
}
(new BMP_Names_Version_Chunk(parent))->version_num = v;
}
}
void Chunk_With_BMPs::inc_version_num(void)
{
if (parent)
{
List<Chunk *> verlist;
parent->lookup_child("BMNAMVER",verlist);
while (verlist.size()>1)
{
Chunk * v1 = verlist.first_entry();
Chunk * v2 = verlist[1];
if (((BMP_Names_Version_Chunk *)v1)->version_num > ((BMP_Names_Version_Chunk *)v2)->version_num)
{
delete verlist.last_entry();
verlist.delete_last_entry();
}
else
{
delete v1;
verlist.delete_first_entry();
}
}
if (verlist.size())
{
((BMP_Names_Version_Chunk *)verlist.first_entry())->version_num ++;
return;
}
(new BMP_Names_Version_Chunk(parent))->version_num ++;
}
}
BMP_Names_ExtraData * Chunk_With_BMPs::GetExtendedData(void)
{
if (parent)
{
List<Chunk *> verlist;
parent->lookup_child("BMNAMEXT",verlist);
if (verlist.size())
{
return (BMP_Names_ExtraData_Chunk *) verlist.first_entry();
}
return new BMP_Names_ExtraData_Chunk(parent);
}
return 0;
}
int const * Chunk_With_BMPs::GetMD5Val(BMP_Name const & rcbmp)
{
Bitmap_MD5_Chunk * md5c = GetMD5Chunk(rcbmp.filename);
if (md5c)
if (rcbmp.version_num == md5c->version_num)
return md5c->md5_val;
return 0;
}
void Chunk_With_BMPs::RemoveMD5Val(char const * bname)
{
Bitmap_MD5_Chunk * md5c = GetMD5Chunk(bname);
if (md5c)
delete md5c;
}
void Chunk_With_BMPs::SetMD5Val(BMP_Name const & rcbmp, int const * md5id)
{
Bitmap_MD5_Chunk * md5c = GetMD5Chunk(rcbmp.filename);
if (md5c)
{
if (rcbmp.version_num == md5c->version_num)
{
memcpy(md5c->md5_val,md5id,16);
return;
}
else
delete md5c;
}
CreateMD5Chunk(rcbmp,md5id);
}
/////////////////////////////////////
// Global_BMP_Name_Chunk
/////////////////////////////////////
RIF_IMPLEMENT_DYNCREATE("BMPNAMES",Global_BMP_Name_Chunk)
Bitmap_MD5_Chunk * Global_BMP_Name_Chunk::GetMD5Chunk(char const * bname)
{
List<Chunk *> chlst;
parent->lookup_child("BMPMD5ID",chlst);
for (LIF<Chunk *> i_chlst(&chlst); !i_chlst.done(); i_chlst.next())
{
Bitmap_MD5_Chunk * md5c = (Bitmap_MD5_Chunk *)i_chlst();
if (!strcmp(md5c->bmpname,bname))
if (!(md5c->rifname ? *md5c->rifname : 1) && !(md5c->shapename ? *md5c->shapename : 1))
return md5c;
}
return 0;
}
void Global_BMP_Name_Chunk::CreateMD5Chunk(BMP_Name const & rcbmp, int const * md5id)
{
new Bitmap_MD5_Chunk(parent,md5id,rcbmp);
}
/////////////////////////////////////
// Bitmap_List_Store_Chunk
/////////////////////////////////////
RIF_IMPLEMENT_DYNCREATE("BMPLSTST",Bitmap_List_Store_Chunk)
Bitmap_MD5_Chunk * Bitmap_List_Store_Chunk::GetMD5Chunk(char const * bname)
{
List<Chunk *> chlst;
parent->lookup_child("BMPMD5ID",chlst);
List<Chunk *> rnlst;
parent->lookup_child("RIFFNAME",rnlst);
char const * rname = 0;
if (rnlst.size())
{
rname = ((RIF_Name_Chunk *)rnlst.first_entry())->rif_name;
}
for (LIF<Chunk *> i_chlst(&chlst); !i_chlst.done(); i_chlst.next())
{
Bitmap_MD5_Chunk * md5c = (Bitmap_MD5_Chunk *)i_chlst();
if (!strcmp(md5c->bmpname,bname))
if (!(md5c->rifname ? rname ? strcmp(rname,md5c->rifname) : *md5c->rifname : rname ? *rname : 0) &&
!(md5c->shapename ? *md5c->shapename : 1))
return md5c;
}
return 0;
}
void Bitmap_List_Store_Chunk::CreateMD5Chunk(BMP_Name const & rcbmp, int const * md5id)
{
List<Chunk *> rnlst;
parent->lookup_child("RIFFNAME",rnlst);
char const * rname = 0;
if (rnlst.size())
{
rname = ((RIF_Name_Chunk *)rnlst.first_entry())->rif_name;
}
new Bitmap_MD5_Chunk(parent,md5id,rcbmp,rname);
}
///////////////////////////////////////
// Class BMP_Names_Version_Chunk functions
RIF_IMPLEMENT_DYNCREATE("BMNAMVER",BMP_Names_Version_Chunk)
size_t BMP_Names_Version_Chunk::size_chunk ()
{
chunk_size = 12+4;
return (chunk_size);
}
void BMP_Names_Version_Chunk::fill_data_block (char * data_start)
{
strncpy (data_start, identifier, 8);
data_start += 8;
*((int *) data_start) = chunk_size;
data_start += 4;
*((int *) data_start) = version_num;
}
///////////////////////////////////////
// Class BMP_Names_ExtraData_Chunk functions
RIF_IMPLEMENT_DYNCREATE("BMNAMEXT",BMP_Names_ExtraData_Chunk)
size_t BMP_Names_ExtraData_Chunk::size_chunk ()
{
chunk_size = 12+52;
return (chunk_size);
}
void BMP_Names_ExtraData_Chunk::fill_data_block (char * data_start)
{
strncpy (data_start, identifier, 8);
data_start += 8;
*((int *) data_start) = chunk_size;
data_start += 4;
*((int *) data_start) = flags;
data_start += 4;
for (int i=0; i<12; ++i, data_start+=4)
{
*(int *)data_start = reserved[i];
}
}
///////////////////////////////////////
// Class External_Shape_BMPs_Store_Chunk functions
RIF_IMPLEMENT_DYNCREATE("SHBMPNAM",External_Shape_BMPs_Store_Chunk)
External_Shape_BMPs_Store_Chunk::External_Shape_BMPs_Store_Chunk (Chunk_With_Children * parent, char const * rifn, char const * shapen)
: Chunk_With_BMPs (parent, "SHBMPNAM"), rifname(0), shapename(0), version_num(0)
{
for (int i=0; i<12; ++i)
reserved[i] = 0;
flags = GBF_NONE;
if (rifn)
{
rifname = new char [strlen(rifn)+1];
strcpy(rifname,rifn);
}
if (shapen)
{
shapename = new char [strlen(shapen)+1];
strcpy(shapename,shapen);
}
}
External_Shape_BMPs_Store_Chunk::~External_Shape_BMPs_Store_Chunk()
{
if (rifname) delete[] rifname;
if (shapename) delete[] shapename;
}
void External_Shape_BMPs_Store_Chunk::fill_data_block(char * data_start)
{
Chunk_With_BMPs::fill_data_block(data_start);
data_start += Chunk_With_BMPs::size_chunk();
size_chunk(); // resize it just in case
strcpy(data_start,rifname ? rifname : "");
unsigned int const l1 = rifname ? strlen(rifname)+1 : 1;
strcpy(data_start+l1,shapename ? shapename : "");
unsigned int const l2 = shapename ? strlen(shapename)+1 : 1;
data_start += l1+l2 +3&~3;
*(int *)data_start = flags;
data_start+=4;
*(int *)data_start = version_num;
data_start+=4;
for (int i=0; i<12; ++i, data_start+=4)
*(int *)data_start = reserved[i];
}
External_Shape_BMPs_Store_Chunk::External_Shape_BMPs_Store_Chunk (Chunk_With_Children * parent, const char * sdata, size_t ssize)
: Chunk_With_BMPs (parent, "SHBMPNAM", sdata, ssize)
{
sdata += Chunk_With_BMPs::size_chunk() -12;
unsigned int const l1 = strlen(sdata)+1;
rifname = new char [l1];
strcpy(rifname,sdata);
unsigned int const l2 = strlen(sdata+l1)+1;
shapename = new char [l2];
strcpy(shapename,sdata+l1);
sdata += l1+l2 +3&~3;
flags = (GlobalBMPFlags)(*(int *)sdata & GBF_MASK);
sdata+=4;
version_num = *(int *)sdata;
sdata+=4;
for (int i=0; i<12; ++i, sdata+=4)
reserved[i] = *(int *)sdata;
}
Bitmap_MD5_Chunk * External_Shape_BMPs_Store_Chunk::GetMD5Chunk(char const * bname)
{
List<Chunk *> chlst;
parent->lookup_child("BMPMD5ID",chlst);
for (LIF<Chunk *> i_chlst(&chlst); !i_chlst.done(); i_chlst.next())
{
Bitmap_MD5_Chunk * md5c = (Bitmap_MD5_Chunk *)i_chlst();
if (!strcmp(md5c->bmpname,bname))
if (!(md5c->rifname ? rifname ? strcmp(rifname,md5c->rifname) : *md5c->rifname : rifname ? *rifname : 0) &&
!(md5c->shapename ? shapename ? strcmp(shapename,md5c->shapename) : *md5c->shapename : shapename ? *shapename : 0) &&
(flags & GBF_SPRITE && md5c->flags & BMD5F_SPRITE || !(flags & GBF_SPRITE) && !(md5c->flags & BMD5F_SPRITE)))
return md5c;
}
return 0;
}
void External_Shape_BMPs_Store_Chunk::CreateMD5Chunk(BMP_Name const & rcbmp, int const * md5id)
{
Bitmap_MD5_Chunk * md5c = new Bitmap_MD5_Chunk(parent,md5id,rcbmp,rifname,shapename);
md5c->flags = flags & GBF_SPRITE ? BMD5F_SPRITE : BMD5F_0;
}
/*************************/
/* matching images stuff */
/*************************/
// class ImageDescriptor
// ---------------------
ImageDescriptor::ImageDescriptor()
: filename(0)
, rifname(0)
, fixrifname(0)
{
}
ImageDescriptor::ImageDescriptor(ImageDescriptor const & id2)
: flags(id2.flags)
, filename(0)
, rifname(0)
, fixrifname(0)
{
spares[0] = id2.spares[0];
spares[1] = id2.spares[1];
spares[2] = id2.spares[2];
if (id2.filename)
{
filename = new char [strlen(id2.filename)+1];
strcpy(filename,id2.filename);
}
if (id2.rifname)
{
rifname = new char [strlen(id2.rifname)+1];
strcpy(rifname,id2.rifname);
}
if (id2.fixrifname)
{
fixrifname = new char [strlen(id2.fixrifname)+1];
strcpy(fixrifname,id2.fixrifname);
}
}
ImageDescriptor::ImageDescriptor(IDscFlags idscf, char const * fname, char const * rname, char const * xname)
: flags(idscf)
, filename(0)
, rifname(0)
, fixrifname(0)
{
spares[0] = 0;
spares[1] = 0;
spares[2] = 0;
if (fname)
{
filename = new char [strlen(fname)+1];
strcpy(filename,fname);
}
if (rname)
{
rifname = new char [strlen(rname)+1];
strcpy(rifname,rname);
}
if (xname)
{
fixrifname = new char [strlen(xname)+1];
strcpy(fixrifname,xname);
}
}
ImageDescriptor::~ImageDescriptor()
{
if (filename) delete[] filename;
if (rifname) delete[] rifname;
if (fixrifname) delete[] fixrifname;
}
ImageDescriptor & ImageDescriptor::operator = (ImageDescriptor const & id2)
{
if (&id2 != this)
{
flags = id2.flags;
spares[0] = id2.spares[0];
spares[1] = id2.spares[1];
spares[2] = id2.spares[2];
if (filename)
{
delete[] filename;
filename = 0;
}
if (rifname)
{
delete[] rifname;
rifname = 0;
}
if (fixrifname)
{
delete[] fixrifname;
fixrifname = 0;
}
if (id2.filename)
{
filename = new char [strlen(id2.filename)+1];
strcpy(filename,id2.filename);
}
if (id2.rifname)
{
rifname = new char [strlen(id2.rifname)+1];
strcpy(rifname,id2.rifname);
}
if (id2.fixrifname)
{
fixrifname = new char [strlen(id2.fixrifname)+1];
strcpy(fixrifname,id2.fixrifname);
}
}
return *this;
}
// I/O
ImageDescriptor::ImageDescriptor(char const * datablock)
: flags((IDscFlags)(*(int const *)datablock & IDSCF_MASK))
{
spares[0] = *(int const *)(datablock+4);
spares[1] = *(int const *)(datablock+8);
spares[2] = *(int const *)(datablock+12);
datablock += 16;
size_t len = strlen(datablock)+1;
filename = new char[len];
strcpy(filename,datablock);
datablock += len;
len = strlen(datablock)+1;
rifname = new char[len];
strcpy(rifname,datablock);
datablock += len;
len = strlen(datablock)+1;
fixrifname = new char[len];
strcpy(fixrifname,datablock);
}
size_t ImageDescriptor::Size() const
{
return 16
+ (filename ? strlen(filename) : 0)
+ (rifname ? strlen(rifname) : 0)
+ (fixrifname ? strlen(fixrifname) : 0)
+ 3
+3&~3;
}
void ImageDescriptor::WriteData(char * datablock) const
{
*(int *)datablock = flags;
*(int *)(datablock+4) = spares[0];
*(int *)(datablock+8) = spares[1];
*(int *)(datablock+12) = spares[2];
datablock+=16;
strcpy(datablock,filename ? filename : "");
datablock += strlen(datablock)+1;
strcpy(datablock,rifname ? rifname : "");
datablock += strlen(datablock)+1;
strcpy(datablock,fixrifname ? fixrifname : "");
}
// operators
BOOL ImageDescriptor::operator == (ImageDescriptor const & id2) const
{
if (flags!=id2.flags) return FALSE;
if (_stricmp(filename ? filename : "",id2.filename ? id2.filename : "")) return FALSE;
if (_stricmp(rifname ? rifname : "",id2.rifname ? id2.rifname : "")) return FALSE;
if (_stricmp(fixrifname ? fixrifname : "",id2.fixrifname ? id2.fixrifname : "")) return FALSE;
return TRUE;
}
// class MatchingImages
// --------------------
// constructos;
MatchingImages::MatchingImages(ImageDescriptor const & _load, ImageDescriptor const & _insteadof)
: load(_load)
, insteadof(_insteadof)
{
spares[0] = 0;
spares[1] = 0;
spares[2] = 0;
}
// I/O
MatchingImages::MatchingImages(char const * datablock)
: load(datablock+12)
, insteadof(datablock+12+load.Size())
{
spares[0] = *(int const *)datablock;
spares[1] = *(int const *)(datablock+4);
spares[2] = *(int const *)(datablock+8);
}
size_t MatchingImages::Size() const
{
return 12 + load.Size() + insteadof.Size();
}
void MatchingImages::WriteData(char * datablock) const
{
*(int *)datablock = spares[0];
*(int *)(datablock+4) = spares[1];
*(int *)(datablock+8) = spares[2];
load.WriteData(datablock+12);
insteadof.WriteData(datablock+12+load.Size());
}
// class Matching_Images_Chunk : public Chunk
// ------------------------------------------
RIF_IMPLEMENT_DYNCREATE("MATCHIMG",Matching_Images_Chunk)
// I/O
Matching_Images_Chunk::Matching_Images_Chunk(Chunk_With_Children * parent, char const * datablock, size_t size)
: Chunk(parent,"MATCHIMG")
, flags ((MICFlags)(*(int *)(datablock+8) & MICF_MASK))
{
char const * datastart = datablock;
spares[0] = *(int *)datablock;
spares[1] = *(int *)(datablock+4);
int listsize = *(int *)(datablock+12);
datablock += 16;
for (;listsize; --listsize)
{
mlist.add_entry_end(datablock);
datablock += mlist.last_entry().Size();
}
assert(datastart + size == datablock);
}
size_t Matching_Images_Chunk::size_chunk()
{
chunk_size = 28; // 2dw spares, 1dw flags, 1dw list size, 12b header
for (LIF<MatchingImages> mlit(&mlist); !mlit.done(); mlit.next())
{
chunk_size += mlit().Size();
}
return chunk_size;
}
void Matching_Images_Chunk::fill_data_block(char * data_start)
{
strncpy (data_start, identifier, 8);
data_start += 8;
*(int *) data_start = chunk_size;
data_start += 4;
*(int *)data_start = spares[0];
*(int *)(data_start+4) = spares[1];
*(int *)(data_start+8) = flags;
*(int *)(data_start+12) = mlist.size();
data_start += 16;
for (LIF<MatchingImages> mlit(&mlist); !mlit.done(); mlit.next())
{
mlit().WriteData(data_start);
data_start += mlit().Size();
}
}
ImageDescriptor const & Matching_Images_Chunk::GetLoadImage(ImageDescriptor const & _insteadof)
{
for (LIF<MatchingImages> mlit(&mlist); !mlit.done(); mlit.next())
{
if (_insteadof == mlit().insteadof) return mlit().load;
}
return _insteadof;
}
// Bitmap MD5 Chunk
RIF_IMPLEMENT_DYNCREATE("BMPMD5ID",Bitmap_MD5_Chunk)
Bitmap_MD5_Chunk::Bitmap_MD5_Chunk(Chunk_With_Children * parent, int const * md5id, BMP_Name const & rcbmp, char const * rname, char const * sname)
: Chunk(parent,"BMPMD5ID"), spare(0), flags(BMD5F_0), version_num(rcbmp.version_num)
{
memcpy(md5_val,md5id,16);
char const * bname = rcbmp.filename;
if (!bname) bname = "";
bmpname = new char[strlen(bname)+1];
strcpy(bmpname,bname);
if (!rname) rname = "";
rifname = new char[strlen(rname)+1];
strcpy(rifname,rname);
if (!sname) sname = "";
shapename = new char[strlen(sname)+1];
strcpy(shapename,sname);
}
Bitmap_MD5_Chunk::Bitmap_MD5_Chunk(Chunk_With_Children * parent, char const * datablock, size_t)
: Chunk(parent,"BMPMD5ID"), spare(*(int *)datablock), flags((BMPMD5_Flags)(*(int *)(datablock+4) & BMD5F_MASK)), version_num(*(int *)(datablock+8))
{
memcpy(md5_val,datablock+12,16);
datablock += 28;
unsigned int const blen = strlen(datablock)+1;
bmpname = new char [blen];
strcpy(bmpname,datablock);
datablock += blen;
unsigned int const rlen = strlen(datablock)+1;
rifname = new char [rlen];
strcpy(rifname,datablock);
datablock += rlen;
unsigned int const slen = strlen(datablock)+1;
shapename = new char [slen];
strcpy(shapename,datablock);
}
Bitmap_MD5_Chunk::~Bitmap_MD5_Chunk()
{
delete [] bmpname;
delete [] rifname;
delete [] shapename;
}
void Bitmap_MD5_Chunk::fill_data_block(char * datastart)
{
strncpy (datastart, identifier, 8);
datastart += 8;
*((int *) datastart) = chunk_size;
datastart += 4;
*(int *)datastart = spare;
*(int *)(datastart+4) = flags;
*(int *)(datastart+8) = version_num;
memcpy(datastart+12,md5_val,16);
datastart += 28;
strcpy(datastart,bmpname ? bmpname : "");
datastart += strlen(datastart)+1;
strcpy(datastart,rifname ? rifname : "");
datastart += strlen(datastart)+1;
strcpy(datastart,shapename ? shapename : "");
}
size_t Bitmap_MD5_Chunk::size_chunk()
{
return chunk_size = 12+28
+(bmpname ? strlen(bmpname) : 0)
+(rifname ? strlen(rifname) : 0)
+(shapename ? strlen(shapename) : 0)
+3 +3&~3;
}

727
src/win95/bmpnames.hpp Normal file
View file

@ -0,0 +1,727 @@
#ifndef _bmpnames_hpp_
#define _bmpnames_hpp_
#include "chunk.hpp"
// for assert
#if engine
#define UseLocalAssert No
#include "ourasert.h"
#define assert(x) GLOBALASSERT(x)
#else
#if cencon
#include "ccassert.h"
#else
#include <assert.h>
#endif
#endif
enum BMPN_Flags
{
ChunkBMPFlag_Null = 0x00000000, // all flags reset
ChunkBMPFlag_NotInShape = 0x00000001, // not a texture map, maybe a sprite or hud graphic
ChunkBMPFlag_UsesTransparency = 0x00000002, // transparency_colour defines invisible pixels
ChunkBMPFlag_RequireGameMipMaps = 0x00000004, // mip maps are required for the game
ChunkBMPFlag_RequireToolsMipMaps = 0x00000008, // mip maps are required for the interface engine
ChunkBMPFlag_MipMapsExist = 0x00000010, // internal mip maps are up to date
ChunkBMPFlag_NotLit = 0x00000020, // not light sourced (eg. hud, iflag_nolight), so do not put darker colours into palette
ChunkBMPFlag_FixedPalette = 0x00000040, // will be quantized once only to a fixed sub-palette of each main palette
ChunkBMPFlag_Quantized = 0x00000080, // .PG0 exists which corresponds to the palette
// See below 0x00000100
ChunkBMPFlag_MipMapsQuantized = 0x00000200, // .PG1-.PG6 exist which correspond to the palette and are mip maps
ChunkBMPFlag_PP0Exists = 0x00000400, // internal .PP0 exists
ChunkBMPFlag_NotInPC = 0x00000800, // for reduced memory, reduced features on some platforms
ChunkBMPFlag_NotInSaturn = 0x00001000, // for reduced memory, reduced features on some platforms
ChunkBMPFlag_NotInPlaystation = 0x00002000, // for reduced memory, reduced features on some platforms
ChunkBMPFlag_BM0Exists = 0x00004000, // 256 colour palettized texture for hw accelerators exists
ChunkBMPFlag_BMnsExist = 0x00008000, // mip mapped versions of 256 colour palettized texture exist
ChunkBMP_Dither = 0x00070000, //
ChunkBMP_DitherFloyd = 0x00010000, //
ChunkBMP_DitherFloydDamp1 = 0x00020000, //
ChunkBMP_DitherFloydDamp2 = 0x00030000, // 3 bits to control the type of error diffusion (if any)
ChunkBMP_DitherJarvis = 0x00040000, //
ChunkBMP_DitherJarvisDamp1 = 0x00050000, //
ChunkBMP_DitherJarvisDamp2 = 0x00060000, //
ChunkBMPFlag_RqQuantLUV = 0x00080000, // Remap in LUV colour space
ChunkBMPFlag_HistogramExists = 0x00100000, // used by cencon in palette generation - help by outputting .HST files
ChunkBMPFlag_HistogramV2Exists = 0x00200000, // used by cencon in palette generation - help by outputting .HS2 files (non-lit histograms for lit bitmaps with conceptual tlt palette)
ChunkBMPFlag_CopiedGenMipMaps = 0x00400000, // mip map HW generic textures have been copied to final dest
ChunkBMPFlag_CopiedGenBaseTex = 0x00800000, // base (non-mip) HW generic textures have been copied to final dest
ChunkBMPFlag_IFF = 0x01000000, // a very important flag indeed:
// when this flag is set, the file is an IFF file and the filename stores a
// full relative path from the 'textures-root' directory for the project
// all other flags are complete bollocks when this flag is set
// (except for the NotIn.... flags)
// all this data will be in the file itself (transparency data anyway,,,)
// the file can be updated without the use of cencon, so for this reason
// I'll store the widths and heights where the transparent colour used
// to be. I'll also provide member-access functions to access this data
// which will check the flag is correct
// This flag will be set on newer RIF files, because older ones will have priorities of 0 which is not ideal!
// When a chunk with these flag not set is detected, default values are filled in and the old values are not used.
ChunkBMPFlag_PriorityAndTransparencyAreValid = 0x00000100
};
//I have removed transparency from the default flags at the request of the artists
// default flags for new bitmaps
#define DEFAULT_BMPN_FLAGS ((BMPN_Flags) ( \
ChunkBMPFlag_PriorityAndTransparencyAreValid | \
ChunkBMPFlag_RequireToolsMipMaps | /* test */ \
ChunkBMPFlag_RequireGameMipMaps ))
// user flags that should correspond for corresponding bitmaps
#define COPY_BMPN_FLAGS ((BMPN_Flags) ( \
ChunkBMPFlag_NotInShape | \
ChunkBMPFlag_UsesTransparency | \
ChunkBMPFlag_RequireToolsMipMaps | \
ChunkBMPFlag_RequireGameMipMaps | \
ChunkBMPFlag_MipMapsExist | \
ChunkBMPFlag_BMnsExist | \
ChunkBMPFlag_BM0Exists | \
ChunkBMPFlag_PP0Exists | \
ChunkBMPFlag_NotLit | \
ChunkBMPFlag_FixedPalette | \
ChunkBMPFlag_NotInPC | \
ChunkBMPFlag_NotInSaturn | \
ChunkBMPFlag_NotInPlaystation | \
ChunkBMP_Dither | \
ChunkBMPFlag_RqQuantLUV | \
ChunkBMPFlag_IFF))
// flags that when changed require requantizing
#define CHECKMODIFY_BMPN_FLAGS ((BMPN_Flags) ( \
ChunkBMPFlag_UsesTransparency | \
ChunkBMPFlag_FixedPalette /* not sure */ | \
ChunkBMP_Dither | \
ChunkBMPFlag_RqQuantLUV ))
// flags to reset if a bitmap needs requantizing
#define QUANTIZED_BMPN_FLAGS ((BMPN_Flags) ( \
ChunkBMPFlag_Quantized | \
ChunkBMPFlag_MipMapsQuantized ))
#define COMPLETED_BMPN_FLAGS ((BMPN_Flags) ( \
ChunkBMPFlag_CopiedGenBaseTex | \
ChunkBMPFlag_CopiedGenMipMaps | \
QUANTIZED_BMPN_FLAGS ))
#define DEFAULT_BMPN_PRIORITY 6
extern void Palette_Outdated(Chunk_With_Children * parent); // decalred here, defined in chunkpal to avoid extra compiler dependencies
extern void FixedPalette_Outdated(Chunk_With_Children * parent); // decalred here, defined in chunkpal to avoid extra compiler dependencies
extern BOOL IsFixedPalette(Chunk_With_Children * parent);
class BMP_Name
{
public:
BMP_Name(const char * fname, int const gbnc_version);
~BMP_Name();
BMP_Name(const BMP_Name &);
const BMP_Name & operator=(const BMP_Name &);
char * filename;
BMPN_Flags flags;
int index;
int version_num;
int enum_id;
#define BMPNAME_PARENT_VER_SHIFT 8
// version num contains bmp version num (incremental on update)
// and Global_BMP_Name_Chunk version (at the time of creation) num shifted up
// This is so that if a bitmap is removed and then added, its
// version num will still be greater than that of the removed version
#define BMPNAME_VERSION_NUM_MASK 0x000fffff
#define BMPNAME_ENUMID_SHIFT 20
// the top 12 bits of the previously spare data item (data1)
// contain an enumeration constant (max 4095)
// and the bottom 20 bits are available for version numbers
// a bit cramped and not ideal, but we are running out of storage space
// there are still two bytes free(0) in the priority data
#define MAX_PC_PRIORITY 0xff
#define MAX_PSX_PRIORITY 0xff
inline int get_pc_priority(void) const { return priority & 0xff; }
inline int get_psx_priority(void) const { return priority >> 8 & 0xff; }
inline void set_pc_priority(int const p) { priority &= ~0xff; priority |= p & 0xff; }
inline void set_psx_priority(int const p) { priority &= ~0xff00; priority |= (p & 0xff) << 8; }
friend BOOL operator==(const BMP_Name &o1, const BMP_Name &o2);
friend BOOL operator!=(const BMP_Name &o1, const BMP_Name &o2);
BMP_Name()
: filename(0), flags((BMPN_Flags)DEFAULT_BMPN_FLAGS), index(0), version_num (0), priority (DEFAULT_BMPN_PRIORITY), transparency_colour_union(0) {}
void Validate(void);
#if cencon
int const * md5val; // space to put a pointer
void DeleteAssociatedFiles() const;
void DeleteAssociatedMipFiles() const;
// changes the filename member, returns FALSE on failure
BOOL Rename(char const * newname);
// use these to prevent DeleteAssociatedMipFiles & DeleteAssociatedFiles
// from deleting specific files
static void PreventDeleteFile(char const * pszFileName);
static void ReallowDeleteFile(char const * pszFileName);
private:
static List<char *> ms_listFilesCantDelete;
static void DeleteFileProt(char const * pszFileName);
public:
#endif
unsigned GetTranspRedVal() const;
unsigned GetTranspGreenVal() const;
unsigned GetTranspBlueVal() const;
unsigned GetWidth() const;
unsigned GetHeight() const;
void SetTranspRedVal(unsigned);
void SetTranspGreenVal(unsigned);
void SetTranspBlueVal(unsigned);
void SetWidth(unsigned);
void SetHeight(unsigned);
// copy all data
void CopyUnionDataFrom(BMP_Name const & rBmp);
bool DifferentTransparencyColour(BMP_Name const & rBmp) const;
enum
{
MAXVAL_RGB = 0xff,
MAXVAL_WH = 0xffff
};
private:
int priority; // contains pc palettized mode palette generating priority as well as 16/256 colour priority for attahced palettes
enum
{
SHIFT_R = 22,
SHIFT_G = 12,
SHIFT_B = 2,
SHIFT_W = 0,
SHIFT_H = 16
};
unsigned transparency_colour_union; // == r<<22 + g<<12 + b << 2 ; r,g,b <- [0..255], but don't assume this'll always be the case
// or H<<16 + W
BMP_Name(const char * fname);
// initial part of constructor from buffer.
// GBNC and BLSC loaders find the rest of the data
// and put it into the BMP_Name object constructed with this constructor
friend class Chunk_With_BMPs;
friend class BMP_Flags;
};
// functions to access the union transparency_colour_union which isn't a real C/C++ union
// they will check that you're performing valid accesses (ie. using the right part of the union)
// if you're a friend class, please ensure you use these access functions or know what you're doing
inline unsigned BMP_Name::GetTranspRedVal() const
{
assert(!(flags & ChunkBMPFlag_IFF)); // not available for IFF files - it's in the file
return transparency_colour_union >> SHIFT_R & MAXVAL_RGB;
}
inline unsigned BMP_Name::GetTranspGreenVal() const
{
assert(!(flags & ChunkBMPFlag_IFF)); // not available for IFF files - it's in the file
return transparency_colour_union >> SHIFT_G & MAXVAL_RGB;
}
inline unsigned BMP_Name::GetTranspBlueVal() const
{
assert(!(flags & ChunkBMPFlag_IFF)); // not available for IFF files - it's in the file
return transparency_colour_union >> SHIFT_B & MAXVAL_RGB;
}
inline unsigned BMP_Name::GetWidth() const
{
assert(flags & ChunkBMPFlag_IFF); // only available for IFF files - required since they can be modified externally
return transparency_colour_union >> SHIFT_W & MAXVAL_WH;
}
inline unsigned BMP_Name::GetHeight() const
{
assert(flags & ChunkBMPFlag_IFF); // only available for IFF files - required since they can be modified externally
return transparency_colour_union >> SHIFT_H & MAXVAL_WH;
}
inline void BMP_Name::SetTranspRedVal(unsigned v)
{
assert(!(flags & ChunkBMPFlag_IFF)); // not available for IFF files - it's in the file
assert(v<=MAXVAL_RGB); // sensible value
transparency_colour_union &= ~(MAXVAL_RGB << SHIFT_R);
transparency_colour_union |= v << SHIFT_R;
}
inline void BMP_Name::SetTranspGreenVal(unsigned v)
{
assert(!(flags & ChunkBMPFlag_IFF)); // not available for IFF files - it's in the file
assert(v<=MAXVAL_RGB); // sensible value
transparency_colour_union &= ~(MAXVAL_RGB << SHIFT_G);
transparency_colour_union |= v << SHIFT_G;
}
inline void BMP_Name::SetTranspBlueVal(unsigned v)
{
assert(!(flags & ChunkBMPFlag_IFF)); // not available for IFF files - it's in the file
assert(v<=MAXVAL_RGB); // sensible value
transparency_colour_union &= ~(MAXVAL_RGB << SHIFT_B);
transparency_colour_union |= v << SHIFT_B;
}
inline void BMP_Name::SetWidth(unsigned v)
{
assert(flags & ChunkBMPFlag_IFF); // only available for IFF files - required since they can be modified externally
assert(v<=MAXVAL_WH); // sensible value
transparency_colour_union &= ~(MAXVAL_WH << SHIFT_W);
transparency_colour_union |= v << SHIFT_W;
}
inline void BMP_Name::SetHeight(unsigned v)
{
assert(flags & ChunkBMPFlag_IFF); // only available for IFF files - required since they can be modified externally
assert(v<=MAXVAL_WH); // sensible value
transparency_colour_union &= ~(MAXVAL_WH << SHIFT_H);
transparency_colour_union |= v << SHIFT_H;
}
inline void BMP_Name::CopyUnionDataFrom(BMP_Name const & rBmp)
{
assert((flags & ChunkBMPFlag_IFF)==(rBmp.flags & ChunkBMPFlag_IFF));
transparency_colour_union = rBmp.transparency_colour_union;
}
inline bool BMP_Name::DifferentTransparencyColour(BMP_Name const & rBmp) const
{
assert(!(flags & ChunkBMPFlag_IFF) && !(rBmp.flags & ChunkBMPFlag_IFF));
return transparency_colour_union != rBmp.transparency_colour_union;
}
///////////////////////////////////////////////
class BMP_Names_ExtraData;
class Bitmap_MD5_Chunk;
class Chunk_With_BMPs : public Chunk
{
public:
int max_index;
List<BMP_Name> bmps;
virtual int get_version_num(void);
virtual void set_version_num(int);
virtual void inc_version_num(void);
virtual BMP_Names_ExtraData * GetExtendedData(void);
virtual int const * GetMD5Val(BMP_Name const & rcbmp);
virtual void SetMD5Val(BMP_Name const & rcbmp, int const * md5id);
virtual void RemoveMD5Val(char const * bname);
friend class BMP_Group; // for cencon
friend class BMP_Info; // for cencon
protected:
virtual Bitmap_MD5_Chunk * GetMD5Chunk(char const * bname) = 0;
virtual void CreateMD5Chunk(BMP_Name const & rcbmp, int const * md5id) = 0;
virtual size_t size_chunk ();
virtual void fill_data_block (char * data_start);
Chunk_With_BMPs (Chunk_With_Children * parent, const char * const ident) : Chunk(parent,ident), max_index(0) {}
Chunk_With_BMPs (Chunk_With_Children * parent, const char * const ident, const char * sdata, size_t ssize);
};
class Global_BMP_Name_Chunk : public Chunk_With_BMPs
{
public:
Global_BMP_Name_Chunk (Chunk_With_Children * parent)
: Chunk_With_BMPs (parent, "BMPNAMES")
{}
// constructor from buffer
Global_BMP_Name_Chunk (Chunk_With_Children * parent, const char * sdata, size_t ssize)
: Chunk_With_BMPs (parent, "BMPNAMES", sdata, ssize) {}
private:
virtual Bitmap_MD5_Chunk * GetMD5Chunk(char const * bname);
virtual void CreateMD5Chunk(BMP_Name const & rcbmp, int const * md5id);
friend class Environment_Data_Chunk;
};
class Bitmap_List_Store_Chunk : public Chunk_With_BMPs
{
public:
Bitmap_List_Store_Chunk (Chunk_With_Children * parent)
: Chunk_With_BMPs (parent, "BMPLSTST")
{}
// constructor from buffer
// not private, so that it is easy to get to
Bitmap_List_Store_Chunk (Chunk_With_Children * parent, const char * sdata, size_t ssize)
: Chunk_With_BMPs (parent, "BMPLSTST", sdata, ssize) {}
private:
virtual Bitmap_MD5_Chunk * GetMD5Chunk(char const * bname);
virtual void CreateMD5Chunk(BMP_Name const & rcbmp, int const * md5id);
friend class Shape_External_File_Chunk;
};
class BMP_Names_Version_Chunk : public Chunk
{
public:
BMP_Names_Version_Chunk (Chunk_With_Children * parent)
: Chunk (parent, "BMNAMVER"), version_num (0)
{}
// constructor from buffer
BMP_Names_Version_Chunk (Chunk_With_Children * parent, const char * sdata, size_t /*ssize*/)
: Chunk (parent, "BMNAMVER"), version_num(*(int *)sdata)
{}
virtual size_t size_chunk ();
virtual void fill_data_block (char * data_start);
private:
int version_num;
friend class Environment_Data_Chunk;
friend class Chunk_With_BMPs;
friend class Shape_External_File_Chunk;
friend class Sprite_Header_Chunk;
};
enum GlobalBMPFlags
{
GBF_FIXEDPALETTE = 0x00000001,
GBF_SPRITE = 0x00000002,
GBF_HISTOGRAMEXISTS = 0x00000004,
GBF_HISTOGRAMV2EXISTS = 0x00000008,
GBF_NONE = 0,
// IMPORTANT
// since enums are not guaranteed to assume any particular
// storage class, code compiled on different compilers or
// with different settings may result in enums to be written
// to the data block as a char and read back in as an int,
// with the three most significant bytes containing junk.
// THIS MASK MUST BE KEPT UP TO DATE AS THE ENUM IS EXTENDED;
// ALSO ENSURE THAT NEW FILES LOADED INTO OLD SOFTWARE WILL
// NOT HAVE THEIR ENUM VALUE OVER-MASKED; THE MASK IS ONLY
// HERE TO ATTEMPT TO REMOVE PROBLEMS FROM FILES MADE
// PRIOR TO ITS INTRODUCTION
GBF_MASK = 0x000000ff
};
class BMP_Names_ExtraData
{
public:
GlobalBMPFlags flags;
protected:
int reserved[12];
};
class BMP_Names_ExtraData_Chunk : public Chunk, public BMP_Names_ExtraData
{
public:
BMP_Names_ExtraData_Chunk (Chunk_With_Children * parent)
: Chunk (parent, "BMNAMEXT")
{
for (int i=0; i<12; ++i) reserved[i] = 0;
flags = GBF_NONE;
}
// constructor from buffer
BMP_Names_ExtraData_Chunk (Chunk_With_Children * parent, const char * sdata, size_t /*ssize*/)
: Chunk (parent, "BMNAMEXT")
{
flags = (GlobalBMPFlags)(*(int *)sdata & GBF_MASK);
sdata += 4;
for (int i=0; i<12; ++i, sdata+=4) reserved[i] = *(int *)sdata;
}
private:
virtual size_t size_chunk ();
virtual void fill_data_block (char * data_start);
friend class Environment_Data_Chunk;
friend class Shape_External_File_Chunk;
friend class Sprite_Header_Chunk;
};
class External_Shape_BMPs_Store_Chunk : public Chunk_With_BMPs, protected BMP_Names_ExtraData
{
public:
char * rifname; // to match one in RIF_Child_Chunk
char * shapename; // matches rif name of original shape
External_Shape_BMPs_Store_Chunk (Chunk_With_Children * parent, char const * rifn, char const * shapen);
External_Shape_BMPs_Store_Chunk (Chunk_With_Children * parent, const char * sdata, size_t ssize);
~External_Shape_BMPs_Store_Chunk();
virtual int get_version_num(void) { return version_num; }
virtual void set_version_num(int v) { version_num = v; }
virtual void inc_version_num(void) { ++version_num; }
virtual BMP_Names_ExtraData * GetExtendedData(void) { return this; }
private:
virtual Bitmap_MD5_Chunk * GetMD5Chunk(char const * bname);
virtual void CreateMD5Chunk(BMP_Name const & rcbmp, int const * md5id);
int version_num;
virtual size_t size_chunk()
{
return chunk_size = Chunk_With_BMPs::size_chunk() + ((rifname ? strlen(rifname) : 0) + (shapename ? strlen(shapename) : 0)+2 +3&~3) + 56;
}
virtual void fill_data_block(char * data_start);
friend class Environment_Game_Mode_Chunk;
};
// for dealing with matching images
enum IDscFlags
{
IDSCF_SPRITE = 0x00000001, // image is in a sprite
IDSCF_INCLUDED = 0x00000002, // image is from another rif file
IDSCF_FIXEDPALETTE = 0x00000004, // image has pgms for fixed palette
IDSCF_SUBSHAPE = 0x00000008, // image for shape included from another file
IDSCF_0 = 0,
// IMPORTANT
// since enums are not guaranteed to assume any particular
// storage class, code compiled on different compilers or
// with different settings may result in enums to be written
// to the data block as a char and read back in as an int,
// with the three most significant bytes containing junk.
// THIS MASK MUST BE KEPT UP TO DATE AS THE ENUM IS EXTENDED;
// ALSO ENSURE THAT NEW FILES LOADED INTO OLD SOFTWARE WILL
// NOT HAVE THEIR ENUM VALUE OVER-MASKED; THE MASK IS ONLY
// HERE TO ATTEMPT TO REMOVE PROBLEMS FROM FILES MADE
// PRIOR TO ITS INTRODUCTION
IDSCF_MASK = 0x000000ff
};
class ImageDescriptor
{
public:
// constructos;
ImageDescriptor();
ImageDescriptor(ImageDescriptor const &);
ImageDescriptor(IDscFlags, char const * fname, char const * rname = 0, char const * xname = 0);
~ImageDescriptor();
ImageDescriptor & operator = (ImageDescriptor const &);
// operators
BOOL operator == (ImageDescriptor const &) const;
inline BOOL operator != (ImageDescriptor const & id2) const
{ return ! operator == (id2); }
// members
IDscFlags flags;
char * filename; // name.bmp
char * rifname; // only if IDSCF_INCLUDED is set
char * fixrifname; // only if IDSCF_FIXEDPALETTE is set
private:
// I/O
ImageDescriptor(char const * datablock);
size_t Size() const;
void WriteData(char * datablock) const;
friend class MatchingImages;
int spares[3];
};
class MatchingImages
{
public:
// constructos;
MatchingImages() {}
MatchingImages(ImageDescriptor const & _load, ImageDescriptor const & _insteadof);
// operators
inline BOOL operator == (MatchingImages const & m2)
{ return load == m2.load && insteadof == m2.insteadof; }
inline BOOL operator != (MatchingImages const & m2)
{ return load != m2.load || insteadof != m2.insteadof; }
// members
ImageDescriptor load;
ImageDescriptor insteadof;
private:
// I/O
MatchingImages(char const * datablock);
size_t Size() const;
void WriteData(char * datablock) const;
friend class Matching_Images_Chunk;
int spares[3];
};
enum MICFlags
{
MICF_0 = 0,
MICF_FIXEDPALETTE = 0x00000001,
// IMPORTANT
// since enums are not guaranteed to assume any particular
// storage class, code compiled on different compilers or
// with different settings may result in enums to be written
// to the data block as a char and read back in as an int,
// with the three most significant bytes containing junk.
// THIS MASK MUST BE KEPT UP TO DATE AS THE ENUM IS EXTENDED;
// ALSO ENSURE THAT NEW FILES LOADED INTO OLD SOFTWARE WILL
// NOT HAVE THEIR ENUM VALUE OVER-MASKED; THE MASK IS ONLY
// HERE TO ATTEMPT TO REMOVE PROBLEMS FROM FILES MADE
// PRIOR TO ITS INTRODUCTION
MICF_MASK = 0x000000ff
};
class Matching_Images_Chunk : public Chunk
{
public:
// constructors
Matching_Images_Chunk(Chunk_With_Children * parent) : Chunk(parent,"MATCHIMG"), flags(MICF_0)
{ spares[0]=0; spares[1]=0; } // empty list
// I/O
Matching_Images_Chunk(Chunk_With_Children * parent, char const * datablock, size_t);
// members
List<MatchingImages> mlist;
MICFlags flags;
// methods
ImageDescriptor const & GetLoadImage(ImageDescriptor const &);
private:
int spares[2];
virtual size_t size_chunk();
virtual void fill_data_block(char * data_start);
friend class Environment_Data_Chunk;
friend class Environment_Game_Mode_Chunk;
};
enum BMPMD5_Flags
{
BMD5F_0 = 0,
BMD5F_SPRITE = 0x00000001,
// IMPORTANT
// since enums are not guaranteed to assume any particular
// storage class, code compiled on different compilers or
// with different settings may result in enums to be written
// to the data block as a char and read back in as an int,
// with the three most significant bytes containing junk.
// THIS MASK MUST BE KEPT UP TO DATE AS THE ENUM IS EXTENDED;
// ALSO ENSURE THAT NEW FILES LOADED INTO OLD SOFTWARE WILL
// NOT HAVE THEIR ENUM VALUE OVER-MASKED; THE MASK IS ONLY
// HERE TO ATTEMPT TO REMOVE PROBLEMS FROM FILES MADE
// PRIOR TO ITS INTRODUCTION
BMD5F_MASK = 0x000000ff
};
class Bitmap_MD5_Chunk : public Chunk
{
public :
Bitmap_MD5_Chunk(Chunk_With_Children * parent, char const * datablock, size_t);
private:
Bitmap_MD5_Chunk(Chunk_With_Children * parent, int const * md5id, BMP_Name const & rcbmp, char const * rname = 0, char const * sname = 0);
~Bitmap_MD5_Chunk();
int md5_val[4];
char * bmpname;
char * rifname;
char * shapename;
BMPMD5_Flags flags;
int version_num;
int spare;
virtual size_t size_chunk();
virtual void fill_data_block(char * data_start);
// your parents are your friends
friend class Environment_Data_Chunk;
friend class Environment_Game_Mode_Chunk;
friend class Shape_External_File_Chunk;
friend class Sprite_Header_Chunk;
// some of your siblings are friends as well
friend class Chunk_With_BMPs;
friend class Global_BMP_Name_Chunk;
friend class Bitmap_List_Store_Chunk;
friend class External_Shape_BMPs_Store_Chunk;
friend class RIF_Child_Chunk;
};
#endif

602
src/win95/cd_player.c Normal file
View file

@ -0,0 +1,602 @@
#include "3dc.h"
#include "inline.h"
#include "psndplat.h"
#include "cd_player.h"
#define UseLocalAssert Yes
#include "ourasert.h"
/* KJL 12:40:35 07/05/98 - This is code derived from Patrick's original stuff &
moved into it's own file. */
/* Patrick 10/6/97 -------------------------------------------------------------
CDDA Support
----------------------------------------------------------------------------*/
#define NO_DEVICE -1
int cdDeviceID = NO_DEVICE;
int cdAuxDeviceID = NO_DEVICE;
/* Patrick 9/6/97 -------------------------------------------------------------
----------------------------------------------------------------------------
CDDA Support
-----------------------------------------------------------------------------
-----------------------------------------------------------------------------*/
static int CDDASwitchedOn = 0;
static int CDDAIsInitialised = 0;
static int CDDAVolume = CDDA_VOLUME_DEFAULT;
CDOPERATIONSTATES CDDAState;
static DWORD PreGameCDVolume;//windows cd volume before the game started
static CDTRACKID TrackBeingPlayed;
static enum CDCOMMANDID LastCommandGiven;
extern HWND hWndMain;
int CDPlayerVolume; // volume control from menus
int CDTrackMax=-1; //highest track number on cd
void CDDA_Start(void)
{
CDDAVolume = CDDA_VOLUME_DEFAULT;
CDPlayerVolume = CDDAVolume;
CDDAState = CDOp_Idle;
CDDAIsInitialised = 0;
if(PlatStartCDDA()!=SOUND_PLATFORMERROR)
{
CDDAIsInitialised = 1;
CDDA_SwitchOn();
CDDA_ChangeVolume(CDDAVolume); /* init the volume */
CDDA_CheckNumberOfTracks();
}
LastCommandGiven = CDCOMMANDID_Start;
}
void CDDA_End(void)
{
if(!CDDAIsInitialised) return;
CDDA_Stop();
PlatChangeCDDAVolume(CDDA_VOLUME_RESTOREPREGAMEVALUE);
PlatEndCDDA();
CDDA_SwitchOff();
CDDAIsInitialised = 0;
LastCommandGiven = CDCOMMANDID_End;
}
void CDDA_Management(void)
{
if(!CDDASwitchedOn) return; /* CDDA is off */
if(CDDAState==CDOp_Playing) return; /* already playing */
PlatCDDAManagement();
}
void CDDA_Play(int CDDATrack)
{
int ok;
if(!CDDASwitchedOn) return; /* CDDA is off */
if(CDDAState==CDOp_Playing) return; /* already playing */
if((CDDATrack<=0)||(CDDATrack>=CDTrackMax)) return; /* no such track */
ok = PlatPlayCDDA((int)CDDATrack);
if(ok!=SOUND_PLATFORMERROR)
{
CDDAState=CDOp_Playing;
LastCommandGiven = CDCOMMANDID_Play;
TrackBeingPlayed = CDDATrack;
}
}
void CDDA_PlayLoop(int CDDATrack)
{
int ok;
if(!CDDASwitchedOn) return; /* CDDA is off */
if(CDDAState==CDOp_Playing) return; /* already playing */
if((CDDATrack<=0)||(CDDATrack>=CDTrackMax)) return; /* no such track */
ok = PlatPlayCDDA((int)CDDATrack);
if(ok!=SOUND_PLATFORMERROR)
{
CDDAState=CDOp_Playing;
LastCommandGiven = CDCOMMANDID_PlayLoop;
TrackBeingPlayed = CDDATrack;
}
}
extern void CheckCDVolume(void)
{
if (CDDAVolume != CDPlayerVolume)
{
CDDA_ChangeVolume(CDPlayerVolume);
}
}
void CDDA_ChangeVolume(int volume)
{
if(!CDDASwitchedOn) return; /* CDDA is off */
if(volume<CDDA_VOLUME_MIN) return;
if(volume>CDDA_VOLUME_MAX) return;
if(CDDA_IsOn())
{
if(PlatChangeCDDAVolume(volume))
{
CDDAVolume=volume;
CDPlayerVolume = volume;
LastCommandGiven = CDCOMMANDID_ChangeVolume;
}
}
}
int CDDA_GetCurrentVolumeSetting(void)
{
return CDDAVolume;
}
void CDDA_Stop()
{
int ok;
if(!CDDASwitchedOn) return; /* CDDA is off */
if(CDDAState!=CDOp_Playing) return; /* nothing playing */
ok = PlatStopCDDA();
CDDAState=CDOp_Idle;
LastCommandGiven = CDCOMMANDID_Stop;
}
void CDDA_SwitchOn()
{
LOCALASSERT(!CDDA_IsPlaying());
if(CDDAIsInitialised) CDDASwitchedOn = 1;
}
void CDDA_SwitchOff()
{
if(!CDDASwitchedOn) return; /* CDDA is off already */
if(CDDA_IsPlaying()) CDDA_Stop();
CDDASwitchedOn = 0;
}
int CDDA_IsOn()
{
return CDDASwitchedOn;
}
int CDDA_IsPlaying()
{
if(CDDAState==CDOp_Playing)
{
LOCALASSERT(CDDASwitchedOn);
return 1;
}
return 0;
}
int CDDA_CheckNumberOfTracks()
{
int numTracks=0;
if(CDDA_IsOn())
{
PlatGetNumberOfCDTracks(&numTracks);
//if there is only one track , then it probably can't be used anyway
if(numTracks==1) numTracks=0;
//store the maximum allowed track number
CDTrackMax=numTracks;
}
return numTracks;
}
/* win95 specific */
int PlatStartCDDA(void)
{
static void PlatGetCDDAVolumeControl(void);
DWORD dwReturn;
MCI_OPEN_PARMS mciOpenParms;
/* Initialise device handles */
cdDeviceID = NO_DEVICE;
cdAuxDeviceID = NO_DEVICE;
/* try to open mci cd-audio device */
mciOpenParms.lpstrDeviceType = (LPCSTR) MCI_DEVTYPE_CD_AUDIO;
dwReturn = mciSendCommand(NULL,MCI_OPEN,MCI_OPEN_TYPE|MCI_OPEN_TYPE_ID,(DWORD)(LPVOID)&mciOpenParms);
if(dwReturn)
{
/* error */
cdDeviceID = NO_DEVICE;
return SOUND_PLATFORMERROR;
}
cdDeviceID = mciOpenParms.wDeviceID;
/* now try to get the cd volume control, by obtaining the auxiliary device id for
the cd-audio player*/
PlatGetCDDAVolumeControl();
return 0;
}
/* this is a support function for PlatStartCDDA() */
#if 0
static void PlatGetCDDAVolumeControl(void)
{
MMRESULT mmres;
unsigned int numAuxDevs,i;
numAuxDevs = auxGetNumDevs();
/* search the auxilary device list for the cd player */
for(i=0;i<numAuxDevs;i++)
{
AUXCAPS devCaps;
mmres = auxGetDevCaps(i,&devCaps,sizeof(AUXCAPS));
if(mmres==MMSYSERR_NOERROR)
{
if((devCaps.wTechnology&AUXCAPS_CDAUDIO)&&(devCaps.dwSupport&AUXCAPS_VOLUME))
{
cdAuxDeviceID = i;
}
}
}
}
#else
static void PlatGetCDDAVolumeControl(void)
{
int i;
int numDev = mixerGetNumDevs();
//go through the mixer devices searching for one that can deal with the cd volume
for(i=0;i<numDev;i++)
{
HMIXER handle;
if(mixerOpen(&handle,i,0,0,MIXER_OBJECTF_MIXER ) == MMSYSERR_NOERROR )
{
//try to get the compact disc mixer line
MIXERLINE line;
line.cbStruct=sizeof(MIXERLINE);
line.dwComponentType=MIXERLINE_COMPONENTTYPE_SRC_COMPACTDISC;
if(mixerGetLineInfo(handle,&line,MIXER_GETLINEINFOF_COMPONENTTYPE) == MMSYSERR_NOERROR)
{
MIXERLINECONTROLS lineControls;
MIXERCONTROL control;
lineControls.cbStruct=sizeof(MIXERLINECONTROLS);
lineControls.dwLineID=line.dwLineID;
lineControls.pamxctrl=&control;
lineControls.dwControlType=MIXERCONTROL_CONTROLTYPE_VOLUME ;
lineControls.cControls=1;
lineControls.cbmxctrl=sizeof(MIXERCONTROL);
control.cbStruct=sizeof(MIXERCONTROL);
//try to get the volume control
if(mixerGetLineControls(handle,&lineControls,MIXER_GETLINECONTROLSF_ONEBYTYPE)==MMSYSERR_NOERROR)
{
MIXERCONTROLDETAILS details;
MIXERCONTROLDETAILS_UNSIGNED detailValue;
details.cbStruct=sizeof(MIXERCONTROLDETAILS);
details.dwControlID=control.dwControlID;
details.cChannels=1;
details.cMultipleItems=0;
details.cbDetails=sizeof(MIXERCONTROLDETAILS_UNSIGNED);
details.paDetails=&detailValue;
//get the current volume so that we can restore it later
if(mixerGetControlDetails(handle,&details,MIXER_GETCONTROLDETAILSF_VALUE)==MMSYSERR_NOERROR)
{
PreGameCDVolume = detailValue.dwValue;
mixerClose(handle);
return; //success
}
}
}
mixerClose(handle);
}
}
return;
}
#endif
void PlatEndCDDA(void)
{
DWORD dwReturn;
/* check the cdDeviceId */
if(cdDeviceID==NO_DEVICE) return;
dwReturn = mciSendCommand((UINT)cdDeviceID,MCI_CLOSE,MCI_WAIT,NULL);
cdDeviceID=NO_DEVICE;
/* reset the auxilary device handle */
cdAuxDeviceID = NO_DEVICE;
}
int PlatPlayCDDA(int track)
{
DWORD dwReturn;
MCI_SET_PARMS mciSetParms = {0,0,0};
MCI_PLAY_PARMS mciPlayParms = {0,0,0};
MCI_STATUS_PARMS mciStatusParms = {0,0,0,0};
/* check the cdDeviceId */
if(cdDeviceID==NO_DEVICE) return SOUND_PLATFORMERROR;
/* set the time format */
mciSetParms.dwTimeFormat = MCI_FORMAT_MSF;
dwReturn = mciSendCommand((UINT)cdDeviceID,MCI_SET,MCI_SET_TIME_FORMAT,(DWORD)(LPVOID) &mciSetParms);
if(dwReturn)
{
// NewOnScreenMessage("CD ERROR - TIME FORMAT");
/* error */
return SOUND_PLATFORMERROR;
}
/* find the length of the track... */
mciStatusParms.dwItem = MCI_STATUS_LENGTH;
mciStatusParms.dwTrack = track;
dwReturn = mciSendCommand((UINT)cdDeviceID,MCI_STATUS,MCI_STATUS_ITEM|MCI_TRACK,(DWORD)(LPVOID)&mciStatusParms);
if(dwReturn)
{
/* error */
// NewOnScreenMessage("CD ERROR - GET LENGTH");
return SOUND_PLATFORMERROR;
}
/* set the time format */
mciSetParms.dwTimeFormat = MCI_FORMAT_TMSF;
dwReturn = mciSendCommand((UINT)cdDeviceID,MCI_SET,MCI_SET_TIME_FORMAT,(DWORD)(LPVOID) &mciSetParms);
if(dwReturn)
{
/* error */
// NewOnScreenMessage("CD ERROR - TIME FORMAT");
return SOUND_PLATFORMERROR;
}
/* play the track: set up for notification when track finishes, or an error occurs */
mciPlayParms.dwFrom=MCI_MAKE_TMSF(track,0,0,0);
mciPlayParms.dwTo=MCI_MAKE_TMSF(track, MCI_MSF_MINUTE(mciStatusParms.dwReturn),
MCI_MSF_SECOND(mciStatusParms.dwReturn),
MCI_MSF_FRAME(mciStatusParms.dwReturn));
mciPlayParms.dwCallback=(DWORD)hWndMain;
dwReturn = mciSendCommand((UINT)cdDeviceID,MCI_PLAY,MCI_FROM|MCI_TO|MCI_NOTIFY,(DWORD)(LPVOID)&mciPlayParms);
if(dwReturn)
{
/* error */
// NewOnScreenMessage("CD ERROR - PLAY");
return SOUND_PLATFORMERROR;
}
return 0;
}
int PlatGetNumberOfCDTracks(int* numTracks)
{
DWORD dwReturn;
MCI_STATUS_PARMS mciStatusParms = {0,0,0,0};
/* check the cdDeviceId */
if(cdDeviceID==NO_DEVICE) return SOUND_PLATFORMERROR;
if(!numTracks) return SOUND_PLATFORMERROR;
/* find the number tracks... */
mciStatusParms.dwItem = MCI_STATUS_NUMBER_OF_TRACKS ;
dwReturn = mciSendCommand((UINT)cdDeviceID,MCI_STATUS,MCI_STATUS_ITEM ,(DWORD)(LPVOID)&mciStatusParms);
if(dwReturn)
{
/* error */
return SOUND_PLATFORMERROR;
}
//number of tracks is in the dwReturn member
*numTracks=mciStatusParms.dwReturn;
return 0;
}
int PlatStopCDDA(void)
{
DWORD dwReturn;
/* check the cdDeviceId */
if(cdDeviceID==NO_DEVICE)
{
return SOUND_PLATFORMERROR;
}
/* stop the cd player */
dwReturn = mciSendCommand((UINT)cdDeviceID,MCI_STOP,MCI_WAIT,NULL);
if(dwReturn)
{
/* error */
return SOUND_PLATFORMERROR;
}
return 0;
}
#if 0
int PlatChangeCDDAVolume(int volume)
{
MMRESULT mmres;
unsigned int newVolume;
/* check the cdDeviceId */
if(cdDeviceID==NO_DEVICE) return SOUND_PLATFORMERROR;
/* check the mixer device id */
if(cdAuxDeviceID==NO_DEVICE) return SOUND_PLATFORMERROR;
/* scale and set the new volume */
{
int channelVolume;
channelVolume = VOLUME_CDDA_MINPLAT + WideMulNarrowDiv(volume,
(VOLUME_CDDA_MAXPLAT-VOLUME_CDDA_MINPLAT), (CDDA_VOLUME_MAX-CDDA_VOLUME_MIN));
if(channelVolume < VOLUME_CDDA_MINPLAT) channelVolume = VOLUME_CDDA_MINPLAT;
if(channelVolume > VOLUME_CDDA_MAXPLAT) channelVolume = VOLUME_CDDA_MAXPLAT;
/* set left and right channels (if there is only one channel,
should still work ok)*/
newVolume = channelVolume|(channelVolume<<16);
}
PlatGetCDDAVolumeControl();
mmres = auxSetVolume((UINT)cdAuxDeviceID,(DWORD)newVolume);
if(mmres==MMSYSERR_NOERROR) return 1;
else return SOUND_PLATFORMERROR;
}
#else
int PlatChangeCDDAVolume(int volume)
{
MMRESULT mmres;
unsigned int newVolume;
int i;
int numDev = mixerGetNumDevs();
/* check the cdDeviceId */
if(cdDeviceID==NO_DEVICE) return SOUND_PLATFORMERROR;
//go through the mixer devices searching for one that can deal with the cd volume
for(i=0;i<numDev;i++)
{
HMIXER handle;
if(mixerOpen(&handle,i,0,0,MIXER_OBJECTF_MIXER ) == MMSYSERR_NOERROR )
{
//try to get the compact disc mixer line
MIXERLINE line;
line.cbStruct=sizeof(MIXERLINE);
line.dwComponentType=MIXERLINE_COMPONENTTYPE_SRC_COMPACTDISC;
if(mixerGetLineInfo(handle,&line,MIXER_GETLINEINFOF_COMPONENTTYPE) == MMSYSERR_NOERROR)
{
MIXERLINECONTROLS lineControls;
MIXERCONTROL control;
lineControls.cbStruct=sizeof(MIXERLINECONTROLS);
lineControls.dwLineID=line.dwLineID;
lineControls.pamxctrl=&control;
lineControls.dwControlType=MIXERCONTROL_CONTROLTYPE_VOLUME ;
lineControls.cControls=1;
lineControls.cbmxctrl=sizeof(MIXERCONTROL);
control.cbStruct=sizeof(MIXERCONTROL);
//try to get the volume control
if(mixerGetLineControls(handle,&lineControls,MIXER_GETLINECONTROLSF_ONEBYTYPE)==MMSYSERR_NOERROR)
{
MIXERCONTROLDETAILS details;
MIXERCONTROLDETAILS_UNSIGNED detailValue;
details.cbStruct=sizeof(MIXERCONTROLDETAILS);
details.dwControlID=control.dwControlID;
details.cChannels=1;
details.cMultipleItems=0;
details.cbDetails=sizeof(MIXERCONTROLDETAILS_UNSIGNED);
details.paDetails=&detailValue;
if(volume==CDDA_VOLUME_RESTOREPREGAMEVALUE)
{
//set the volume to what it was before the game started
newVolume=PreGameCDVolume;
}
else
{
//scale the volume
newVolume = control.Bounds.dwMinimum + WideMulNarrowDiv(volume,
(control.Bounds.dwMaximum-control.Bounds.dwMinimum), (CDDA_VOLUME_MAX-CDDA_VOLUME_MIN));
if(newVolume<control.Bounds.dwMinimum) newVolume=control.Bounds.dwMinimum;
if(newVolume>control.Bounds.dwMaximum) newVolume=control.Bounds.dwMaximum;
}
//fill in the volume in the control details structure
detailValue.dwValue=newVolume;
mmres = mixerSetControlDetails(handle,&details,MIXER_SETCONTROLDETAILSF_VALUE);
mixerClose(handle);
if(mmres==MMSYSERR_NOERROR) return 1;
else return SOUND_PLATFORMERROR;
}
}
mixerClose(handle);
}
}
return SOUND_PLATFORMERROR;
}
#endif
void PlatCDDAManagement(void)
{
/* does nothing for Win95: use call back instead */
}
void PlatCDDAManagementCallBack(WPARAM flags, LONG deviceId)
{
extern CDOPERATIONSTATES CDDAState;
/* check the cdDeviceId */
if(cdDeviceID==NO_DEVICE) return;
/* compare with the passed device id */
if((UINT)deviceId!=(UINT)cdDeviceID) return;
if(flags&MCI_NOTIFY_SUCCESSFUL)
{
CDDAState = CDOp_Idle;
//NewOnScreenMessage("CD COMMAND RETURNED WITH SUCCESSFUL");
/* Play it again, sam */
if (LastCommandGiven == CDCOMMANDID_PlayLoop)
{
CDDA_PlayLoop(TrackBeingPlayed);
}
}
else if(flags&MCI_NOTIFY_FAILURE)
{
/* error while playing: abnormal termination */
//NewOnScreenMessage("CD COMMAND FAILED");
CDDAState = CDOp_Idle;
}
else if(flags&MCI_NOTIFY_SUPERSEDED)
{
//NewOnScreenMessage("CD COMMAND SUPERSEDED");
}
else if(flags&MCI_NOTIFY_ABORTED)
{
/* aborted or superceeded: try and stop the device */
//NewOnScreenMessage("CD COMMAND ABORTED(?)");
// CDDA_Stop();
}
else
{
//NewOnScreenMessage("CD COMMAND RETURNED WITH UNKNOWN MESSAGE");
}
}

110
src/win95/cd_player.h Normal file
View file

@ -0,0 +1,110 @@
/* KJL 12:40:35 07/05/98 - This is code derived from Patrick's original stuff &
moved into it's own file. */
/* Patrick 10/6/97 --------------------------------------------------------------
SUPPORT FOR CDDA SYSTEM
-----------------------------------------------------------------------------*/
/* Patrick 10/6/97 --------------------------------------------------------------
Some Volume defines
-----------------------------------------------------------------------------*/
#define CDDA_VOLUME_MAX (127)
#define CDDA_VOLUME_MIN (0)
#define CDDA_VOLUME_DEFAULT (127)
#define CDDA_VOLUME_RESTOREPREGAMEVALUE (-100)
/* Patrick 10/6/97 --------------------------------------------------------------
Enumeration of CD player states
-----------------------------------------------------------------------------*/
typedef enum cdoperationstates
{
CDOp_Idle,
CDOp_Playing,
}
CDOPERATIONSTATES;
/* Patrick 10/6/97 --------------------------------------------------------------
CDDA_Start/End are used to initialise and de-initialise the CDDA system.
No CDDA operations have any effect until the system has been initialised.
-----------------------------------------------------------------------------*/
extern void CDDA_Start(void);
extern void CDDA_End(void);
/* Patrick 10/6/97 --------------------------------------------------------------
This is provided to allow platform specific polling/management of the CD device
whilst playing. It should be called during the main game loop.
-----------------------------------------------------------------------------*/
extern void CDDA_Management(void);
/* Patrick 10/6/97 --------------------------------------------------------------
Play , change volume, and stop are the basic CDDA operations provided. An
enumeration of tracks should be provided in the platform header.
-----------------------------------------------------------------------------*/
extern void CDDA_Play(int CDDATrack);
extern void CDDA_PlayLoop(int CDDATrack);
extern void CDDA_ChangeVolume(int volume);
extern void CDDA_Stop(void);
extern int CDDA_CheckNumberOfTracks(void);
/* Patrick 23/6/97 --------------------------------------------------------------
Returns the current CDDA volume setting. NB if the cd player has not been
initialised the volume setting can still be obtained by calling this function,
though it may not be changed using CDDA_ChangeVolume().
-----------------------------------------------------------------------------*/
extern int CDDA_GetCurrentVolumeSetting(void);
/* Patrick 10/6/97 --------------------------------------------------------------
Switch on and switch off may be used to stop and start the CDDA system after
initialisation. They are provided to allow the user to stop and start CDDA
during a game.
-----------------------------------------------------------------------------*/
extern void CDDA_SwitchOn(void);
extern void CDDA_SwitchOff(void);
/* Patrick 10/6/97 --------------------------------------------------------------
These are provided to interrogate the state of the CDDA system.
-----------------------------------------------------------------------------*/
extern int CDDA_IsOn(void);
extern int CDDA_IsPlaying(void);
enum CDCOMMANDID
{
CDCOMMANDID_Start,
CDCOMMANDID_End,
CDCOMMANDID_Play,
CDCOMMANDID_PlayLoop,
CDCOMMANDID_ChangeVolume,
CDCOMMANDID_Stop,
};
/* CDDA SUPPORT */
#define VOLUME_CDDA_MAXPLAT (65535)
#define VOLUME_CDDA_MINPLAT (0)
/* Patrick 10/6/97 -------------------------------------------------------------
Start and end functions provide any platform specific initialisation for
the CD player. The start function returns SOUND_PLATFORM error if unsucessful,
or zero otherwise.
----------------------------------------------------------------------------*/
extern int PlatStartCDDA(void);
extern void PlatEndCDDA(void);
/* Patrick 10/6/97 -------------------------------------------------------------
Platform specific play, stop, and change volume functions. NB the volume
is scaled to the platform limits defined above.
These functions return SOUND_PLATFORM error if unsucessful, or 0 otherwise.
----------------------------------------------------------------------------*/
extern int PlatPlayCDDA(int track);
extern int PlatStopCDDA(void);
extern int PlatChangeCDDAVolume(int volume);
int PlatGetNumberOfCDTracks(int* numTracks);
/* Patrick 10/6/97 -------------------------------------------------------------
Management functions are provided for platform specific detection of changes
in the cd player state (ie finishing a track, or an error). The basic
management function is provided for consoles, who need to poll the device,
whilst the call back is provided for intercepting WIN95 MCI call backs.
----------------------------------------------------------------------------*/
extern void PlatCDDAManagement(void);
extern void PlatCDDAManagementCallBack(WPARAM flags, LONG deviceId);
extern int CDPlayerVolume;

699
src/win95/chnkimag.cpp Normal file
View file

@ -0,0 +1,699 @@
#include <string.h>
#define TRY_OLD_DIRS 0 // obsolete
#define ALLOW_LOAD_ORIGINAL 0
#if TRY_OLD_DIRS // temporary until all textures go into subshps directory
#include "ffstdio.h"
#endif
#include "chnkimag.hpp"
#include "list_tem.hpp"
#include "envchunk.hpp"
#include "chunkpal.hpp"
#include "bmpnames.hpp"
#include "chnkload.hpp"
char const * CL_RIFFImage::game_mode = 0;
// useful filename handling functions
// returns pointer into string pointing to filename without dirname
template <class C> // C can be char or char const
static C * strip_path(C * n)
{
C * rm = strrchr(n,':');
if (rm) n = rm+1;
rm = strrchr(n,'/');
if (rm) n = rm+1;
rm = strrchr(n,'\\');
if (rm) n = rm+1;
return n;
}
// removes any .extension from filename by inserting null character
static void strip_file_extension(char * n)
{
char * dotpos = strrchr(n,'.');
if (dotpos) *dotpos = 0;
}
static char * strip_file_extension(char const * n)
{
char * nn = new char[strlen(n)+1];
strcpy(nn,n);
strip_file_extension(nn);
return nn;
}
////////////////////////
//
// riff file interface
//
////////////////////////
// get the directory associated with the riff - free with delete[]
static char * riff_basename(Chunk_With_Children * envd)
{
RIF_Name_Chunk * rnc = 0;
List<Chunk *> chlst = envd->lookup_child("RIFFNAME");
if (chlst.size())
{
rnc = (RIF_Name_Chunk *)chlst.first_entry();
const char * rif_name = strip_path(rnc->rif_name);
char * basename = new char[strlen(rif_name)+1];
strcpy(basename,rif_name);
strip_file_extension(basename);
return basename;
}
const char * deflt = "empty";
char * basename = new char [strlen(deflt)+1];
strcpy(basename,deflt);
return basename;
}
#if OUTPUT_LOG
#define _LOGID CL_LogFile.lprintf("%s:%d :: ",__FILE__,__LINE__)
#define _LOGPUT(s) _LOGID,CL_LogFile.lputs(s)
#define _LOGPRINT(args) _LOGID,CL_LogFile.lprintf args
#else
#define _LOGPUT(s) (void)0
#define _LOGPRINT(args) (void)0
#endif
void CL_RIFFImage::GetPath(ImageDescriptor const & idsc, Environment_Data_Chunk * envd, BMPN_Flags bflags)
{
if (fname) delete[] fname;
fname = 0;
// set the name
if (name) delete[] name;
char * nptr = strip_path(idsc.filename);
name = new char[strlen(nptr)+1];
strcpy(name,nptr);
#if 0
char orig_ext[32];
char const * oeP = strrchr(name,'.');
if (!oeP) eoP = "";
strcpy(orig_ext,oeP);
#endif
strip_file_extension(name);
// load this image
char const * pg0ext = ".PG0";
switch (imode)
{
case CLM_16BIT:
case CLM_24BIT:
case CLM_32BIT:
#if ALLOW_LOAD_ORIGINAL
{
char const * dir2 = idsc.flags & IDSCF_SPRITE ? "Sprites\\" : "";
char * riffname = riff_basename(envd);
char const * dir3 = idsc.flags & IDSCF_INCLUDED ? idsc.rifname : riffname;
fname = new char[strlen(ToolsTex_Directory)+strlen(dir2)+strlen(dir3)+1+strlen(name)+5];
strcpy(fname,ToolsTex_Directory);
strcat(fname,dir2);
strcat(fname,dir3);
strcat(fname,"\\");
strcat(fname,name);
strcat(fname,".PP0");
delete[] riffname;
break;
}
#endif
case CLM_ATTACHEDPALETTE:
{
char const * dir2 = idsc.flags & IDSCF_SPRITE ? "Sprites\\" : idsc.flags & IDSCF_SUBSHAPE ? "SubShps\\All\\" : "";
char * riffname = riff_basename(envd);
char const * dir3 = idsc.flags & IDSCF_INCLUDED ? idsc.rifname : riffname;
fname = new char[strlen(GenTex_Directory)+strlen(dir2)+strlen(dir3)+1+strlen(name)+5];
strcpy(fname,GenTex_Directory);
strcat(fname,dir2);
strcat(fname,dir3);
strcat(fname,"\\");
strcat(fname,name);
strcat(fname,".BM0");
delete[] riffname;
#if TRY_OLD_DIRS // temporary until all textures go into subshps directory
FFILE * ftest = ffopen(fname,"rb");
if (ftest) ffclose(ftest);
else
{
_LOGPUT("WARNING! Not found in SubShps directory\n");
char const * dir2 = idsc.flags & IDSCF_SPRITE ? "Sprites\\" : "";
char * riffname = riff_basename(envd);
char const * dir3 = idsc.flags & IDSCF_INCLUDED ? idsc.rifname : riffname;
delete[] fname;
fname = new char[strlen(GenTex_Directory)+strlen(dir2)+strlen(dir3)+1+strlen(name)+5];
strcpy(fname,GenTex_Directory);
strcat(fname,dir2);
strcat(fname,dir3);
strcat(fname,"\\");
strcat(fname,name);
strcat(fname,".BM0");
delete[] riffname;
}
#endif
break;
}
case CLM_TLTPALETTE:
if (!(bflags & ChunkBMPFlag_NotLit))
{
pg0ext = ".PW0";
flags.tltpalette = 1;
}
case CLM_GLOBALPALETTE:
{
if (idsc.flags & IDSCF_FIXEDPALETTE)
{
char const * dir2 = idsc.fixrifname ? *idsc.fixrifname ? idsc.fixrifname : 0 : 0;
char const * dir3 = idsc.flags & IDSCF_SPRITE ? "Sprites\\" : "";
char * riffname = riff_basename(envd);
char const * dir4 = idsc.flags & IDSCF_INCLUDED ? idsc.rifname : riffname;
fname = new char[strlen(FixTex_Directory)+(dir2 ? strlen(dir2)+1 : 0)+strlen(dir3)+strlen(dir4)+1+strlen(name)+5];
strcpy(fname,FixTex_Directory);
if (dir2)
{
strcat(fname,dir2);
strcat(fname,"\\");
}
strcat(fname,dir3);
strcat(fname,dir4);
strcat(fname,"\\");
strcat(fname,name);
strcat(fname,pg0ext);
delete[] riffname;
}
else
{
char const * dir1 = game_mode ? GameTex_Directory : ToolsTex_Directory;
char * dir2 = riff_basename(envd);
char const * dir4 = idsc.flags & IDSCF_SPRITE ? "Sprites\\" : "";
char const * dir5 = idsc.flags & IDSCF_INCLUDED ? idsc.rifname : 0;
fname = new char[strlen(dir1)+strlen(dir2)+1+(game_mode ? strlen(game_mode)+1 : 0)+strlen(dir4)+(dir5 ? strlen(dir5)+1 : 0)+strlen(name)+5];
strcpy(fname,dir1);
strcat(fname,dir2);
strcat(fname,"\\");
if (game_mode)
{
strcat(fname,game_mode);
strcat(fname,"\\");
}
strcat(fname,dir4);
if (dir5)
{
strcat(fname,dir5);
strcat(fname,"\\");
}
strcat(fname,name);
strcat(fname,pg0ext);
delete[] dir2;
}
break;
}
}
if (!fname)
{
_LOGPUT("WARNING! GetPath returning NULL pointer\n");
}
else
_LOGPRINT(("file expected to be %s\n",fname));
}
CL_Error CL_RIFFImage::Locate(char const * iname, int const enum_id)
{
_LOGPRINT(("RIF File image finder called for %s, id %d\n",iname,enum_id));
if (!Env_Chunk)
_LOGPUT("WARNING! no .RIF file loaded\n");
if (!Env_Chunk) return CLE_RIFFERROR;
switch (imode)
{
case CLM_ATTACHEDPALETTE:
case CLM_16BIT:
case CLM_24BIT:
case CLM_32BIT:
case CLM_GLOBALPALETTE:
case CLM_TLTPALETTE:
break;
default:
_LOGPUT("WARNING! undefined video mode\n");
return CLE_INVALIDDXMODE;
}
// remove projectsubdirectory from start of image name if it is there
unsigned int const psdirlen = strlen(projectsubdirectory);
if (!strncmp(projectsubdirectory,iname,psdirlen))
iname += psdirlen;
List<Chunk *> envdl (Env_Chunk->lookup_child("REBENVDT"));
if (!envdl.size())
{
_LOGPUT("WARNING! no environment data chunk\n");
return CLE_RIFFERROR;
}
Environment_Data_Chunk * envd = (Environment_Data_Chunk *) envdl.first_entry();
CL_Error retval = CLE_OK;
Environment_Game_Mode_Chunk * egmc = 0;
if (game_mode)
{
if (*game_mode)
{
List<Chunk *> egmcl (envd->lookup_child("GAMEMODE"));
for (LIF<Chunk *> egmci(&egmcl); !egmci.done(); egmci.next())
{
Environment_Game_Mode_Chunk * egmcm = (Environment_Game_Mode_Chunk *) egmci();
if (egmcm->id_equals(game_mode))
{
egmc = egmcm;
break;
}
}
if (!egmc) retval = CLE_INVALIDGAMEMODE;
// only returns this error if the game mode cannot be found *and* the image is not listed
}
}
if (name)
{
delete[] name;
name = 0;
}
if (iname) name = strip_file_extension(strip_path(iname));
char * rcname = 0;
if (iname)
{
if (strchr(iname,'\\'))
{
rcname = new char[strlen(iname)+1];
strcpy(rcname,iname);
*strchr(rcname,'\\')=0;
}
else if (strchr(iname,'/'))
{
rcname = new char[strlen(iname)+1];
strcpy(rcname,iname);
*strchr(rcname,'/')=0;
}
}
if (egmc)
{
int shapefoundingm = rcname ? 0 : 1;
// Get the matching image 'Processor' chunk
List<Chunk *> micl = egmc->lookup_child("MATCHIMG");
Matching_Images_Chunk * mic = 0;
if (micl.size()) mic = (Matching_Images_Chunk *)micl.first_entry();
List<Chunk *> rcl = egmc->lookup_child("RIFCHILD");
for (LIF<Chunk *> rci(&rcl); !rci.done(); rci.next())
{
RIF_Child_Chunk * rcm = (RIF_Child_Chunk *) rci();
if (rcname)
{
if (_stricmp(rcname,rcm->rifname) && (*rcname || *rcm->filename))
continue;
shapefoundingm = 1;
}
for (LIF<BMP_Flags> bmpfi(&rcm->bmps); !bmpfi.done(); bmpfi.next())
{
BMP_Flags bmpft(bmpfi());
strip_file_extension(bmpft.filename);
if (iname ? !_stricmp(name,strip_path(bmpft.filename)) : enum_id == bmpft.enum_id)
{
// select image descriptor
ImageDescriptor const idsc
(
*rcm->filename ?
(IDscFlags)((bmpft.flags & ChunkBMPFlag_FixedPalette ?
IDSCF_FIXEDPALETTE
:
IDSCF_0)
|IDSCF_INCLUDED)
:
IDSCF_0,
bmpfi().filename,
*rcm->filename ? rcm->rifname : 0
);
ImageDescriptor const * p_idsc = &idsc;
if (mic) p_idsc = &mic->GetLoadImage(idsc);
else _LOGPRINT(("WARNING! no rule to find matching images in game mode %s\n",egmc->header->mode_identifier));
// load this image
GetPath(*p_idsc,envd,bmpft.flags);
if (fname)
{
if (rcname)
{
delete[] rcname;
rcname = 0;
}
flags.located = 1;
return CLE_OK;
}
}
}
}
List<Chunk *> ssc = egmc->lookup_child("SHBMPNAM");
for (LIF<Chunk *> ssi(&ssc); !ssi.done(); ssi.next())
{
External_Shape_BMPs_Store_Chunk * ss = (External_Shape_BMPs_Store_Chunk *) ssi();
if (rcname)
if (_stricmp(rcname,ss->shapename) && *rcname)
continue;
for (LIF<BMP_Name> bmpfi(&ss->bmps); !bmpfi.done(); bmpfi.next())
{
BMP_Name bmpft(bmpfi());
strip_file_extension(bmpft.filename);
if (iname ? !_stricmp(name,strip_path(bmpft.filename)) : enum_id == bmpft.enum_id)
{
// select image descriptor
ImageDescriptor const idsc
(
(IDscFlags)((bmpft.flags & ChunkBMPFlag_FixedPalette ?
IDSCF_FIXEDPALETTE
:
IDSCF_0)
|(ss->GetExtendedData()->flags & GBF_SPRITE ?
IDSCF_SPRITE
:
IDSCF_SUBSHAPE)
|IDSCF_INCLUDED),
bmpfi().filename,
ss->shapename,
bmpft.flags & ChunkBMPFlag_FixedPalette ? ss->rifname : 0
);
ImageDescriptor const * p_idsc = &idsc;
if (mic) p_idsc = &mic->GetLoadImage(idsc);
else _LOGPRINT(("WARNING! no rule to find matching images in game mode %s\n",egmc->header->mode_identifier));
#if TRY_OLD_DIRS // temporary until all textures move to SubShps/All directory
if (*p_idsc == idsc)
{
// select image descriptor
ImageDescriptor const idsc2
(
(IDscFlags)((bmpft.flags & ChunkBMPFlag_FixedPalette ?
IDSCF_FIXEDPALETTE
:
IDSCF_0)
|(ss->GetExtendedData()->flags & GBF_SPRITE ?
IDSCF_SPRITE
:
IDSCF_0)
|IDSCF_INCLUDED),
bmpfi().filename,
ss->shapename,
bmpft.flags & ChunkBMPFlag_FixedPalette ? ss->rifname : 0
);
ImageDescriptor const * p_idsc2 = &idsc2;
if (mic) p_idsc2 = &mic->GetLoadImage(idsc2);
else _LOGPRINT(("WARNING! no rule to find matching images in game mode %s\n",egmc->header->mode_identifier));
if (*p_idsc2 != idsc2)
{
_LOGPUT("WARNING! Not listed as in SubShps directory\n");
p_idsc = p_idsc2;
}
}
#endif
// load this image
GetPath(*p_idsc,envd,bmpft.flags);
if (fname)
{
if (rcname)
{
delete[] rcname;
rcname = 0;
}
flags.located = 1;
return CLE_OK;
}
}
}
}
if (rcname)
{
if (!shapefoundingm)
_LOGPRINT(("WARNING! shape/sprite %s not found in this RIF file\n",rcname));
else
_LOGPRINT(("WARNING! shape/sprite %s does not appear to list %s\n",rcname,name));
}
}
List<Chunk *> micl = envd->lookup_child("MATCHIMG");
Matching_Images_Chunk * mic_fix = 0;
Matching_Images_Chunk * mic_nrm = 0;
for (LIF<Chunk *> mici(&micl); !mici.done(); mici.next())
{
Matching_Images_Chunk * mic = (Matching_Images_Chunk *)mici();
if (mic->flags & MICF_FIXEDPALETTE)
mic_fix = mic;
else
mic_nrm = mic;
}
List<Chunk_With_Children *> shapesandsprites;
List<Chunk *> shlst = Env_Chunk->lookup_child("REBSHAPE");
for (LIF<Chunk *> shLIF(&shlst); !shLIF.done(); shLIF.next())
{
List<Chunk *> shxflst = ((Shape_Chunk *)shLIF())->lookup_child("SHPEXTFL");
if (shxflst.size())
{
shapesandsprites.add_entry( (Shape_External_File_Chunk *)shxflst.first_entry() );
}
}
shlst = Env_Chunk->lookup_child("RSPRITES");
if (shlst.size())
{
List<Chunk *> splst = ((Chunk_With_Children *)shlst.first_entry())->lookup_child("SPRIHEAD");
for (LIF<Chunk *> spLIF(&splst); !spLIF.done(); spLIF.next())
{
shapesandsprites.add_entry( (Chunk_With_Children *)spLIF() );
}
}
int shapefound = rcname ? 0 : 1;
for (LIF<Chunk_With_Children *> sasLIF(&shapesandsprites); !sasLIF.done(); sasLIF.next())
{
char * subrifname = riff_basename(sasLIF());
if (rcname)
{
if (_stricmp(subrifname,rcname)) // must match shapes name exactly
{
delete[] subrifname;
continue;
}
shapefound = 1;
}
List<Chunk *> blsclst = sasLIF()->lookup_child("BMPLSTST");
if (blsclst.size())
{
Bitmap_List_Store_Chunk * gbnc = (Bitmap_List_Store_Chunk *) blsclst.first_entry();
for (LIF<BMP_Name> bmpni(&gbnc->bmps); !bmpni.done(); bmpni.next())
{
BMP_Name bmpnt(bmpni());
strip_file_extension(bmpnt.filename);
if (iname ? !_stricmp(name,strip_path(bmpnt.filename)) : enum_id == bmpnt.enum_id)
{
// select image descriptor
char * riffname = riff_basename(envd);
ImageDescriptor const idsc
(
(IDscFlags)((bmpnt.flags & ChunkBMPFlag_FixedPalette ?
IDSCF_FIXEDPALETTE
:
IDSCF_0)
|(gbnc->GetExtendedData()->flags & GBF_SPRITE ?
IDSCF_SPRITE
:
IDSCF_SUBSHAPE)
|IDSCF_INCLUDED),
bmpni().filename,
subrifname,
bmpnt.flags & ChunkBMPFlag_FixedPalette ? riffname : 0
);
ImageDescriptor const * p_idsc = &idsc;
delete[] riffname;
if (bmpnt.flags & ChunkBMPFlag_FixedPalette)
{
if (mic_fix) p_idsc = &mic_fix->GetLoadImage(idsc);
else _LOGPUT("WARNING! no rule to find fixed palette matching images in environment data\n");
}
else
{
if (mic_nrm) p_idsc = &mic_nrm->GetLoadImage(idsc);
else _LOGPUT("WARNING! no rule to find matching images in environment data (interface engine?)\n");
}
#if TRY_OLD_DIRS // temporary until all textures move to SubShps/All directory
if (*p_idsc == idsc)
{
// select image descriptor
char * riffname = riff_basename(envd);
ImageDescriptor const idsc2
(
(IDscFlags)((bmpnt.flags & ChunkBMPFlag_FixedPalette ?
IDSCF_FIXEDPALETTE
:
IDSCF_0)
|(gbnc->GetExtendedData()->flags & GBF_SPRITE ?
IDSCF_SPRITE
:
IDSCF_0)
|IDSCF_INCLUDED),
bmpni().filename,
subrifname,
bmpnt.flags & ChunkBMPFlag_FixedPalette ? riffname : 0
);
ImageDescriptor const * p_idsc2 = &idsc2;
delete[] riffname;
if (bmpnt.flags & ChunkBMPFlag_FixedPalette)
{
if (mic_fix) p_idsc2 = &mic_fix->GetLoadImage(idsc2);
else _LOGPUT("WARNING! no rule to find fixed palette matching images in environment data\n");
}
else
{
if (mic_nrm) p_idsc2 = &mic_nrm->GetLoadImage(idsc2);
else _LOGPUT("WARNING! no rule to find matching images in environment data (interface engine?)\n");
}
if (*p_idsc2 != idsc2)
{
_LOGPUT("WARNING! Not listed as in SubShps directory\n");
p_idsc = p_idsc2;
}
}
#endif
// load this image
GetPath(*p_idsc,envd,bmpnt.flags);
if (fname)
{
delete[] subrifname;
if (rcname)
{
delete[] rcname;
rcname = 0;
}
flags.located = 1;
return CLE_OK;
}
}
}
}
delete[] subrifname;
}
if (rcname)
{
if (!shapefound)
_LOGPRINT(("WARNING! shape/sprite %s not found in this RIF file\n",rcname));
else
_LOGPRINT(("WARNING! shape/sprite %s does not appear to list %s\n",rcname,name));
delete[] rcname;
rcname = 0;
}
// not found in game textures, so look in default
else // but only if there is no virtual shape directory
{
List<Chunk *> gbncl = envd->lookup_child("BMPNAMES");
if (gbncl.size())
{
Global_BMP_Name_Chunk * gbnc = (Global_BMP_Name_Chunk *) gbncl.first_entry();
for (LIF<BMP_Name> bmpni(&gbnc->bmps); !bmpni.done(); bmpni.next())
{
BMP_Name bmpnt(bmpni());
strip_file_extension(bmpnt.filename);
if (iname ? !_stricmp(name,strip_path(bmpnt.filename)) : enum_id == bmpnt.enum_id)
{
// select image descriptor
ImageDescriptor const idsc (bmpnt.flags & ChunkBMPFlag_FixedPalette ? IDSCF_FIXEDPALETTE : IDSCF_0, bmpni().filename);
ImageDescriptor const * p_idsc = &idsc;
if (bmpnt.flags & ChunkBMPFlag_FixedPalette)
{
if (mic_fix) p_idsc = &mic_fix->GetLoadImage(idsc);
else _LOGPUT("WARNING! no rule to find fixed palette matching images in environment data\n");
}
else
{
if (mic_nrm) p_idsc = &mic_nrm->GetLoadImage(idsc);
else _LOGPUT("WARNING! no rule to find matching images in environment data (interface engine?)\n");
}
// load this image
GetPath(*p_idsc,envd,bmpnt.flags);
if (fname)
{
flags.located = 1;
return CLE_OK;
}
}
}
}
}
if (retval != CLE_OK) return retval;
return CLE_FINDERROR;
}

33
src/win95/chnkimag.hpp Normal file
View file

@ -0,0 +1,33 @@
#ifndef _included__chnkimag_hpp_
#define _included__chnkimag_hpp_
#error "This file is obsolete"
#include <stdio.h>
#include "d3_image.hpp"
#include "mishchnk.hpp"
#include "bmpnames.hpp"
extern "C" extern char projectsubdirectory[];
extern char const * GameTex_Directory;
extern char const * GenTex_Directory;
extern char const * FixTex_Directory;
extern char const * ToolsTex_Directory;
struct CL_RIFFImage : public CL_Image
{
public:
static char const * game_mode; // game mode defines palette and set of graphics - can be null or "" for default
CL_RIFFImage() : CL_Image() {}
CL_RIFFImage(CL_Image const & base) : CL_Image(base) {}
private:
virtual CL_Error Locate(char const * iname, int const enum_id);
void GetPath(ImageDescriptor const & idsc, Environment_Data_Chunk * envd, BMPN_Flags bflags);
};
#endif // !_included__chnkimag_hpp_

4024
src/win95/chnkload.cpp Normal file

File diff suppressed because it is too large Load diff

233
src/win95/chnkload.h Normal file
View file

@ -0,0 +1,233 @@
#ifndef _chnkload_h_
#define _chnkload_h_
#ifdef __cplusplus
extern "C" {
#endif
#include "system.h"
#include "equates.h"
#include "platform.h"
#include "shape.h"
#include "prototyp.h"
#include "module.h"
extern SCREENDESCRIPTORBLOCK ScreenDescriptorBlock;
#define GLS_NOTINLIST (-1)
///////////////////
// RIF Loading, etc
///////////////////
typedef struct _RifHandle * RIFFHANDLE;
#define INVALID_RIFFHANDLE 0
// flags - project specific ones start at lsb
// - generic ones to start from msb
#define CCF_NOMORPH 0x80000000
typedef enum UVCoordType
{
UVC_SPRITE_U,
UVC_SPRITE_V,
UVC_POLY_U,
UVC_POLY_V,
} UVCOORDTYPE;
// Note: for aesthetic reasons, macros enable one to have all one's fuctions in lower case or captialized, to suit one's style!
// For clarity, functions which are to be defined in project specific files
// are here declared with extern
/////////////////////////////////////////
// Functions which operate on RIFFHANDLEs
/////////////////////////////////////////
// load a rif file into memory
RIFFHANDLE load_rif (const char * fname);
RIFFHANDLE load_rif_non_env (const char * fname);
#define LoadRIF(s) load_rif(s)
// deallocate the shapes, unload the rif, close the handle
void undo_rif_load (RIFFHANDLE);
#define UndoRIFLoad(h) undo_rif_load(h)
// deallocate the shapes copied from the rif
void deallocate_loaded_shapes (RIFFHANDLE);
#define DeallocateLoadedShapes(h) deallocate_loaded_shapes(h)
// unloads the rif but keeps the handle and associated copied shapes
void unload_rif (RIFFHANDLE);
#define UnloadRIF(h) unload_rif(h);
// close the handle - performs tidying up and memory deallocation
void close_rif_handle (RIFFHANDLE);
#define CloseRIFHandle(h) close_rif_handle(h)
// load textures for environment
BOOL load_rif_bitmaps (RIFFHANDLE, int flags);
#define LoadRIFBitmaps(h,f) load_rif_bitmaps(h,f)
// set the quantization event depending on CL_RIFFImage::game_mode
BOOL set_quantization_event(RIFFHANDLE, int flags);
#define SetQuantizationEvent(h,f) set_quantization_event(h,f)
// copy palette
BOOL copy_rif_palette (RIFFHANDLE, int flags);
#define CopyRIFPalette(h,f) copy_rif_palette(h,f)
// copy texture lighting table
BOOL copy_rif_tlt (RIFFHANDLE, int flags);
#define CopyRIFTLT(h,f) copy_rif_tlt(h,f)
// copy palette remap table (15-bit) - post_process_shape may use it
BOOL get_rif_palette_remap_table (RIFFHANDLE, int flags);
#define GetRIFPaletteRemapTable(h,f) get_rif_palette_remap_table(h,f)
// copy one named shape or sprite; does not put in main shape list, needs deallocating
SHAPEHEADER * CopyNamedShapePtr (RIFFHANDLE, char const * shapename);
#define copy_named_shape_ptr(h,s) CopyNamedShapePtr(h,s)
// copy one named shape or sprite; put it in the main shape list
int CopyNamedShapeMSL (RIFFHANDLE, char const * shapename);
#define copy_named_shape_msl(h,s) CopyNamedShapeMSL(h,s)
////////////////////////////////////////////////////////////////////////
// Functions which do not operate on RIFFHANDLEs and may become obsolete
////////////////////////////////////////////////////////////////////////
// these functions work on the current rif; they only remain for historical reasons
extern RIFFHANDLE current_rif_handle;
// returns NULL on fail; does not put it in the mainshapelist
SHAPEHEADER * CopyNamedShape (char const * shapename);
/////////////////////////////////////////////
// Functions for handling the main shape list
/////////////////////////////////////////////
// reserves the next avaialbe position in the main shape list and returns it
extern int GetMSLPos(void);
#define get_msl_pos() GetMSLPos()
// frees a position in the main shape list
extern void FreeMSLPos(int);
#define free_msl_pos(i) FreeMSLPos(i)
////////////////////////////////////////////////
// Functions retrieving data about loaded shapes
////////////////////////////////////////////////
// gets the main shape list position of a shape loaded into the msl
int GetLoadedShapeMSL(char const * shapename);
#define get_loaded_shape_msl(s) GetLoadedShapeMSL(s)
// ditto, but returns a pointer; the shape need not be in the msl
SHAPEHEADER * GetLoadedShapePtr(char const * shapename);
#define get_loaded_shape_ptr(s) GetLoadedShapePtr(s)
// gets name of shape from msl pos
char const * GetMSLLoadedShapeName(int listpos);
#define get_msl_loaded_shape_name(i) GetMSLLoadedShapeName(i)
// gets name of shape from pointer; the shape need not be in msl
char const * GetPtrLoadedShapeName(SHAPEHEADER *);
#define get_ptr_loaded_shape_name(p) GetPtrLoadedShapeName(p)
// free a reference to a named shape if it exists - not necessary since these are all tidied up
void FreeShapeNameReference(SHAPEHEADER * shptr);
#define free_shape_name_reference(p) FreeShapeNameReference(p)
//////////////////////////////////////////////////////////////////////////////
// Initializing, deallocating of shapes, mainly hooks for project specific fns
//////////////////////////////////////////////////////////////////////////////
// perform initial post processing on shape just after loading
// note that the copy named shape functions will not call this
extern void post_process_shape (SHAPEHEADER *);
#define PostProcessShape(p) post_process_shape(p)
// hook to perhaps scale the uv coordinates - should return new value
extern int ProcessUVCoord(RIFFHANDLE,UVCOORDTYPE,int uv_value,int image_num);
#define process_uv_coord(h,t,u,i) ProcessUVCoord(h,t,u,i)
// delete a shape by the shapeheader
void DeallocateLoadedShapePtr(SHAPEHEADER *);
#define deallocate_loaded_shape_ptr(h,p) DeallocateLoadedShapePtr(h,p)
// delete a shape by the shape list number
void DeallocateLoadedShapeMSL(RIFFHANDLE, int);
#define deallocate_loaded_shape_msl(h,i) DeallocateLoadedShapeMSL(h,i)
// your function could perform any extra tidying up you need
extern void DeallocateLoadedShapeheader(SHAPEHEADER *);
#define deallocate_loaded_shapeheader(p) DeallocateLoadedShapeHeader(p)
// your function should call this function which undoes the allocation done when copied from rif data
void DeallocateRifLoadedShapeheader(SHAPEHEADER *);
#define deallocate_rif_loaded_shapeheader(p) DeallocateRifLoadedShapeHeader(p)
///////
// Misc
///////
// return TRUE if the poly item type corresponds to a textured polygon
BOOL is_textured(int);
#define IsTextured(i) is_textured(i)
/////////////////////
// Rif loader globals
/////////////////////
extern unsigned char const * PaletteMapTable;
/////////////////
// Engine globals
/////////////////
extern int start_of_loaded_shapes;
extern unsigned char *TextureLightingTable;
#if defined(InterfaceEngine) && InterfaceEngine
// this is of crucial importance!!
extern SHAPEHEADER * mainshapelist[];
#else
extern SHAPEHEADER ** mainshapelist;
#endif
extern MAPHEADER Map[];
extern MAPBLOCK8 Player_and_Camera_Type8[];
extern MAPBLOCK6 Empty_Landscape_Type6;
extern MAPBLOCK6 Empty_Object_Type6;
extern MAPBLOCK6 Term_Type6;
extern unsigned char TestPalette[];
extern unsigned char LPTestPalette[]; /* to cast to lp*/
#if 0
extern int NumImages; /* # current images */
extern IMAGEHEADER *ImageHeaderPtrs[]; /* Ptrs to Image Header Blocks */
extern IMAGEHEADER ImageHeaderArray[]; /* Array of Image Headers */
extern IMAGEHEADER *NextFreeImageHeaderPtr;
#endif
#if SupportModules
extern SCENEMODULE MainScene;
extern MODULE Empty_Module;
extern MODULE Term_Module;
extern MODULEMAPBLOCK Empty_Module_Map;
#endif
#ifdef __cplusplus
}
#endif
#endif

106
src/win95/chnkload.hpp Normal file
View file

@ -0,0 +1,106 @@
#ifndef _chnkload_hpp
#define _chnkload_hpp 1
#include "chnkload.h"
#ifdef __cplusplus
#include "chunk.hpp"
#include "shpchunk.hpp"
#include "obchunk.hpp"
#include "bmpnames.hpp"
#include "projload.hpp"
#if 0
extern BOOL copy_to_mainshpl (Shape_Chunk *shape, int list_pos);
extern BOOL copy_to_mainshpl (Shape_Sub_Shape_Chunk *shape, int list_pos);
#endif
extern void copy_to_module (Object_Chunk * ob, int mod_pos, int shplst_pos);
extern BOOL copy_to_shapeheader (
RIFFHANDLE,
ChunkShape const & cshp,
SHAPEHEADER *& shphd,
Chunk_With_Children * shape,
int flags,
int local_max_index,
int * local_tex_index_nos,
int listpos = GLS_NOTINLIST,
const ChunkObject* object=0 //object used so that conversion from float to int can be done in world coordinates
);
extern BOOL copy_preprocessed_to_shapeheader (
RIFFHANDLE,
Shape_Preprocessed_Data_Chunk*,
SHAPEHEADER *& shphd,
Chunk_With_Children * shape,
int flags,
int local_max_index,
int * local_tex_index_nos,
int listpos = GLS_NOTINLIST,
const ChunkObject* object=0 //object used so that conversion from float to int can be done in world coordinates
);
extern BOOL copy_sprite_to_shapeheader (RIFFHANDLE, SHAPEHEADER *& shphd,Sprite_Header_Chunk* shc, int listpos = GLS_NOTINLIST);
extern BOOL copy_to_map6(Object_Chunk *,MAPBLOCK6*, int shplst_pos);
extern void merge_polygons_in_chunkshape (ChunkShape & shp, Shape_Merge_Data_Chunk * smdc);
extern File_Chunk * Env_Chunk;
extern double local_scale;
// copies shape to msl
#if SupportMorphing && LOAD_MORPH_SHAPES
typedef struct
{
int start_list_pos;
int main_list_pos;
MORPHCTRL * mc;
} CTM_ReturnType;
#else
typedef int CTM_ReturnType;
#endif
CTM_ReturnType copy_to_mainshapelist(RIFFHANDLE, Shape_Chunk *, int flags,const ChunkObject* object=0);
#define CopyToMainshapelist(h,r,p,f) copy_to_mainshapelist(h,r,p,f)
// copies sprite to msl
int copy_sprite_to_mainshapelist(RIFFHANDLE, Sprite_Header_Chunk *, int flags);
#define CopySpriteToMainshapelist(h,p,f) copy_sprite_to_mainshapelist(h,p,f)
// hook to load a bitmap - so you can load them from test directories, etc. should return tex index
extern int load_rif_bitmap (char const * fname, BMPN_Flags flags);
#define LoadRIFBitmap(s,f) load_rif_bitmap(s,f)
// project specific shape pre processing - usually merge polys
extern void pre_process_shape (RIFFHANDLE, ChunkShape &, Chunk_With_Children * shape_chunk, int flags);
#define PreProcessShape(h,r,p,f) pre_process_shape(h,r,p,f)
struct _RifHandle : Project_RifHandle
{
File_Chunk * fc;
Environment_Data_Chunk * envd;
Chunk_With_Children * palparent;
List<int> shape_nums;
int max_index;
int * tex_index_nos;
~_RifHandle()
{}
_RifHandle()
: fc(0)
, envd(0)
, max_index(0)
, tex_index_nos(0)
, palparent(0)
{}
};
#endif
#endif

940
src/win95/chnktexi.cpp Normal file
View file

@ -0,0 +1,940 @@
#include <windows.h>
#include <string.h>
#include <string.hpp>
#ifndef DB_LEVEL
#define DB_LEVEL 4
#endif
#include "db.h"
#include "awTexLd.h"
#include "chnkload.hpp"
#include "chunkpal.hpp"
#ifndef CL_SUPPORT_FASTFILE
#error "Please #define CL_SUPPORT_FASTFILE to 0 or 1 in projload.hpp"
#endif
#if CL_SUPPORT_FASTFILE
#include "ffstdio.h"
#endif
#ifndef CL_SUPPORT_ALTTAB
#error "Please #define CL_SUPPORT_ALTTAB to 0 or 1 in projload.hpp"
#endif
#if CL_SUPPORT_ALTTAB
#include "alt_tab.h"
#endif
#include "chnktexi.h"
#if !defined(NDEBUG) && defined(_CPPRTTI)
#include <typeinfo.h>
#else
#define dynamic_cast static_cast
#endif
char const * cl_pszGameMode = NULL;
// used to determine if the display is palettized
// currently assuming that if this is <= 8 then all
// surfaces et. except d3d textures have a global palette
extern "C" extern int VideoModeColourDepth;
// useful filename handling functions
// returns pointer into string pointing to filename without dirname
template <class C> // C can be char or char const
static C * StripPath(C * n)
{
C * rm = strrchr(n,':');
if (rm) n = rm+1;
rm = strrchr(n,'/');
if (rm) n = rm+1;
rm = strrchr(n,'\\');
if (rm) n = rm+1;
return n;
}
// removes any .extension from filename by inserting null character
static void StripFileExtension(char * n)
{
char * dotpos = strrchr(n,'.');
if (dotpos) *dotpos = 0;
}
static char * StripFileExtension(char const * n)
{
char * nn = new char[strlen(n)+1];
strcpy(nn,n);
StripFileExtension(nn);
return nn;
}
// get the directory associated with the riff - free with delete[]
static char * RiffBasename(Chunk_With_Children * pEnvDataChunk)
{
Chunk * pChunk = pEnvDataChunk->lookup_single_child("RIFFNAME");
if (pChunk)
{
RIF_Name_Chunk * pRifNameChunk = dynamic_cast<RIF_Name_Chunk *>(pChunk);
const char * pszRifName = StripPath(pRifNameChunk->rif_name);
char * pszBaseName = new char[strlen(pszRifName)+1];
strcpy(pszBaseName,pszRifName);
StripFileExtension(pszBaseName);
return pszBaseName;
}
const char * pszDefault = "empty";
char * pszBaseName = new char [strlen(pszDefault)+1];
strcpy(pszBaseName,pszDefault);
return pszBaseName;
}
#if CL_SUPPORT_FASTFILE
static inline bool IsFileInFastFile(char const * pszFileName)
{
unsigned nLen;
return ffreadbuf(pszFileName,&nLen) ? true : false;
}
#endif
static bool DoesFileExist(char const * pszFileName)
{
DWORD dwFileAttributes = GetFileAttributes(pszFileName);
if (0xffffffff == dwFileAttributes || dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
return false;
else
return true;
}
static char * GetPath(char * pszFileNameBuf, unsigned nBufSize, ImageDescriptor const & idsc, Chunk_With_Children * pEnvDataChunk, bool bGloballyPalettized)
{
// set the name
char const * pszRawName = StripPath(idsc.filename);
char * pszName = new char[strlen(pszRawName)+1];
strcpy(pszName,pszRawName);
StripFileExtension(pszName);
// load this image
char const * pg0ext = ".PG0";
if (!bGloballyPalettized)
{
char const * dir2 = idsc.flags & IDSCF_SPRITE ? "Sprites\\" : idsc.flags & IDSCF_SUBSHAPE ? SubShps_Directory : "";
char * riffname = RiffBasename(pEnvDataChunk);
char const * dir3 = idsc.flags & IDSCF_INCLUDED ? idsc.rifname : riffname;
if (nBufSize < strlen(GenTex_Directory)+strlen(dir2)+strlen(dir3)+1+strlen(pszName)+5)
{
db_log1("CL_LoadImageOnce(): ERROR: buffer not big enough for filename");
pszFileNameBuf = NULL;
}
else
{
strcpy(pszFileNameBuf,GenTex_Directory);
strcat(pszFileNameBuf,dir2);
strcat(pszFileNameBuf,dir3);
strcat(pszFileNameBuf,"\\");
strcat(pszFileNameBuf,pszName);
strcat(pszFileNameBuf,".BM0");
}
delete[] riffname;
}
else
{
if (idsc.flags & IDSCF_FIXEDPALETTE)
{
char const * dir2 = idsc.fixrifname ? *idsc.fixrifname ? idsc.fixrifname : 0 : 0;
char const * dir3 = idsc.flags & IDSCF_SPRITE ? "Sprites\\" : "";
char * riffname = RiffBasename(pEnvDataChunk);
char const * dir4 = idsc.flags & IDSCF_INCLUDED ? idsc.rifname : riffname;
if (nBufSize < strlen(FixTex_Directory)+(dir2 ? strlen(dir2)+1 : 0)+strlen(dir3)+strlen(dir4)+1+strlen(pszName)+5)
{
db_log1("CL_LoadImageOnce(): ERROR: buffer not big enough for filename");
pszFileNameBuf = NULL;
}
else
{
strcpy(pszFileNameBuf,FixTex_Directory);
if (dir2)
{
strcat(pszFileNameBuf,dir2);
strcat(pszFileNameBuf,"\\");
}
strcat(pszFileNameBuf,dir3);
strcat(pszFileNameBuf,dir4);
strcat(pszFileNameBuf,"\\");
strcat(pszFileNameBuf,pszName);
strcat(pszFileNameBuf,pg0ext);
}
delete[] riffname;
}
else
{
char const * dir1 = cl_pszGameMode ? GameTex_Directory : ToolsTex_Directory;
char * dir2 = RiffBasename(pEnvDataChunk);
char const * dir4 = idsc.flags & IDSCF_SPRITE ? "Sprites\\" : "";
char const * dir5 = idsc.flags & IDSCF_INCLUDED ? idsc.rifname : 0;
if (nBufSize < strlen(dir1)+strlen(dir2)+1+(cl_pszGameMode ? strlen(cl_pszGameMode)+1 : 0)+strlen(dir4)+(dir5 ? strlen(dir5)+1 : 0)+strlen(pszName)+5)
{
db_log1("CL_LoadImageOnce(): ERROR: buffer not big enough for filename");
pszFileNameBuf = NULL;
}
else
{
strcpy(pszFileNameBuf,dir1);
strcat(pszFileNameBuf,dir2);
strcat(pszFileNameBuf,"\\");
if (cl_pszGameMode)
{
strcat(pszFileNameBuf,cl_pszGameMode);
strcat(pszFileNameBuf,"\\");
}
strcat(pszFileNameBuf,dir4);
if (dir5)
{
strcat(pszFileNameBuf,dir5);
strcat(pszFileNameBuf,"\\");
}
strcat(pszFileNameBuf,pszName);
strcat(pszFileNameBuf,pg0ext);
}
delete[] dir2;
}
}
if (pszFileNameBuf)
db_logf4(("\tfile expected to be '%s'",pszFileNameBuf));
delete[] pszName;
return pszFileNameBuf;
}
char * CL_GetImageFileName(char * pszDestBuf, unsigned nBufSize, char const * pszFileName, unsigned fFlagsEtc)
{
db_assert1(pszFileName);
db_assert1(pszDestBuf);
db_assert1(nBufSize>0);
db_logf4(("CL_LoadImageOnce(): Getting the full pathname for %s",pszFileName));
switch (fFlagsEtc & _LIO_PATHTYPEMASK)
{
case LIO_ABSOLUTEPATH:
db_log4("\t(which is an absolute path)");
if (strlen(pszFileName)<nBufSize)
{
strcpy(pszDestBuf,pszFileName);
return pszDestBuf;
}
else
{
db_log1("CL_LoadImageOnce(): ERROR: buffer not large enough to hold filename");
return NULL;
}
case LIO_RELATIVEPATH:
db_logf4(("\t(which is a path relative to %s or %s)",
FirstTex_Directory ? FirstTex_Directory : "<not-specified>",
SecondTex_Directory ? SecondTex_Directory : "<not-specified>"));
#define _GET_RELATIVE_PATH(pszDirectory,fnDoesExist) \
if (pszDirectory) { \
String str = pszDirectory; \
if (str.length()) { \
int chLast = str.get_at(str.length()-1); \
if (chLast != '\\' && chLast != '/') \
str += '\\'; \
str += pszFileName; \
if (fnDoesExist(str)) { \
if (str.length() < nBufSize) { \
strcpy(pszDestBuf,str); \
return pszDestBuf; \
} else { \
db_log1("CL_LoadImageOnce(): ERROR: buffer not large enough to hold filename"); \
return NULL; /* fail because the buffer isnt big enough */ \
} } } }
#if CL_SUPPORT_FASTFILE
_GET_RELATIVE_PATH(FirstTex_Directory,IsFileInFastFile)
_GET_RELATIVE_PATH(SecondTex_Directory,IsFileInFastFile)
#endif
#if !defined(CL_SUPPORTONLY_FASTFILE) || !CL_SUPPORTONLY_FASTFILE
_GET_RELATIVE_PATH(FirstTex_Directory,DoesFileExist)
_GET_RELATIVE_PATH(SecondTex_Directory,DoesFileExist)
#endif
db_log1("CL_LoadImageOnce(): ERROR: file not found in relative path");
return NULL;
case LIO_RIFFPATH:
{
int enum_id = -1; // may be supported at a later date, valid when pszFileName is NULL
bool bGloballyPalettized = VideoModeColourDepth <= 8 && (fFlagsEtc & _LIO_SURFTYPEMASK) != LIO_D3DTEXTURE;
db_log4("\t(whose path is determined by the current .RIF file)");
if (!Env_Chunk)
{
db_log1("CL_LoadImageOnce(): ERROR: no RIF file");
return NULL;
}
Chunk * pChunk = Env_Chunk->lookup_single_child("REBENVDT");
if (!pChunk)
{
db_log1("CL_LoadImageOnce(): ERROR: no environment data chunk");
return NULL;
}
Chunk_With_Children * pEnvDataChunk = dynamic_cast<Chunk_With_Children *>(pChunk);
db_assert1(pEnvDataChunk);
Environment_Game_Mode_Chunk * pGameModeChunk = NULL;
if (cl_pszGameMode)
{
if (*cl_pszGameMode)
{
List<Chunk *> listGmChunks;
pEnvDataChunk->lookup_child("GAMEMODE",listGmChunks);
for (LIF<Chunk *> itGmChunks(&listGmChunks); !itGmChunks.done(); itGmChunks.next())
{
Environment_Game_Mode_Chunk * pGmChunk = dynamic_cast<Environment_Game_Mode_Chunk *>(itGmChunks());
db_assert1(pGmChunk);
if (pGmChunk->id_equals(cl_pszGameMode))
{
pGameModeChunk = pGmChunk;
break;
}
}
if (!pGameModeChunk)
db_logf3(("CL_LoadImageOnce(): WARNING: Game Mode '%s' not found",cl_pszGameMode));
}
}
char * pszName = StripFileExtension(StripPath(pszFileName));
char * pszSubName = 0;
if (pszFileName)
{
if (strchr(pszFileName,'\\'))
{
pszSubName = new char[strlen(pszFileName)+1];
strcpy(pszSubName,pszFileName);
*strchr(pszSubName,'\\')=0;
}
else if (strchr(pszFileName,'/'))
{
pszSubName = new char[strlen(pszFileName)+1];
strcpy(pszSubName,pszFileName);
*strchr(pszSubName,'/')=0;
}
}
if (pGameModeChunk)
{
bool bShapeInGm = pszSubName ? false : true;
// Get the matching image 'Processor' chunk
Chunk * pMiChunk = pGameModeChunk->lookup_single_child("MATCHIMG");
Matching_Images_Chunk * pMatchImageChunk = NULL;
if (pMiChunk)
{
pMatchImageChunk = dynamic_cast<Matching_Images_Chunk *>(pMiChunk);
db_assert1(pMatchImageChunk);
}
List<Chunk *> listRifChildChunks;
pGameModeChunk->lookup_child("RIFCHILD",listRifChildChunks);
for (LIF<Chunk *> itRifChildChunks(&listRifChildChunks); !itRifChildChunks.done(); itRifChildChunks.next())
{
RIF_Child_Chunk * pRifChildChunk = dynamic_cast<RIF_Child_Chunk *>(itRifChildChunks());
db_assert1(pRifChildChunk);
if (pszSubName)
{
if (_stricmp(pszSubName,pRifChildChunk->rifname) && (*pszSubName || *pRifChildChunk->filename))
continue;
bShapeInGm = true;
}
for (LIF<BMP_Flags> itBmpFlags(&pRifChildChunk->bmps); !itBmpFlags.done(); itBmpFlags.next())
{
BMP_Flags bmpfTemp(itBmpFlags());
StripFileExtension(bmpfTemp.filename);
if (pszFileName ? !_stricmp(pszName,StripPath(bmpfTemp.filename)) : enum_id == bmpfTemp.enum_id)
{
// select image descriptor
ImageDescriptor const idsc
(
*pRifChildChunk->filename ?
(IDscFlags)((bmpfTemp.flags & ChunkBMPFlag_FixedPalette ?
IDSCF_FIXEDPALETTE
:
IDSCF_0)
|IDSCF_INCLUDED)
:
IDSCF_0,
itBmpFlags().filename,
*pRifChildChunk->filename ? pRifChildChunk->rifname : 0
);
ImageDescriptor const * pIdsc = &idsc;
if (pMatchImageChunk) pIdsc = &pMatchImageChunk->GetLoadImage(idsc);
else db_logf3(("CL_LoadImageOnce(): WARNING! no rule to find matching images in game mode '%s'\n",pGameModeChunk->header->mode_identifier));
// load this image
if (GetPath(pszDestBuf,nBufSize,*pIdsc,pEnvDataChunk,bGloballyPalettized))
{
if (pszSubName)
{
delete[] pszSubName;
}
delete[] pszName;
return pszDestBuf;
}
}
}
}
List<Chunk *> listExtShapes;
pGameModeChunk->lookup_child("SHBMPNAM",listExtShapes);
for (LIF<Chunk *> itExtShapes(&listExtShapes); !itExtShapes.done(); itExtShapes.next())
{
External_Shape_BMPs_Store_Chunk * pShapeBmpsChunk = dynamic_cast<External_Shape_BMPs_Store_Chunk *>(itExtShapes());
db_assert1(pShapeBmpsChunk);
if (pszSubName)
if (_stricmp(pszSubName,pShapeBmpsChunk->shapename) && *pszSubName)
continue;
for (LIF<BMP_Name> itBmpNames(&pShapeBmpsChunk->bmps); !itBmpNames.done(); itBmpNames.next())
{
BMP_Name bmpnTemp(itBmpNames());
StripFileExtension(bmpnTemp.filename);
if (pszFileName ? !_stricmp(pszName,StripPath(bmpnTemp.filename)) : enum_id == bmpnTemp.enum_id)
{
// select image descriptor
ImageDescriptor const idsc
(
(IDscFlags)((bmpnTemp.flags & ChunkBMPFlag_FixedPalette ?
IDSCF_FIXEDPALETTE
:
IDSCF_0)
|(pShapeBmpsChunk->GetExtendedData()->flags & GBF_SPRITE ?
IDSCF_SPRITE
:
IDSCF_SUBSHAPE)
|IDSCF_INCLUDED),
itBmpNames().filename,
pShapeBmpsChunk->shapename,
bmpnTemp.flags & ChunkBMPFlag_FixedPalette ? pShapeBmpsChunk->rifname : 0
);
ImageDescriptor const * pIdsc = &idsc;
if (pMatchImageChunk) pIdsc = &pMatchImageChunk->GetLoadImage(idsc);
else db_logf3(("WARNING! no rule to find matching images in game mode %s\n",pGameModeChunk->header->mode_identifier));
// load this image
if (GetPath(pszDestBuf,nBufSize,*pIdsc,pEnvDataChunk,bGloballyPalettized))
{
if (pszSubName)
{
delete[] pszSubName;
}
delete[] pszName;
return pszDestBuf;
}
}
}
}
if (pszSubName)
{
if (!bShapeInGm)
db_logf3(("CL_LoadImageOnce(): WARNING! shape/sprite %s not found in this RIF file\n",pszSubName));
else
db_logf3(("CL_LoadImageOnce(): WARNING! shape/sprite %s does not appear to list %s\n",pszSubName,pszName));
}
}
List<Chunk *> listMatchImageChunk;
pEnvDataChunk->lookup_child("MATCHIMG",listMatchImageChunk);
Matching_Images_Chunk * pMicFix = NULL;
Matching_Images_Chunk * pMicNorm = NULL;
for (LIF<Chunk *> itMatchImageChunk(&listMatchImageChunk); !itMatchImageChunk.done(); itMatchImageChunk.next())
{
Matching_Images_Chunk * pMatchImageChunk = dynamic_cast<Matching_Images_Chunk *>(itMatchImageChunk());
db_assert1(pMatchImageChunk);
if (pMatchImageChunk->flags & MICF_FIXEDPALETTE)
pMicFix = pMatchImageChunk;
else
pMicNorm = pMatchImageChunk;
}
List<Chunk_With_Children *> listShapesSprites;
List<Chunk *> listShapes;
Env_Chunk->lookup_child("REBSHAPE",listShapes);
for (LIF<Chunk *> itShapes(&listShapes); !itShapes.done(); itShapes.next())
{
Shape_Chunk * pShapeChunk = dynamic_cast<Shape_Chunk *>(itShapes());
db_assert1(pShapeChunk);
Chunk * pSxfnChunk = pShapeChunk->lookup_single_child("SHPEXTFL");
if (pSxfnChunk)
{
Shape_External_File_Chunk * pShpExtFnameChunk = dynamic_cast<Shape_External_File_Chunk *>(pSxfnChunk);
db_assert1(pShpExtFnameChunk);
listShapesSprites.add_entry(pShpExtFnameChunk);
}
}
Chunk * pSprChunk = Env_Chunk->lookup_single_child("RSPRITES");
if (pSprChunk)
{
Chunk_With_Children * pSpritesChunk = dynamic_cast<Chunk_With_Children *>(pSprChunk);
db_assert1(pSpritesChunk);
List<Chunk *> listSprHeadChunks;
pSpritesChunk->lookup_child("SPRIHEAD",listSprHeadChunks);
for (LIF<Chunk *> itSprites(&listSprHeadChunks); !itSprites.done(); itSprites.next())
{
Chunk_With_Children * pSpriteHead = dynamic_cast<Chunk_With_Children *>(itSprites());
db_assert1(pSpriteHead);
listShapesSprites.add_entry(pSpriteHead);
}
}
int bShapeFound = pszSubName ? false : true;
for (LIF<Chunk_With_Children *> itShapesSprites(&listShapesSprites); !itShapesSprites.done(); itShapesSprites.next())
{
char * pszSubRifName = RiffBasename(itShapesSprites());
if (pszSubName)
{
if (_stricmp(pszSubRifName,pszSubName)) // must match shapes name exactly
{
delete[] pszSubRifName;
continue;
}
bShapeFound = true;
}
Chunk * pBmpLstStChunk = itShapesSprites()->lookup_single_child("BMPLSTST");
if (pBmpLstStChunk)
{
Bitmap_List_Store_Chunk * pBmpListStoreChunk = dynamic_cast<Bitmap_List_Store_Chunk *>(pBmpLstStChunk);
db_assert1(pBmpListStoreChunk);
for (LIF<BMP_Name> itBmpName(&pBmpListStoreChunk->bmps); !itBmpName.done(); itBmpName.next())
{
BMP_Name bmpnTemp(itBmpName());
StripFileExtension(bmpnTemp.filename);
if (pszFileName ? !_stricmp(pszName,StripPath(bmpnTemp.filename)) : enum_id == bmpnTemp.enum_id)
{
// select image descriptor
char * pszRifName = RiffBasename(pEnvDataChunk);
ImageDescriptor const idsc
(
(IDscFlags)((bmpnTemp.flags & ChunkBMPFlag_FixedPalette ?
IDSCF_FIXEDPALETTE
:
IDSCF_0)
|(pBmpListStoreChunk->GetExtendedData()->flags & GBF_SPRITE ?
IDSCF_SPRITE
:
IDSCF_SUBSHAPE)
|IDSCF_INCLUDED),
itBmpName().filename,
pszSubRifName,
bmpnTemp.flags & ChunkBMPFlag_FixedPalette ? pszRifName : 0
);
ImageDescriptor const * pIdsc = &idsc;
delete[] pszRifName;
if (bmpnTemp.flags & ChunkBMPFlag_FixedPalette)
{
if (pMicFix) pIdsc = &pMicFix->GetLoadImage(idsc);
else db_log3("CL_LoadImageOnce(): WARNING! no rule to find fixed palette matching images in environment data\n");
}
else
{
if (pMicNorm) pIdsc = &pMicNorm->GetLoadImage(idsc);
else db_log3("CL_LoadImageOnce(): WARNING! no rule to find matching images in environment data (interface engine?)\n");
}
// load this image
if (GetPath(pszDestBuf,nBufSize,*pIdsc,pEnvDataChunk,bGloballyPalettized))
{
delete[] pszSubRifName;
if (pszSubName)
{
delete[] pszSubName;
}
delete[] pszName;
return pszDestBuf;
}
}
}
}
delete[] pszSubRifName;
}
if (pszSubName)
{
if (!bShapeFound)
db_logf3(("CL_LoadImageOnce(): WARNING! shape/sprite %s not found in this RIF file\n",pszSubName));
else
db_logf3(("CL_LoadImageOnce(): WARNING! shape/sprite %s does not appear to list %s\n",pszSubName,pszName));
delete[] pszSubName;
}
// not found in game textures, so look in default
else // but only if there is no virtual shape directory
{
Chunk * pBmpNames = pEnvDataChunk->lookup_single_child("BMPNAMES");
if (pBmpNames)
{
Global_BMP_Name_Chunk * pGbnc = dynamic_cast<Global_BMP_Name_Chunk *>(pBmpNames);
db_assert1(pGbnc);
for (LIF<BMP_Name> itBmpName(&pGbnc->bmps); !itBmpName.done(); itBmpName.next())
{
BMP_Name bmpnTemp(itBmpName());
StripFileExtension(bmpnTemp.filename);
if (pszFileName ? !_stricmp(pszName,StripPath(bmpnTemp.filename)) : enum_id == bmpnTemp.enum_id)
{
// select image descriptor
ImageDescriptor const idsc (bmpnTemp.flags & ChunkBMPFlag_FixedPalette ? IDSCF_FIXEDPALETTE : IDSCF_0, itBmpName().filename);
ImageDescriptor const * pIdsc = &idsc;
if (bmpnTemp.flags & ChunkBMPFlag_FixedPalette)
{
if (pMicFix) pIdsc = &pMicFix->GetLoadImage(idsc);
else db_log3("CL_LoadImageOnce(): WARNING! no rule to find fixed palette matching images in environment data\n");
}
else
{
if (pMicNorm) pIdsc = &pMicNorm->GetLoadImage(idsc);
else db_log3("CL_LoadImageOnce(): WARNING! no rule to find matching images in environment data (interface engine?)\n");
}
// load this image
if (GetPath(pszDestBuf,nBufSize,*pIdsc,pEnvDataChunk,bGloballyPalettized))
{
delete[] pszName;
return pszDestBuf;
}
}
}
}
}
delete[] pszName;
return NULL;
}
default: // invalid arguments
db_log1("CL_LoadImageOnce(): ERROR: invalid parameter passed to CL_GetImageFileName()");
return NULL;
}
}
extern "C" extern void CheckForWindowsMessages(void);
int CL_LoadImageOnce(char const * pszFileName, unsigned fFlagsEtc)
{
// safe to handle windows messages at this point (I think - JCWH)
CheckForWindowsMessages();
// get the filename
char szBuf[MAX_PATH];
if (!CL_GetImageFileName(szBuf,sizeof szBuf/sizeof szBuf[0],pszFileName,fFlagsEtc))
{
db_log1("CL_LoadImageOnce(): ERROR: unable to determine path of file");
return GEI_NOTLOADED;
}
db_logf4(("\tLoading '%s'",szBuf));
// already loaded ?
int iExistingImage = GetExistingImageNum(szBuf);
if (GEI_NOTLOADED != iExistingImage)
{
db_logf4(("\tImage already loaded to image number %d",iExistingImage));
return iExistingImage;
}
// what flags do we want?
unsigned fAwLoad = AW_TLF_DEFAULT;
if (fFlagsEtc & LIO_VIDMEM)
fAwLoad |= AW_TLF_VIDMEM;
if (fFlagsEtc & LIO_TRANSPARENT)
fAwLoad |= AW_TLF_TRANSP;
if (fFlagsEtc & LIO_CHROMAKEY)
fAwLoad |= AW_TLF_CHROMAKEY;
if (fFlagsEtc & LIO_LOADMIPMAPS)
db_log1("CL_LoadImageOnce(): WARNING: mip maps not supported yet - will not be created/loaded");
// what are we loading into ?
switch (fFlagsEtc & _LIO_SURFTYPEMASK)
{
case LIO_CHIMAGE:
{
db_log1("CL_LoadImageOnce(): WARNING: having to call LoadImageCH()");
IMAGEHEADER * pImageHdr = GetImageHeader();
db_assert1(pImageHdr);
memset(pImageHdr,0,sizeof(IMAGEHEADER));
if (LoadImageCH(szBuf,pImageHdr))
return NumImages-1;
else
{
db_log1("CL_LoadImageOnce(): ERROR: LoadImageCH() failed");
return GEI_NOTLOADED;
}
}
case LIO_DDSURFACE:
{
#if CL_SUPPORT_FASTFILE
unsigned nFastFileLen;
void const * pFastFileData = ffreadbuf(szBuf,&nFastFileLen);
if (pFastFileData)
{
db_log4("\tfile is in a fast file");
unsigned nWidth, nHeight;
AW_BACKUPTEXTUREHANDLE hBackup = NULL;
DDSurface * pSurface =
AwCreateSurface
(
fFlagsEtc & LIO_RESTORABLE ? "pxfXYB" : "pxfXY",
pFastFileData,
nFastFileLen,
fAwLoad,
&nWidth,
&nHeight,
&hBackup
);
if (pSurface)
{
IMAGEHEADER * pImageHdr = GetImageHeader();
db_assert1(pImageHdr);
memset(pImageHdr,0,sizeof(IMAGEHEADER));
pImageHdr->ImageWidth = nWidth;
pImageHdr->ImageHeight = nHeight;
db_assert1(sizeof pImageHdr->ImageName / sizeof pImageHdr->ImageName[0] > strlen(szBuf));
strcpy(pImageHdr->ImageName,szBuf);
pImageHdr->DDSurface = pSurface;
pImageHdr->hBackup = hBackup;
db_logf4(("\tloaded to image number %d",NumImages-1));
#if CL_SUPPORT_ALTTAB
if (fFlagsEtc & LIO_RESTORABLE)
#ifdef NDEBUG
ATIncludeSurface(pSurface,hBackup);
#else
{
char szDbInf[512];
sprintf(szDbInf,"Name \"%s\" Number %d",szBuf,NumImages-1);
ATIncludeSurfaceDb(pSurface,hBackup,szDbInf);
}
#endif
#endif // CL_SUPPORT_ALTTAB
return NumImages-1;
}
else
{
db_log1("CL_LoadImageOnce(): ERROR copying data to surface");
return GEI_NOTLOADED;
}
}
else
#endif // CL_SUPPORT_FASTFILE
{
#if !defined(CL_SUPPORTONLY_FASTFILE) || !CL_SUPPORTONLY_FASTFILE
db_log4("\tloading the actual file");
unsigned nWidth, nHeight;
AW_BACKUPTEXTUREHANDLE hBackup = NULL;
DDSurface * pSurface =
AwCreateSurface
(
fFlagsEtc & LIO_RESTORABLE ? "sfXYB" : "sfXY",
&szBuf[0],
fAwLoad,
&nWidth,
&nHeight,
&hBackup
);
if (pSurface)
{
IMAGEHEADER * pImageHdr = GetImageHeader();
db_assert1(pImageHdr);
memset(pImageHdr,0,sizeof(IMAGEHEADER));
pImageHdr->ImageWidth = nWidth;
pImageHdr->ImageHeight = nHeight;
db_assert1(sizeof pImageHdr->ImageName / sizeof pImageHdr->ImageName[0] > strlen(szBuf));
strcpy(pImageHdr->ImageName,szBuf);
pImageHdr->DDSurface = pSurface;
pImageHdr->hBackup = hBackup;
db_logf4(("\tloaded to image number %d",NumImages-1));
db_logf4(("\t\tsurface:%p",pSurface));
#if CL_SUPPORT_ALTTAB
if (fFlagsEtc & LIO_RESTORABLE)
#ifdef NDEBUG
ATIncludeSurface(pSurface,hBackup);
#else
{
char szDbInf[512];
sprintf(szDbInf,"Name \"%s\" Number %d",szBuf,NumImages-1);
ATIncludeSurfaceDb(pSurface,hBackup,szDbInf);
}
#endif
#endif // CL_SUPPORT_ALTTAB
return NumImages-1;
}
else
{
db_log1("CL_LoadImageOnce(): ERROR copying data to surface");
return GEI_NOTLOADED;
}
#elif !CL_SUPPORT_FASTFILE
#error "CL_SUPPORTONLY_FASTFILE set but CL_SUPPORT_FASTFILE not set"
#endif // !CL_SUPPORTONLY_FASTFILE
}
//db_msg1("THIS CODE SHOULD BE UNREACHABLE");
}
case LIO_D3DTEXTURE:
{
fAwLoad |= AW_TLF_COMPRESS; // required on some cards!!
#if CL_SUPPORT_FASTFILE
unsigned nFastFileLen;
void const * pFastFileData = ffreadbuf(szBuf,&nFastFileLen);
if (pFastFileData)
{
db_log4("\tfile is in a fast file");
unsigned nWidth, nHeight;
AW_BACKUPTEXTUREHANDLE hBackup = NULL;
D3DTexture * pTexture =
AwCreateTexture
(
fFlagsEtc & LIO_RESTORABLE ? "pxfWHB" : "pxfWH",
pFastFileData,
nFastFileLen,
fAwLoad,
&nWidth,
&nHeight,
&hBackup
);
if (pTexture)
{
IMAGEHEADER * pImageHdr = GetImageHeader();
db_assert1(pImageHdr);
memset(pImageHdr,0,sizeof(IMAGEHEADER));
pImageHdr->ImageWidth = nWidth;
pImageHdr->ImageHeight = nHeight;
db_assert1(sizeof pImageHdr->ImageName / sizeof pImageHdr->ImageName[0] > strlen(szBuf));
strcpy(pImageHdr->ImageName,szBuf);
pImageHdr->D3DTexture = pTexture;
pImageHdr->hBackup = hBackup;
db_logf4(("\tloaded to image number %d",NumImages-1));
/* KJL 16:05:50 26/02/98 - attempt to get a texture handle */
{
int gotTextureHandle = GetTextureHandle(pImageHdr);
db_assert1(gotTextureHandle==TRUE);
}
#if CL_SUPPORT_ALTTAB
if (fFlagsEtc & LIO_RESTORABLE)
#ifdef NDEBUG
ATIncludeTexture(pTexture,hBackup);
#else
{
char szDbInf[512];
sprintf(szDbInf,"Name \"%s\" Number %d",szBuf,NumImages-1);
ATIncludeTextureDb(pTexture,hBackup,szDbInf);
}
#endif
#endif // CL_SUPPORT_ALTTAB
return NumImages-1;
}
else
{
db_log1("CL_LoadImageOnce(): ERROR copying data to texture");
return GEI_NOTLOADED;
}
}
else
#endif // CL_SUPPORT_FASTFILE
{
#if !defined(CL_SUPPORTONLY_FASTFILE) || !CL_SUPPORTONLY_FASTFILE
db_log4("\tloading the actual file");
unsigned nWidth, nHeight;
AW_BACKUPTEXTUREHANDLE hBackup = NULL;
D3DTexture * pTexture =
AwCreateTexture
(
fFlagsEtc & LIO_RESTORABLE ? "sfWHB" : "sfWH",
&szBuf[0],
fAwLoad,
&nWidth,
&nHeight,
&hBackup
);
if (pTexture)
{
IMAGEHEADER * pImageHdr = GetImageHeader();
db_assert1(pImageHdr);
memset(pImageHdr,0,sizeof(IMAGEHEADER));
pImageHdr->ImageWidth = nWidth;
pImageHdr->ImageHeight = nHeight;
db_assert1(sizeof pImageHdr->ImageName / sizeof pImageHdr->ImageName[0] > strlen(szBuf));
strcpy(pImageHdr->ImageName,szBuf);
pImageHdr->D3DTexture = pTexture;
pImageHdr->hBackup = hBackup;
db_logf4(("\tloaded to image number %d",NumImages-1));
/* KJL 16:05:50 26/02/98 - attempt to get a texture handle */
{
int gotTextureHandle = GetTextureHandle(pImageHdr);
db_assert1(gotTextureHandle==TRUE);
}
#if CL_SUPPORT_ALTTAB
if (fFlagsEtc & LIO_RESTORABLE)
#ifdef NDEBUG
ATIncludeTexture(pTexture,hBackup);
#else
{
char szDbInf[512];
sprintf(szDbInf,"Name \"%s\" Number %d",szBuf,NumImages-1);
ATIncludeTextureDb(pTexture,hBackup,szDbInf);
}
#endif
#endif // CL_SUPPORT_ALTTAB
return NumImages-1;
}
else
{
db_log1("CL_LoadImageOnce(): ERROR copying data to texture");
return GEI_NOTLOADED;
}
#elif !CL_SUPPORT_FASTFILE
#error "CL_SUPPORTONLY_FASTFILE set but CL_SUPPORT_FASTFILE not set"
#endif // !CL_SUPPORTONLY_FASTFILE
}
//db_msg1("THIS CODE SHOULD BE UNREACHABLE");
}
default:
db_log1("CL_LoadImageOnce(): ERROR: Invalid destination surface specification");
return GEI_NOTLOADED;
}
}

70
src/win95/chnktexi.h Normal file
View file

@ -0,0 +1,70 @@
#ifndef _INCLUDED_CHNKTEXI_H_
#define _INCLUDED_CHNKTEXI_H_
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/* image number for already loaded image - really an internal function */
#define GEI_NOTLOADED (-1)
extern int GetExistingImageNum(char const * pszActualFileName);
enum /* flags, etc */
{
/* destination surface type */
LIO_CHIMAGE = 0x00000000U, /* Chris Humphries texture */
LIO_DDSURFACE = 0x00000001U, /* Direct Draw Surface */
LIO_D3DTEXTURE = 0x00000002U, /* Direct 3D Texture */
_LIO_SURFTYPEMASK= 0x00000003U,
/* target memory type for DDSURFACE only - D3DTextures dest depends on driver */
LIO_SYSMEM = 0x00000000U, /* system memory */
LIO_VIDMEM = 0x00000004U, /* video memory */
/* transparency flags - unless specified in the file */
LIO_NONTRANSP = 0x00000000U, /* no transparency */
LIO_TRANSPARENT = 0x00000008U, /* has transparency */
/* alpha or chroma key? */
LIO_USEALPHA = 0x00000000U, /* use alpha mask if available instead of chroma keying */
LIO_CHROMAKEY = 0x00000010U, /* use chroma key even if surface has alpha channel */
/* path flags */
LIO_ABSOLUTEPATH = 0x00000000U, /* path is correct */
LIO_RELATIVEPATH = 0x00000020U, /* path is relative to a textures directory */
LIO_RIFFPATH = 0x00000040U, /* current RIF file used to build path and extension */
_LIO_PATHTYPEMASK= 0x00000060U,
/* mip maps? */
LIO_NOMIPMAPS = 0x00000000U, /* no mip maps */
LIO_LOADMIPMAPS = 0x00000080U, /* load mip maps if available */
/* restorable ? */
LIO_NORESTORE = 0x00000000U, /* not going to be restorable */
LIO_RESTORABLE = 0x00000100U, /* put something in imageheader to allow restoring */
};
/* CL_LoadImageOnce relies on this value to be 1 greater
than the index of the last loaded image */
extern int NumImages;
/* directories used with the LIO_RIFFPATH flag */
extern char const * GameTex_Directory;
extern char const * SubShps_Directory;
extern char const * GenTex_Directory;
extern char const * FixTex_Directory;
extern char const * ToolsTex_Directory;
/* game mode for use with the above */
extern char const * cl_pszGameMode;
/* directories used with the LIO_RELATIVEPATH flag
these are searched in order*/
extern char const * FirstTex_Directory;
extern char const * SecondTex_Directory;
/* returns GEI_NOTLOADED on failure */
extern int CL_LoadImageOnce(char const * pszFileName, unsigned fFlagsEtc);
/* returns NULL on failure, or pointer to pszDestBuf on success, nBufSize includes nul terminator */
extern char * CL_GetImageFileName(char * pszDestBuf, unsigned nBufSize, char const * pszFileName, unsigned fFlagsEtc);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* !_INCLUDED_CHNKTEXI_H_ */

1221
src/win95/chnktype.cpp Normal file

File diff suppressed because it is too large Load diff

396
src/win95/chnktype.hpp Normal file
View file

@ -0,0 +1,396 @@
#ifndef _chnktype_hpp
#define _chnktype_hpp 1
#if engine
#include "3dc.h"
#endif
#include "list_tem.hpp"
struct ChunkVectorInt;
struct ChunkVectorFloat;
struct ChunkVector
{
double x;
double y;
double z;
ChunkVector friend operator+(const ChunkVector&, const ChunkVector&);
ChunkVector friend operator-(const ChunkVector&, const ChunkVector&);
ChunkVector& operator+=(const ChunkVector&);
ChunkVector& operator-=(const ChunkVector&);
ChunkVector friend operator*(const ChunkVector&, const double);
ChunkVector friend operator/(const ChunkVector&, const double);
ChunkVector friend operator*(const ChunkVector&, const ChunkVector&); //cross prod
#if engine
operator VECTORCH () const;
#endif
operator ChunkVectorInt () const;
operator ChunkVectorFloat () const;
friend double dot(const ChunkVector&, const ChunkVector&);//dot product
friend double mod(const ChunkVector&);//magnitude of vector
int norm(); //normalize
};
struct ChunkVectorInt
{
int x;
int y;
int z;
ChunkVectorInt friend operator+(const ChunkVectorInt&, const ChunkVectorInt&);
ChunkVectorInt friend operator-(const ChunkVectorInt&, const ChunkVectorInt&);
ChunkVectorInt& operator+=(const ChunkVectorInt&);
ChunkVectorInt& operator-=(const ChunkVectorInt&);
ChunkVectorInt friend operator*(const ChunkVectorInt&, const double);
ChunkVectorInt friend operator/(const ChunkVectorInt&, const double);
//ChunkVectorInt friend operator*(const ChunkVectorInt&, const ChunkVectorInt&); //cross prod
#if engine
operator VECTORCH () const;
#endif
//friend double dot(const ChunkVector&, const ChunkVector&);//dot product
friend double mod(const ChunkVectorInt&);//magnitude of vector
int norm(); //normalize to 65536
};
struct ChunkVectorFloat
{
float x;
float y;
float z;
ChunkVectorFloat friend operator+(const ChunkVectorFloat&, const ChunkVectorFloat&);
ChunkVectorFloat friend operator-(const ChunkVectorFloat&, const ChunkVectorFloat&);
ChunkVectorFloat& operator+=(const ChunkVectorFloat&);
ChunkVectorFloat& operator-=(const ChunkVectorFloat&);
ChunkVectorFloat friend operator*(const ChunkVectorFloat&, const double);
ChunkVectorFloat friend operator/(const ChunkVectorFloat&, const double);
//ChunkVectorInt friend operator*(const ChunkVectorInt&, const ChunkVectorInt&); //cross prod
#if engine
operator VECTORCH () const;
#endif
//friend double dot(const ChunkVector&, const ChunkVector&);//dot product
friend double mod(const ChunkVectorFloat&);//magnitude of vector
int norm(); //normalize to 1
};
struct ChunkUV
{
float u;
float v;
};
// in integers I suppose
struct ChunkMatrix
{
int mat11;
int mat12;
int mat13;
int mat21;
int mat22;
int mat23;
int mat31;
int mat32;
int mat33;
};
struct ChunkUV_List
{
int num_verts;
ChunkUV vert[4];
// for list iterator
friend BOOL operator== (const ChunkUV_List &, const ChunkUV_List &);
friend BOOL operator!= (const ChunkUV_List &, const ChunkUV_List &);
};
class ChunkPoly
{
public:
int engine_type;
int normal_index;
int flags;
unsigned int colour;
int num_verts;
int vert_ind[4];
//functions for gettings and setting texture and uv indeces in the colour
unsigned int GetUVIndex();
unsigned int GetTextureIndex();
void SetUVIndex(unsigned int uv_index);
void SetTextureIndex(unsigned int texture_index);
};
struct ChunkShape
{
ChunkShape();
~ChunkShape();
ChunkShape (const ChunkShape &);
ChunkShape& operator=(const ChunkShape &);
float radius; //radius of points about 0,0,0
ChunkVectorInt max;
ChunkVectorInt min;
ChunkVectorInt centre; //average of min and max
float radius_about_centre;
int num_verts;
ChunkVectorInt * v_list;
#if UseOldChunkLoader
ChunkVector * float_v_list;
#endif
//int num_vert_normals; //I don't think num_vert_normals is ever used
ChunkVectorFloat * v_normal_list;
int num_polys;
ChunkPoly * poly_list;
ChunkVectorFloat * p_normal_list;
int num_uvs;
ChunkUV_List * uv_list;
int num_texfiles;
char ** texture_fns;
void rescale (double);
};
struct ChunkQuat
{
float x,y,z,w;
};
struct ObjectID
{
int id1;
int id2;
friend BOOL operator== (const ObjectID &, const ObjectID &);
friend BOOL operator!= (const ObjectID &, const ObjectID &);
friend ObjectID Minimum(const ObjectID &,const ObjectID &);
};
struct ChunkObject
{
ChunkVectorInt location;
#if UseOldChunkLoader
ChunkVector float_location;
#endif
ChunkQuat orientation;
BOOL is_base_object;
char o_name[50];
int index_num; //this won't get changed by update_my_chunkobject
ObjectID ID;
};
struct VMod_Arr_Item
{
VMod_Arr_Item();
~VMod_Arr_Item();
VMod_Arr_Item(const VMod_Arr_Item & vma);
VMod_Arr_Item & operator=(const VMod_Arr_Item & vma);
int branch_no;
int flags;
int spare;
int object_index;
#if UseOldChunkLoader
char * o_name; //replaced by object_index
#endif
friend BOOL operator==(const VMod_Arr_Item &, const VMod_Arr_Item &);
friend BOOL operator!=(const VMod_Arr_Item &, const VMod_Arr_Item &);
};
struct Adjacent_Module
{
Adjacent_Module();
~Adjacent_Module();
Adjacent_Module(const Adjacent_Module & vma);
Adjacent_Module & operator=(const Adjacent_Module & vma);
int flags;
ChunkVectorInt entry_point;
int object_index;
#if UseOldChunkLoader
char * o_name;
#endif
friend BOOL operator==(const Adjacent_Module & am1, const Adjacent_Module & am2);
friend BOOL operator!=(const Adjacent_Module & am1, const Adjacent_Module & am2);
};
class Shape_Chunk;
class Shape_Sub_Shape_Chunk;
struct a_frame
{
a_frame()
: shape1a (0), shape1b(0), shape2a(0), shape2b(0)
{}
Shape_Sub_Shape_Chunk * shape1a;
Shape_Chunk * shape1b;
Shape_Sub_Shape_Chunk * shape2a;
Shape_Chunk * shape2b;
int spare;
};
// Data structures for bits and pieces
struct obinfile
{
int filepos;
char name[50];
size_t length;
friend BOOL operator==(const obinfile &o1, const obinfile &o2);
friend BOOL operator!=(const obinfile &o1, const obinfile &o2);
};
struct shpinfile
{
int filepos;
int id;
size_t length;
friend BOOL operator==(const shpinfile &s1, const shpinfile &s2);
friend BOOL operator!=(const shpinfile &s1, const shpinfile &s2);
};
struct poly_change_info
{
int poly_num;
int vert_num_before;
int vert_num_after;
friend BOOL operator==(poly_change_info const &f1, poly_change_info const &f2);
friend BOOL operator!=(poly_change_info const &f1, poly_change_info const &f2);
};
#define animframeflag_not_in_psx 0x00000001
#define animframeflag_not_in_saturn 0x00000002
#define animframeflag_interpolated_frame 0x00000004
struct ChunkAnimFrame
{
ChunkAnimFrame();
~ChunkAnimFrame();
ChunkAnimFrame(const ChunkAnimFrame &);
//constructor for interpolated frame
//ChunkAnimFrame(ChunkAnimFrame* startframe,ChunkAnimFrame* endframe,int startwt,int endwt,ChunkShape const *cs);
ChunkAnimFrame& operator=(const ChunkAnimFrame &);
char* name;
int num_polys;
int num_verts;
ChunkVectorInt * v_list;
ChunkVectorFloat * p_normal_list;
int flags;
int num_interp_frames;
int pad3,pad4;
};
#define animseqflag_not_in_psx 0x00000001
#define animseqflag_not_in_saturn 0x00000002
struct ChunkAnimSequence
{
ChunkAnimSequence();
~ChunkAnimSequence();
ChunkAnimSequence (const ChunkAnimSequence &);
ChunkAnimSequence& operator=(const ChunkAnimSequence &);
void DeleteInterpolatedFrames();
void GenerateInterpolatedFrames(ChunkShape const *cs);
void UpdateNormalsAndExtents(ChunkShape const *cs,List<int>* poly_not_in_bb=0);
int SequenceNum;
char* name;
int NumFrames;
ChunkAnimFrame** Frames;
int flags;
int pad2,pad3,pad4;
ChunkVectorInt min;
ChunkVectorInt max;
float radius;
int num_verts;
ChunkVectorFloat* v_normal_list;
};
#endif

599
src/win95/chunk.cpp Normal file
View file

@ -0,0 +1,599 @@
#include <string.h>
#include "chunk.hpp"
#if engine
#define UseLocalAssert No
#include "ourasert.h"
#define assert(x) GLOBALASSERT(x)
#else
#if cencon
#include "ccassert.h"
#else
#include <assert.h>
#endif
#endif
#if cencon
#include "environs.hpp"
#else
#define twprintf printf
#ifdef cencon
#define new my_new
#endif
char * users_name = "Player";
#endif
#include "hash_tem.hpp"
Chunk * Parent_File;
// Non class functions ( only one as yet )
void list_chunks_in_file(List<int> * pList, HANDLE hand, char const * chunk_id)
{
unsigned long bytes_read;
char buffer[8];
BOOL ok = TRUE;
while (pList->size())
pList->delete_first_entry();
// assuming we start at the front of a parent chunk,
// containing the child chunk specified
int init_file_pos = SetFilePointer (hand,0,0,FILE_CURRENT);
int file_pos;
int file_length = GetFileSize(hand, 0);
SetFilePointer (hand,8,0,FILE_CURRENT);
int chunk_length;
int sub_chunk_ln;
ReadFile (hand, (long *) &chunk_length, 4, &bytes_read, 0);
if ((init_file_pos + chunk_length) > file_length) return;
while ((file_pos = SetFilePointer (hand,0,0,FILE_CURRENT))
< (init_file_pos + chunk_length) && ok) {
ok = ReadFile (hand, (long *) buffer, 8, &bytes_read, 0);
if (strncmp(buffer, chunk_id, 8) == 0)
pList->add_entry(file_pos);
ok = ReadFile (hand, (long *) &sub_chunk_ln, 4, &bytes_read, 0);
SetFilePointer (hand,sub_chunk_ln-12,0,FILE_CURRENT);
}
}
#ifndef RIFF_OPTIMIZE
List<int> list_chunks_in_file (HANDLE & hand, const char * chunk_id)
{
List<int> chunk_list;
list_chunks_in_file(&chunk_list, hand, chunk_id);
return chunk_list;
}
#endif
//////////////////////////////////////////////
// Class Chunk functions
Chunk::~Chunk()
{
if (parent) {
if (parent->children == this) {
parent->children = next;
if (next)
next->previous = previous;
}
else {
if (previous)
previous->next = next;
if (next)
next->previous = previous;
}
}
}
Chunk::Chunk(Chunk_With_Children * _parent, const char * _identifier)
: error_code(0)
{
strncpy (identifier_store, _identifier, 8);
identifier_store[8] = 0;
identifier = identifier_store;
parent = _parent;
next = NULL;
previous = NULL;
if (parent){
if (parent->children) {
Chunk * pTail = parent->children;
while (pTail->next)
pTail = pTail->next;
pTail->next = this;
previous = pTail;
}
else
parent->children = this;
}
}
BOOL Chunk::output_chunk (HANDLE & hand)
{
unsigned long junk;
BOOL ok;
char * data_block;
data_block = make_data_block_from_chunk();
if (data_block)
{
ok = WriteFile (hand, (long *) data_block, (unsigned long) chunk_size, &junk, 0);
delete [] data_block;
if (!ok) return FALSE;
}
else if (chunk_size)
{
return(FALSE);
}
return TRUE;
}
char * Chunk::make_data_block_from_chunk ()
{
char * data_block;
size_t block_size;
block_size = size_chunk();
if (!chunk_size)
{
return(0);
}
data_block = new char [block_size];
this->fill_data_block(data_block);
return data_block;
}
char * Chunk::make_data_block_for_process ()
{
char * data_block;
size_t block_size;
block_size = size_chunk_for_process();
if (!chunk_size)
{
return(0);
}
data_block = new char [block_size];
fill_data_block_for_process(data_block);
return data_block;
}
size_t Chunk::size_chunk_for_process()
{
return size_chunk();
}
void Chunk::fill_data_block_for_process(char * data_start)
{
fill_data_block(data_start);
}
Chunk_With_Children * Chunk::GetRootChunk(void)
{
Chunk * retp = this;
while (retp->parent) retp = retp->parent;
return (Chunk_With_Children *) retp;
}
Chunk_With_Children const * Chunk::GetRootChunk(void) const
{
Chunk const * retp = this;
while (retp->parent) retp = retp->parent;
return (Chunk_With_Children const *) retp;
}
///////////////////////////////////////
// Class Miscellaneous_Chunk functions
Miscellaneous_Chunk::Miscellaneous_Chunk (Chunk_With_Children * parent, const char * identifier,
const char * _data, size_t _data_size)
: Chunk (parent, identifier),
data(NULL), data_size (_data_size)
{
if (data_size)
{
data_store = new char [data_size];
*((char **) &data) = data_store;
for (int i = 0; i < (signed)data_size; i++)
data_store[i] = _data[i];
}
else
{
data_store = NULL;
}
}
void Miscellaneous_Chunk::fill_data_block (char * data_start)
{
strncpy (data_start, identifier, 8);
data_start += 8;
*((int *) data_start) = chunk_size;
data_start += 4;
for (int i = 0; i<(signed)(chunk_size-12); i++)
data_start[i] = data[i];
}
Miscellaneous_Chunk::~Miscellaneous_Chunk ()
{
delete [] data_store;
}
///////////////////////////////////////
// Class Chunk_With_Children functions
Chunk_With_Children::~Chunk_With_Children()
{
while (children)
delete children;
}
size_t Chunk_With_Children::size_chunk ()
{
Chunk * child_ptr = children;
chunk_size = 12; // identifier + length
if (children)
while (child_ptr != NULL) {
chunk_size += child_ptr->size_chunk();
child_ptr = child_ptr->next;
}
return chunk_size;
}
BOOL Chunk_With_Children::output_chunk (HANDLE &hand)
{
unsigned long junk;
Chunk * child_ptr = children;
BOOL ok;
ok = WriteFile (hand, (long *) identifier, 8, &junk, 0);
if (!ok) return FALSE;
ok = WriteFile (hand, (long *) &chunk_size, 4, &junk, 0);
if (!ok) return FALSE;
if (children)
while (child_ptr != NULL && ok){
ok = child_ptr->output_chunk(hand);
child_ptr = child_ptr->next;
}
if (!ok) return FALSE;
return TRUE;
}
size_t Chunk_With_Children::size_chunk_for_process()
{
Chunk * child_ptr = children;
chunk_size = 12; // identifier + length
if (children)
while (child_ptr != NULL) {
chunk_size += child_ptr->size_chunk_for_process();
child_ptr = child_ptr->next;
}
return chunk_size;
}
void Chunk_With_Children::fill_data_block_for_process(char * data_start)
{
strncpy (data_start, identifier, 8);
data_start += 8;
*((int *) data_start) = chunk_size;
data_start += 4;
Chunk * child_ptr = children;
if (children)
while (child_ptr != NULL) {
child_ptr->fill_data_block_for_process (data_start);
data_start += child_ptr->chunk_size;
child_ptr = child_ptr->next;
}
}
void Chunk_With_Children::fill_data_block(char * data_start)
{
strncpy (data_start, identifier, 8);
data_start += 8;
*((int *) data_start) = chunk_size;
data_start += 4;
Chunk * child_ptr = children;
if (children)
while (child_ptr != NULL) {
child_ptr->fill_data_block (data_start);
data_start += child_ptr->chunk_size;
child_ptr = child_ptr->next;
}
}
#ifndef RIFF_OPTIMIZE
List<Chunk *> Chunk_With_Children::lookup_child (const char * class_ident) const
{
List<Chunk *> child_list;
lookup_child(class_ident,child_list);
return child_list;
}
#endif
void Chunk_With_Children::lookup_child (const char * class_ident,List<Chunk*>& child_list) const
{
//make sure the list is empty first
while(child_list.size())
{
child_list.delete_first_entry();
}
Chunk * child_ptr = children;
if (children)
while (child_ptr != NULL) {
if (strncmp (class_ident, child_ptr->identifier, 8) == NULL)
{
assert (!child_ptr->r_u_miscellaneous());
child_list.add_entry(child_ptr);
}
child_ptr = child_ptr->next;
}
}
unsigned Chunk_With_Children::count_children (char const * class_ident) const
{
unsigned nChildren = 0;
Chunk * child_ptr = children;
if (children)
while (child_ptr != NULL) {
if (strncmp (class_ident, child_ptr->identifier, 8) == NULL)
{
assert (!child_ptr->r_u_miscellaneous());
++ nChildren;
}
child_ptr = child_ptr->next;
}
return nChildren;
}
Chunk* Chunk_With_Children::lookup_single_child (const char * class_ident) const
{
#if debug
//if debug make sure there is at most one of the required chunk type
Chunk * child_ptr = children;
Chunk * chunk_found=0;
if (children)
while (child_ptr != NULL) {
if (strncmp (class_ident, child_ptr->identifier, 8) == NULL)
{
assert (!child_ptr->r_u_miscellaneous());
assert(!chunk_found);
chunk_found=child_ptr;
}
child_ptr = child_ptr->next;
}
return chunk_found;
#else
Chunk * child_ptr = children;
if (children)
while (child_ptr != NULL) {
if (strncmp (class_ident, child_ptr->identifier, 8) == NULL)
{
assert (!child_ptr->r_u_miscellaneous());
return child_ptr;
}
child_ptr = child_ptr->next;
}
return 0;
#endif
}
void Chunk_With_Children::prepare_for_output()
{
Chunk * child_ptr = children;
if (children)
while (child_ptr != NULL){
child_ptr->prepare_for_output ();
child_ptr = child_ptr->next;
}
}
void Chunk_With_Children::post_input_processing()
{
Chunk * child_ptr = children;
if (children)
while (child_ptr != NULL){
child_ptr->post_input_processing ();
child_ptr = child_ptr->next;
}
}
///////////////////////////////////////////////////
//Chunk registering stuff
class RifRegEntry
{
public:
int chunk_id_1;
int chunk_id_2;
int parent_id_1;
int parent_id_2;
Chunk * (* m_pfnCreate) (Chunk_With_Children* parent,const char* data);
/*
For two members of this class to be considered similar there chunk_is members must match.
If both parent_id members are zero for one of the objects being compared , then they are considered
equal regardless of the parent_id members of the other object.
Otherwise the parent_id members of the two objects must match.
(This is done because not all of the constructors insist on a given parent)
*/
inline bool operator == (RifRegEntry const & rEntry) const
{
if(chunk_id_1 != rEntry.chunk_id_1 || chunk_id_2 != rEntry.chunk_id_2) return FALSE;
if(parent_id_1 == 0 && parent_id_2 == 0) return TRUE;
if(rEntry.parent_id_1 == 0 && rEntry.parent_id_2 == 0) return TRUE;
return parent_id_1 == rEntry.parent_id_1 && parent_id_2 == rEntry.parent_id_2;
}
inline bool operator != (RifRegEntry const & rEntry) const
{
return ! operator == (rEntry);
}
};
inline unsigned HashFunction(RifRegEntry const & rEntry)
{
return HashFunction(rEntry.chunk_id_1 + rEntry.chunk_id_2);
}
static HashTable<RifRegEntry> * g_pRifRegister = NULL;
void Chunk::Register(const char* idChunk,const char* idParent, Chunk * (* pfnCreate) (Chunk_With_Children* parent,const char* data) )
{
static HashTable<RifRegEntry> reg;
char temp_id[8];
g_pRifRegister = &reg;
RifRegEntry entry;
strncpy(temp_id,idChunk,8);
entry.chunk_id_1 = *(int*) &temp_id[0];
entry.chunk_id_2 = *(int*) &temp_id[4];
entry.m_pfnCreate = pfnCreate;
if(idParent)
{
strncpy(temp_id,idParent,8);
entry.parent_id_1 = *(int*) &temp_id[0];
entry.parent_id_2 = *(int*) &temp_id[4];
}
else
{
entry.parent_id_1 = 0;
entry.parent_id_2 = 0;
}
reg.AddAsserted(entry);
}
Chunk* Chunk_With_Children::DynCreate(const char* data)
{
/*
Look in hash tables for a constructor for this block
If none exists , create a Miscellaneous_Chunk
*/
if (g_pRifRegister)
{
RifRegEntry test;
test.chunk_id_1 = *(int*) data;
test.chunk_id_2 = *(int*) &data[4];
test.parent_id_1 = *(int*) identifier;
test.parent_id_2 = *(int*) &identifier[4];
test.m_pfnCreate = NULL;
RifRegEntry const * pEntry = g_pRifRegister->Contains(test);
if (pEntry)
{
return pEntry->m_pfnCreate(this,data);
}
}
return new Miscellaneous_Chunk(this,data,(data + 12), (*(int *) (data + 8))-12);
}

687
src/win95/chunk.hpp Normal file
View file

@ -0,0 +1,687 @@
// Chunk library
#ifndef _chunk_hpp
#define _chunk_hpp 1
#if engine
#include "3dc.h"
#include "mem3dc.h" // for debug new and delete
#include "inline.h"
#if SupportModules
#include "module.h"
#endif
#include "list_tem.hpp"
#endif
#if cencon
#include "AFXWIN.H"
#ifdef _DEBUG
#undef new
#define new DEBUG_NEW
#define my_new DEBUG_NEW
#else
#define my_new new
#endif
#include "list_tem.hpp"
#endif
#if objedit || sprite_edit || ANIMEXP
#include "StdAfx.h"
#include "list_tem.hpp"
#endif
#if shpedit
#include "stdafx.h"
#include "list_tem.hpp"
#endif
#if standard
#include "advwin32.h"
#include <windows.h>
#include "list_tem.hpp"
#endif
#define CHUNK_FAILED_ON_LOAD -1
#define CHUNK_FAILED_ON_LOAD_NOT_RECOGNISED -2
#define CHUNK_FAILED_ON_WRITE -3
#define CHECK_FAILED_NOT_OPEN -4
#define DisableLock 1
#define GENERAL_FLAG_LOCKED 0x0000001
// Non class functions ( only one as yet )
// The function will return a list of file pointers
// for the starting position of each chunk within a chunk
// File pointers are offset from the start of the file.
// we start at the header of the chunk we are in
// so that we can stop at the end of the chunk
#if cencon
extern char users_name[];
#endif
#ifndef RIFF_OPTIMIZE // define this to get compiler errors where you are calling the old slow functions
extern List<int> list_chunks_in_file (HANDLE &, const char * chunk_id);
#endif
extern void list_chunks_in_file (List<int> * pList, HANDLE, const char * chunk_id);
// Structures for interfacing with the outside application
// these are going to be basically very C-ee so that C
// functions can also read them
// The basic chunk class structure is as follows
//
// Base_Chunk
// | |
// Chunk_With_Children Data Chunks
// |
// File_Chunk
//
// Most chunk classes are either derived from the Chunk
// class or the Chunk_With_Children class.
// A chunk with data is derived from the Chunk class as follows
// class Sample_Data_Chunk : public Chunk
// {
// public:
//
// // Constructors are placed either here or may be private
// // The constructors for most shape data chunks are private
// // as only the Shape_Chunk can call them. This is because
// // the shape chunk deals with the data.
// //
// // Any constuctor should initialise class chunk with the
// // correct identifier for the current chunk.
// //
// // There are normally two constructors - one for constructing
// // from interface data one for constructing from raw data.
// //
// // A destructor can also be placed here or may not be needed
// //
// // Any variables that are made available for the user should also
// // be placed here.
// //
// // The next three functions are vital for the io functions
// //
// virtual BOOL output_chunk (HANDLE &hand);
// // This function will write the chunk data to the file specified
// // by the windows file handle - hand.
// //
// virtual size_t size_chunk ();
// // This function will return the size of the chunk (including the header).
// // IT MUST SET the variable chunk_size to the size it returns
// //
// virtual fill_data_block (char * data_start);
// // This function will fill a data block with data. The data will be
// // the same as the file data. The data is assumed to be pre-allocated
// // with the size given by the size_chunk function.
// //
// }
// A chunk with children is derived from the Chunk_With_Children class
// as follows
//
// class Sample_Chunk_With_Children : public Chunk
// {
// public:
//
// // Constructors may be used to construct child chunks from
// // interface data. A parsing constructor should be used for
// // constructing from raw data (look at Shape_Chunk).
// //
// // Any constructor should initialise class Chunk_With_Children with
// // the correct identifier for the current chunk.
// //
// // The Destructor does not need to destroy child chunks as the
// // Chunk_With_Children destructor will automatically do this.
// //
// // The three functions (size_chunk, output_chunk and fill_data_block)
// // are not needed as Chunk_With_Children can deal with these - but may
// // be put in.
// //
// }
//
//
// The logic behind the locking is as follows.
// There are two functions for locking and unlocking chunks
// these are currently only in the shape and object chunks
// lock_chunk(File_Chunk &)
// will lock a chunk, this must only be called once
// and will return false if it tries to lock a chunk
// that has already been locked by anyone.
// unlock_chunk (File_Chunk &, BOOL updatedyn)
// will unlock the chunk locally and in the file if it is not to be updated
// If it is to be updated, it will set the updated flag and
// the chunk can only be locked again once it is written to a file.
// The user may call File_Chunk::update_file() whenever
// (either after every chunk update, or once a minute)
// Note that this fully unlocks locally locked chunks
// that are being written to the file.
// Another function File_Chunk::update_chunks_from_file()
// will reload those chunks that have been externally upadted
// This must be done with care!!
// The objects are associated with shapes primarily
// When a shape is being edited, a list of objects will
// be with that shape in the header. These objects will be locked
// also.
///////////////////////////////////////////////
class Chunk
{
public:
//destructor
virtual ~Chunk ();
// constructors
Chunk (class Chunk_With_Children * parent, const char * ident);
virtual size_t size_chunk () = 0;
virtual BOOL output_chunk (HANDLE &);
virtual void fill_data_block (char * data_start) = 0;
// this function is virtual, but will probably not be used elsewhere
virtual char * make_data_block_from_chunk ();
// Selective output functions, these are similar to the normal ones
// and will normally call the equivalents.
// special chunks will have there own functions which will only respond
// if they have a flag set
virtual char * make_data_block_for_process();
virtual size_t size_chunk_for_process();
virtual void fill_data_block_for_process(char * data_start);
// these functions are virtual, but will only be used sparingly
virtual void prepare_for_output()
{}
virtual void post_input_processing()
{}
const char * identifier;
int error_code;
// this allows chunks with children to trap miscellaneous chunks
// that shouldn't be miscellaneous !!!
virtual BOOL r_u_miscellaneous()
{ return FALSE; }
static void Register(const char* idChunk,const char* idParent ,Chunk * (* pfnCreate) (Chunk_With_Children* parent,const char* data) );
private:
// copy - private to stop chunks
// from being copied
Chunk (const Chunk &);
// ditto
void operator=(const Chunk &);
// pointers to siblings
friend class Chunk_With_Children;
friend class Sprite_Header_Chunk; // sprite updating needs to scan through all child chunks
friend class File_Chunk;
friend class RIF_File_Chunk;
friend class Shape_Chunk;
Chunk * next;
Chunk * previous;
// identifier store
char identifier_store[9];
protected:
size_t chunk_size;
// pointer to parent
class Chunk_With_Children * parent;
public :
class Chunk_With_Children * GetRootChunk(void);
class Chunk_With_Children const * GetRootChunk(void) const;
};
///////////////////////////////////////////////
class Miscellaneous_Chunk : public Chunk
{
public:
Miscellaneous_Chunk (Chunk_With_Children * parent, const char * identifier,
const char * _data, size_t _data_size);
virtual ~Miscellaneous_Chunk ();
virtual size_t size_chunk ()
{
return (chunk_size = (data_size + 12));
}
virtual void fill_data_block (char * data_start);
const size_t data_size;
const char * const data;
// this allows chunks with children to trap miscellaneous chunks
// that shouldn't be miscellaneous !!!
virtual BOOL r_u_miscellaneous()
{ return TRUE; }
private:
char * data_store;
};
///////////////////////////////////////////////
class Chunk_With_Children : public Chunk
{
public:
virtual ~Chunk_With_Children();
Chunk_With_Children (Chunk_With_Children * parent, const char * identifier)
: Chunk (parent, identifier), children (NULL) {}
virtual size_t size_chunk ();
virtual BOOL output_chunk (HANDLE &);
virtual void fill_data_block (char * data_start);
virtual void prepare_for_output();
virtual void post_input_processing();
// look for child chunk(s)
#ifndef RIFF_OPTIMIZE // define this to get compiler errors where you are calling the old slow functions
List<Chunk *> lookup_child (const char *) const;
#endif
void lookup_child (const char *,List<Chunk*>&) const;
Chunk* lookup_single_child(const char*) const;
unsigned count_children(char const *) const;
// Selective output functions, these are similar to the normal ones
// and will normally call the equivalents.
// special chunks will have there own functions which will only respond
// if they have a flag set
virtual size_t size_chunk_for_process();
virtual void fill_data_block_for_process(char * data_start);
Chunk* Chunk_With_Children::DynCreate(const char* data);
protected:
friend class Chunk;
friend class File_Chunk;
// points to a doubly linked list
Chunk * children;
};
/////////////////////////////////////////////
// macros to save typing for chunk with children loader
extern Chunk * Parent_File;
#define CHUNK_WITH_CHILDREN_LOADER_PARENT __parent
#define CHUNK_WITH_CHILDREN_LOADER_INIT_PT1(id,chunkclass) \
chunkclass::chunkclass(Chunk_With_Children * const CHUNK_WITH_CHILDREN_LOADER_PARENT, char const * __data, size_t const __size) \
:Chunk_With_Children(CHUNK_WITH_CHILDREN_LOADER_PARENT,id)
#define CHUNK_WITH_CHILDREN_LOADER_INIT_PT2 { \
const char * const __buffer_ptr = __data; \
while (__data - __buffer_ptr < (signed)__size){ \
if (*(int *)(__data + 8) + (__data-__buffer_ptr) > (signed)__size){ \
Parent_File->error_code = CHUNK_FAILED_ON_LOAD_NOT_RECOGNISED; \
break;}
#define LOCKABLE_CHUNK_WITH_CHILDREN_LOADER_INIT_PT1(id,chunkclass) \
chunkclass::chunkclass(Chunk_With_Children * const CHUNK_WITH_CHILDREN_LOADER_PARENT, char const * __data, size_t const __size) \
:Lockable_Chunk_With_Children(CHUNK_WITH_CHILDREN_LOADER_PARENT,id)
#define LOCKABLE_CHUNK_WITH_CHILDREN_LOADER_INIT_PT2 { \
const char * const __buffer_ptr = __data; \
while (__data - __buffer_ptr < (signed) __size){ \
if (*(int *)(__data + 8) + (__data-__buffer_ptr) > (signed) __size){ \
Parent_File->error_code = CHUNK_FAILED_ON_LOAD_NOT_RECOGNISED; \
break;}
#define CHUNK_WITH_CHILDREN_LOADER_INIT(id,chunkclass) \
CHUNK_WITH_CHILDREN_LOADER_INIT_PT1(id,chunkclass) \
CHUNK_WITH_CHILDREN_LOADER_INIT_PT2
#define LOCKABLE_CHUNK_WITH_CHILDREN_LOADER_INIT(id,chunkclass) \
LOCKABLE_CHUNK_WITH_CHILDREN_LOADER_INIT_PT1(id,chunkclass) \
LOCKABLE_CHUNK_WITH_CHILDREN_LOADER_INIT_PT2
#define CHUNK_WITH_CHILDREN_LOADER_FOR(id,chunkclass) \
else if (!strncmp(__data,id,8)){ \
new chunkclass(this,__data+12,*(int *)(__data+8)-12); \
__data += *(int *)(__data+8);}
#define CHUNK_WITH_CHILDREN_LOADER_END \
else { \
new Miscellaneous_Chunk (this, __data, (__data + 12), (*(int *) (__data + 8)) -12 ); \
__data += *(int *)(__data + 8);}}}
// example:
//
// CHUNK_WITH_CHILDREN_LOADER_INIT("GAMEMODE",Environment_Game_Mode_Chunk)
// CHUNK_WITH_CHILDREN_LOADER_FOR("ENVPALET",Environment_Palette_Chunk)
// CHUNK_WITH_CHILDREN_LOADER_FOR("ENVTXLIT",Environment_TLT_Chunk)
// CHUNK_WITH_CHILDREN_LOADER_FOR("CLRLOOKP",Coloured_Polygons_Lookup_Chunk)
// CHUNK_WITH_CHILDREN_LOADER_FOR("RIFCHILD",RIF_Name_Chunk)
// CHUNK_WITH_CHILDREN_LOADER_END
///////////////////////////////////////////////
//macros for use in chunk construction from buffer, assume buffer is called data
//read variable of type 'type'
#define CHUNK_EXTRACT(var,type) \
var=*(type*)data; \
data+=sizeof(type);
//read 4 byte aligned string
#define CHUNK_EXTRACT_STRING(var) { \
int __length=strlen(data); \
if(__length) \
{ \
var=new char[__length+1]; \
strcpy(var,data); \
} \
else var=0; \
data+=(__length+4) &~3 ;}
//read array
//length is an int (filled in by macro)
//pointer is a pointer of type 'type'
#define CHUNK_EXTRACT_ARRAY(length,pointer,type){\
CHUNK_EXTRACT(length,int) \
if(length) \
{ \
pointer=new type[length]; \
for(int __i=0;__i<length;__i++) \
{ \
CHUNK_EXTRACT(pointer[__i],type) \
} \
} \
else pointer=0;}
//macros for use in fill_data_block
#define CHUNK_FILL_START \
strncpy (data, identifier, 8); \
data += 8; \
*(int *) data = chunk_size; \
data += 4;
//write variable of type 'type'
#define CHUNK_FILL(var,type) \
*(type*)data=var; \
data+=sizeof(type);
//write 4 byte aligned string
#define CHUNK_FILL_STRING(var) \
if(var) strcpy(data,var); \
else *data=0; \
data+=(strlen(data)+4)&~3;
#define CHUNK_FILL_ARRAY(length,pointer,type){\
CHUNK_FILL(length,int) \
for(int __i=0;__i<length;__i++) \
{ \
CHUNK_FILL(pointer[__i],type); \
} \
}
//macros for use in size_chunk
#define CHUNK_SIZE_START \
chunk_size = 12
//size of variable of type 'type'
#define CHUNK_SIZE(var,type) \
+ sizeof(type)
//size of 4 byte aligned string
#define CHUNK_SIZE_STRING(string) \
+ (string ? (strlen(string)+4)&~3 : 4)
#define CHUNK_SIZE_ARRAY(length,pointer,type) \
+ sizeof(int) \
+ (length * sizeof(type))
#define CHUNK_SIZE_END ;
///////////////////////////////////////////////
class GodFather_Chunk : public Chunk_With_Children
{
public:
GodFather_Chunk ()
: Chunk_With_Children (NULL, "REBINFF2")
{}
GodFather_Chunk (char * buffer, size_t size);
};
///////////////////////////////////////////////
/*
Macro for adding chunk class to list of that can be created using DynCreate
Chunks registered this way can be created as a child of any chunk
*/
#define RIF_IMPLEMENT_DYNCREATE(idChunk,tokenClassName) _RIF_IMPLEMENT_DYNCREATE_LINE_EX(idChunk,tokenClassName,__LINE__)
#define _RIF_IMPLEMENT_DYNCREATE_LINE_EX(idChunk,tokenClassName,nLine) _RIF_IMPLEMENT_DYNCREATE_LINE(idChunk,tokenClassName,nLine)
#define _RIF_IMPLEMENT_DYNCREATE_LINE(idChunk,tokenClassName,nLine) \
static Chunk * RifCreateClassObject ## tokenClassName ##_## nLine (Chunk_With_Children* parent,const char* data) { \
Chunk * pChunk = new tokenClassName(parent,data+12,(*(int *) (data + 8))-12); \
return pChunk; \
} \
class RegisterRifChunkClass ## tokenClassName ##_## nLine { \
public: RegisterRifChunkClass ## tokenClassName ##_## nLine () { \
Chunk::Register(idChunk ,0,RifCreateClassObject ## tokenClassName ##_## nLine); \
} \
} rifcc ## tokenClassName ##_## nLine;
/*
Macro for adding chunk class to list of that can be created using DynCreate.
Chunks registered this way will only be created as children of the parent named
*/
#define RIF_IMPLEMENT_DYNCREATE_DECLARE_PARENT(idChunk,tokenClassName,idParent,parentClassName) _RIF_IMPLEMENT_DYNCREATE_PARENT_LINE_EX(idChunk,tokenClassName,idParent,parentClassName,__LINE__)
#define _RIF_IMPLEMENT_DYNCREATE_PARENT_LINE_EX(idChunk,tokenClassName,idParent,parentClassName,nLine) _RIF_IMPLEMENT_DYNCREATE_PARENT_LINE(idChunk,tokenClassName,idParent,parentClassName,nLine)
#define _RIF_IMPLEMENT_DYNCREATE_PARENT_LINE(idChunk,tokenClassName,idParent,parentClassName,nLine) \
static Chunk * RifCreateClassObject ## tokenClassName ##_## nLine (Chunk_With_Children* parent,const char* data) { \
Chunk * pChunk = new tokenClassName((parentClassName*)parent,data+12,(*(int *) (data + 8))-12); \
return pChunk; \
} \
class RegisterRifChunkClass ## tokenClassName ##_## nLine { \
public: RegisterRifChunkClass ## tokenClassName ##_## nLine () { \
Chunk::Register(idChunk ,idParent,RifCreateClassObject ## tokenClassName ##_## nLine); \
} \
} rifcc ## tokenClassName ##_## nLine;
/*
Load from buffer function for standard Chunk_With_Children
*/
#define CHUNK_WITH_CHILDREN_LOADER(id,chunk_class) \
chunk_class::chunk_class(Chunk_With_Children * const parent,char const * __data, size_t const __size)\
:Chunk_With_Children(parent,id)\
{\
const char * __buffer_ptr = __data;\
while ((__data-__buffer_ptr)< (signed) __size) {\
if ((*(int *)(__data + 8)) + (__data-__buffer_ptr) > (signed) __size) {\
Parent_File->error_code = CHUNK_FAILED_ON_LOAD_NOT_RECOGNISED;\
break;\
}\
\
DynCreate(__data);\
__data += *(int *)(__data + 8);\
}\
}
/*
Load from buffer function for standard Lockable_Chunk_With_Children
*/
#define LOCKABLE_CHUNK_WITH_CHILDREN_LOADER(id,chunk_class) \
chunk_class::chunk_class(Chunk_With_Children * const parent,char const * __data, size_t const __size)\
:Lockable_Chunk_With_Children(parent,id)\
{\
const char * __buffer_ptr = __data;\
while ((__data-__buffer_ptr)< (signed) __size) {\
if ((*(int *)(__data + 8)) + (__data-__buffer_ptr) > (signed) __size) {\
Parent_File->error_code = CHUNK_FAILED_ON_LOAD_NOT_RECOGNISED;\
break;\
}\
\
DynCreate(__data);\
__data += *(int *)(__data + 8);\
}\
}
//macros for forcing inclusion of chunk files from a library
#define FORCE_CHUNK_INCLUDE_START //not needed anymore
#define FORCE_CHUNK_INCLUDE(filename)\
extern int __Chunk_Include_##filename;\
int* p__Chunk_Include_##filename =& __Chunk_Include_##filename;
#define FORCE_CHUNK_INCLUDE_END //not needed anymore
#define FORCE_CHUNK_INCLUDE_IMPLEMENT(filename) int __Chunk_Include_##filename;
/*
//eg.
FORCE_CHUNK_INCLUDE_START
FORCE_CHUNK_INCLUDE(mishchnk)
FORCE_CHUNK_INCLUDE(shpchunk)
FORCE_CHUNK_INCLUDE(obchunk)
FORCE_CHUNK_INCLUDE(envchunk)
FORCE_CHUNK_INCLUDE(animchnk)
FORCE_CHUNK_INCLUDE(hierchnk)
FORCE_CHUNK_INCLUDE(animobs)
FORCE_CHUNK_INCLUDE(sndchunk)
FORCE_CHUNK_INCLUDE(avpchunk)
FORCE_CHUNK_INCLUDE(bmpnames)
FORCE_CHUNK_INCLUDE(chunkpal)
FORCE_CHUNK_INCLUDE(dummyobjectchunk)
FORCE_CHUNK_INCLUDE(enumchnk)
FORCE_CHUNK_INCLUDE(enumsch)
FORCE_CHUNK_INCLUDE(fragchnk)
FORCE_CHUNK_INCLUDE(gsprchnk)
FORCE_CHUNK_INCLUDE(hierplace)
FORCE_CHUNK_INCLUDE(ltchunk)
FORCE_CHUNK_INCLUDE(oechunk)
FORCE_CHUNK_INCLUDE(pathchnk)
FORCE_CHUNK_INCLUDE(sprchunk)
FORCE_CHUNK_INCLUDE(strachnk)
FORCE_CHUNK_INCLUDE(toolchnk)
FORCE_CHUNK_INCLUDE(wpchunk)
FORCE_CHUNK_INCLUDE_END
*/
#endif // !included

1007
src/win95/chunkpal.cpp Normal file

File diff suppressed because it is too large Load diff

1044
src/win95/chunkpal.hpp Normal file

File diff suppressed because it is too large Load diff

34
src/win95/cl_init.cpp Normal file
View file

@ -0,0 +1,34 @@
#include "cl_init.h"
#include "system.h" // because the 3dc header files don't automatically include the ones they need
#include "equates.h" // because the 3dc header files don't automatically include the ones they need
#include "platform.h" // for VideoModeTypes
#include "shape.h" // because the 3dc header files don't automatically include the ones they need
#include "prototyp.h" // for SDB
#include "d3_image.hpp" // for init functions
extern "C" extern SCREENDESCRIPTORBLOCK ScreenDescriptorBlock;
void CL_Init_All(void)
{
switch (VideoModeTypeScreen)
{
case VideoModeType_8:
if (ScreenDescriptorBlock.SDB_Flags & SDB_Flag_TLTPalette)
CL_Init_DirectDrawMode(CLV_8TLT);
else
CL_Init_DirectDrawMode(CLV_8);
break;
case VideoModeType_15:
CL_Init_DirectDrawMode(CLV_15);
break;
case VideoModeType_24:
CL_Init_DirectDrawMode(CLV_24);
break;
case VideoModeType_8T:
CL_Init_DirectDrawMode(CLV_8T);
break;
}
if (ScanDrawDirectDraw != ScanDrawMode)
CL_Init_D3DMode(&(d3d.TextureFormat[d3d.CurrentTextureFormat].ddsd));
}

23
src/win95/cl_init.h Normal file
View file

@ -0,0 +1,23 @@
#ifndef _included_cl_init_h_
#define _included_cl_init_h_
#error "This file is obsolete"
#ifdef __cplusplus
extern "C" {
#endif
#include "d3d.h" // required by d3_func.hpp
#include "d3_func.h" // for D3DINFO definition
extern int VideoModeTypeScreen;
extern int ScanDrawMode;
extern D3DINFO d3d;
void CL_Init_All(void);
#ifdef __cplusplus
};
#endif
#endif // !_included_cl_init_h_

949
src/win95/d3_func.cpp Normal file
View file

@ -0,0 +1,949 @@
// Interface functions (written in C++) for
// Direct3D immediate mode system
// Must link to C code in main engine system
extern "C" {
// Mysterious definition required by objbase.h
// (included via one of the include files below)
// to start definition of obscure unique in the
// universe IDs required by Direct3D before it
// will deign to cough up with anything useful...
#define INITGUID
#include "3dc.h"
#include "awTexLd.h"
#include "dxlog.h"
#include "module.h"
#include "inline.h"
#include "d3_func.h"
#include "d3dmacs.h"
#include "string.h"
#include "kshape.h"
#include "eax.h"
#include "vmanpset.h"
extern "C++" {
#include "chnktexi.h"
#include "chnkload.hpp" // c++ header which ignores class definitions/member functions if __cplusplus is not defined ?
#include "r2base.h"
}
#define UseLocalAssert No
#include "ourasert.h"
// FIXME!!! Structures in d3d structure
// never have any size field set!!!
// This is how it's done in Microsoft's
// demo code --- but ARE THEY LYING???
// As far as I know the execute buffer should always be in
// system memory on any configuration, but this may
// eventually have to be changed to something that reacts
// to the caps bit in the driver, once drivers have reached
// the point where we can safely assume that such bits will be valid.
#define ForceExecuteBufferIntoSystemMemory Yes
// To define TBLEND mode --- at present
// it must be on for ramp textures and
// off for evrything else...
#define ForceTBlendCopy No
// Set to Yes for debugging, to No for normal
// operations (i.e. if we need a palettised
// file for an accelerator, load it from
// pre-palettised data, using code not yet
// written as of 27 / 8/ 96)
#define QuantiseOnLoad Yes
// Set to Yes to make default texture filter bilinear averaging rather
// than nearest
BOOL BilinearTextureFilter = 1;
extern LPDIRECTDRAW lpDD;
#if 0//
// Externs
extern int VideoMode;
extern int DXMemoryMode;
extern int ZBufferRequestMode;
extern int RasterisationRequestMode;
extern int SoftwareScanDrawRequestMode;
extern SCREENDESCRIPTORBLOCK ScreenDescriptorBlock;
extern VIEWDESCRIPTORBLOCK* Global_VDB_Ptr;
extern IMAGEHEADER ImageHeaderArray[];
extern BOOL MMXAvailable;
//Globals
int D3DDriverMode;
static unsigned char DefaultD3DTextureFilterMin;
static unsigned char DefaultD3DTextureFilterMax;
#if SuppressWarnings
static int* itemptr_tmp;
#ifdef __WATCOMC__
#pragma warning 389 5
#pragma message("Note: Disabled Warning W389 'Integral value may be truncated...'")
#endif
#endif
#endif //
HRESULT LastError;
int ExBufSize;
LPDIRECT3DEXECUTEBUFFER lpD3DExecCmdBuf;
LPDIRECTDRAWSURFACE lpZBuffer;
extern LPDIRECTDRAWSURFACE lpDDSBack;
extern LPDIRECTDRAWSURFACE lpDDSPrimary;
extern LPDIRECTDRAWPALETTE lpDDPal[]; // DirectDraw palette
D3DINFO d3d;
BOOL D3DHardwareAvailable;
int StartDriver;
int StartFormat;
static int devZBufDepth;
extern int WindowMode;
extern int ZBufferMode;
extern int ScanDrawMode;
extern int VideoModeColourDepth;
extern enum TexFmt { D3TF_4BIT, D3TF_8BIT, D3TF_16BIT, D3TF_32BIT, D3TF_MAX } d3d_desired_tex_fmt;
// Callback function to enumerate devices present
// on system (required so that device interface GUID
// can be retrieved if for no other reason). Device
// information is copied into instance of structure
// defined in d3_func.h
HRESULT WINAPI DeviceEnumerator(LPGUID lpGuid,
LPSTR lpDeviceDescription, LPSTR lpDeviceName,
LPD3DDEVICEDESC lpHWDesc, LPD3DDEVICEDESC lpHELDesc, LPVOID lpContext)
{
int *lpStartDriver = (int *)lpContext;
/*
Record the D3D driver's description
of itself.
*/
memcpy(&d3d.Driver[d3d.NumDrivers].Guid, lpGuid, sizeof(GUID));
strcpy(d3d.Driver[d3d.NumDrivers].About, lpDeviceDescription);
strcpy(d3d.Driver[d3d.NumDrivers].Name, lpDeviceName);
/*
Is this a hardware device or software emulation? Checking the color
model for a valid model works.
*/
if (lpHWDesc->dcmColorModel)
{
D3DHardwareAvailable = Yes;
d3d.Driver[d3d.NumDrivers].Hardware = Yes;
memcpy(&d3d.Driver[d3d.NumDrivers].Desc, lpHWDesc,
sizeof(D3DDEVICEDESC));
}
else
{
d3d.Driver[d3d.NumDrivers].Hardware = No;
memcpy(&d3d.Driver[d3d.NumDrivers].Desc, lpHELDesc,
sizeof(D3DDEVICEDESC));
}
/*
Does this driver do texture mapping?
*/
d3d.Driver[d3d.NumDrivers].Textures =
(d3d.Driver[d3d.NumDrivers].Desc.dpcTriCaps.dwTextureCaps &
D3DPTEXTURECAPS_PERSPECTIVE) ? TRUE : FALSE;
/*
Can this driver use a z-buffer?
*/
d3d.Driver[d3d.NumDrivers].ZBuffer =
d3d.Driver[d3d.NumDrivers].Desc.dwDeviceZBufferBitDepth & (DDBD_16 | DDBD_24 | DDBD_32)
? TRUE : FALSE;
// The driver description is recorded here,
// and some basic things like ZBuffering
// availability are noted separately. Other
// things such as hardware acceleration for
// translucency could potentially be noted here
// for use in the Write functions to decide
// whether e.g. iflag_transparent should be
// treated as valid. Obviously this will
// require modification of the D3DDRIVERINFO
// structure in d3_func.h
*lpStartDriver = d3d.NumDrivers;
d3d.NumDrivers++;
if (d3d.NumDrivers == MAX_D3D_DRIVERS)
return (D3DENUMRET_CANCEL);
else
return (D3DENUMRET_OK);
}
// This function is called from
// InitialiseDirect3DImmediateMode, to
// insert and execute opcodes which cannot
// be run during a "real" scene because of
// some obscure feature of Direct3D.
// Initialise Direct3D immediate mode system
BOOL InitialiseDirect3DImmediateMode(void)
{
BOOL RetVal;
// to tell device enum function that it has not been called before
StartDriver = -1;
// to tell texture enum function that it has not been called before
StartFormat = -1;
// default is no hardware
// note that we are still resetting
// this here just in case the test from
// InitialiseSystem failed and things aren't
// what we thought...
D3DHardwareAvailable = No;
// Zero d3d structure
memset(&d3d, 0, sizeof(D3DINFO));
// Set up Direct3D interface object
LastError = lpDD->QueryInterface(IID_IDirect3D, (LPVOID*) &d3d.lpD3D);
LOGDXERR(LastError);
if (LastError != DD_OK)
return FALSE;
// Use callback function to enumerate available devices on system
// and acquire device GUIDs etc
// note that we are still resetting
// this here just in case the test from
// InitialiseSystem failed and things aren't
// what we thought...
LastError = d3d.lpD3D->EnumDevices(DeviceEnumerator, (LPVOID)&StartDriver);
LOGDXERR(LastError);
if (LastError != D3D_OK)
return FALSE;
// Must be run as soon as possible in the
// initialisation sequence, but after the
// device enumeration (and obviously after
// DirectDraw object and surface initialisation).
SelectD3DDriverAndDrawMode();
d3d.ThisDriver = d3d.Driver[d3d.CurrentDriver].Desc;
// Test!!! Release D3D object if we don't need it and do an
// early exit. Will this fix the banding problem on some
// accelerators in palettised modes??
// Evidently not. Still, probably a good thing to do...
// But!!! The whole banding problem appears to be a
// modeX emulation problem on some 3D accelerator cards...
#if 1
if (ScanDrawMode == ScanDrawDirectDraw)
{
ReleaseDirect3DNotDDOrImages();
return TRUE;
}
#endif
// Note that this must be done BEFORE the D3D device object is created
#if SupportZBuffering
if (ZBufferMode != ZBufferOff)
{
RetVal = CreateD3DZBuffer();
if (RetVal == FALSE) return FALSE;
}
#endif
// Set up Direct3D device object (must be linked to back buffer)
LastError = lpDDSBack->QueryInterface(d3d.Driver[d3d.CurrentDriver].Guid,
(LPVOID*)&d3d.lpD3DDevice);
LOGDXERR(LastError);
if (LastError != DD_OK)
return FALSE;
AW_TL_ERC awErr = AwSetD3DDevice(d3d.lpD3DDevice);
GLOBALASSERT(AW_TLE_OK==awErr);
// Enumerate texture formats and pick one
// (palettised if possible).
d3d.NumTextureFormats = 0;
d3d_desired_tex_fmt=D3TF_8BIT;
LastError = d3d.lpD3DDevice->EnumTextureFormats
(TextureFormatsEnumerator,
(LPVOID)&StartFormat);
LOGDXERR(LastError);
if (LastError != D3D_OK)
#if debug
{
ReleaseDirect3D();
exit(LastError);
}
#else
return FALSE;
#endif
d3d.CurrentTextureFormat = StartFormat;
// NEW NEW NEW
// Note: we are NOT restricted to only one texture format
awErr = AwSetTextureFormat(&d3d.TextureFormat[StartFormat].ddsd);
GLOBALASSERT(AW_TLE_OK==awErr);
// Create viewport
LastError = d3d.lpD3D->CreateViewport(&d3d.lpD3DViewport, NULL);
LOGDXERR(LastError);
if (LastError != D3D_OK)
return FALSE;
// Add viewport to desired device
LastError = d3d.lpD3DDevice->AddViewport(d3d.lpD3DViewport);
LOGDXERR(LastError);
if (LastError != D3D_OK)
return FALSE;
// Set up viewport data
// Note that the viewport is always set to the
// SDB limits because internal clipping is handled
// within the main engine code using the VDB
// system.
{
// Configure viewport here
D3DVIEWPORT viewPort;
memset(&viewPort, 0, sizeof(D3DVIEWPORT));
viewPort.dwSize = sizeof(D3DVIEWPORT);
viewPort.dwX = 0; // origins x and y
viewPort.dwY = 0;
viewPort.dwWidth = ScreenDescriptorBlock.SDB_Width;
viewPort.dwHeight = ScreenDescriptorBlock.SDB_Height;
viewPort.dvScaleX = D3DVAL((float)viewPort.dwWidth / 2.0); // ????was 2.0
viewPort.dvScaleY = D3DVAL((float)viewPort.dwHeight / 2.0); // ????was 2.0
viewPort.dvMaxX = D3DVAL(D3DDivide(D3DVAL(viewPort.dwWidth),
D3DVAL(2 * viewPort.dvScaleX))); // ????
viewPort.dvMaxY = D3DVAL(D3DDivide(D3DVAL(viewPort.dwHeight),
D3DVAL(2 * viewPort.dvScaleY))); // ????
// And actually set viewport
LastError = d3d.lpD3DViewport->SetViewport(&viewPort);
LOGDXERR(LastError);
if (LastError != D3D_OK)
return FALSE;
}
// At present we will not set a background material for the
// viewport, staying instead with the blit code in backdrop.c
// Also, we are not currently adding default lights to the
// viewport, since the engine lighting system is completely
// disconnected from the immediate mode lighting module.
// Create execute buffer
{
// Locals for execute buffer
D3DEXECUTEBUFFERDESC d3dexDesc;
// Set up structure to initialise buffer
// Note some instructions (e.g. lines) may be smaller than a
// triangle, but none can be larger
ExBufSize = ((sizeof(D3DINSTRUCTION) + sizeof(D3DTRIANGLE))
* MaxD3DInstructions)
+ (sizeof(D3DTLVERTEX) * MaxD3DVertices);
memset(&d3dexDesc, 0, sizeof(D3DEXECUTEBUFFERDESC));
d3dexDesc.dwSize = sizeof(D3DEXECUTEBUFFERDESC);
d3dexDesc.dwFlags = D3DDEB_BUFSIZE | D3DDEB_CAPS;
d3dexDesc.dwBufferSize = ExBufSize;
#if ForceExecuteBufferIntoSystemMemory
d3dexDesc.dwCaps = D3DDEBCAPS_SYSTEMMEMORY;
#else
d3dexDesc.dwCaps = D3DDEBCAPS_MEM; // untested!!!
#endif
// Create buffer
LastError = d3d.lpD3DDevice->CreateExecuteBuffer
(&d3dexDesc, &lpD3DExecCmdBuf, NULL);
LOGDXERR(LastError);
if (LastError != D3D_OK)
return FALSE;
}
// Temporary patch here because the defaults function
// buggers palette setting in ScanDrawDirectDraw
// for some really obscure reason...
if (ScanDrawMode != ScanDrawDirectDraw)
SetExecuteBufferDefaults();
return TRUE;
}
#if 1
// Note that error conditions have been removed
// on the grounds that an early exit will prevent
// EndScene being run if this function is used,
// which screws up all subsequent buffers
BOOL RenderD3DScene(void)
{
// Begin scene
// My theory is that the functionality of this
// thing must invoke a DirectDraw surface lock
// on the back buffer without telling you. However,
// we shall see...
LastError = d3d.lpD3DDevice->BeginScene();
LOGDXERR(LastError);
// if (LastError != D3D_OK)
// return FALSE;
// Execute buffer
LastError = d3d.lpD3DDevice->Execute(lpD3DExecCmdBuf,
d3d.lpD3DViewport, D3DEXECUTE_UNCLIPPED);
LOGDXERR(LastError);
// if (LastError != D3D_OK)
// return FALSE;
// End scene
LastError = d3d.lpD3DDevice->EndScene();
LOGDXERR(LastError);
// if (LastError != D3D_OK)
// return FALSE;
return TRUE;
}
#else
int Time1, Time2, Time3, Time4;
BOOL RenderD3DScene(void)
{
// Begin scene
// My theory is that the functionality of this
// thing must invoke a DirectDraw surface lock
// on the back buffer without telling you. However,
// we shall see...
Time1 = GetWindowsTickCount();
LastError = d3d.lpD3DDevice->BeginScene();
LOGDXERR(LastError);
if (LastError != D3D_OK)
return FALSE;
Time2 = GetWindowsTickCount();
// Execute buffer
#if 1
LastError = d3d.lpD3DDevice->Execute(lpD3DExecCmdBuf,
d3d.lpD3DViewport, D3DEXECUTE_UNCLIPPED);
LOGDXERR(LastError);
#else
LastError = d3d.lpD3DDevice->Execute(lpD3DExecCmdBuf,
d3d.lpD3DViewport, D3DEXECUTE_CLIPPED);
LOGDXERR(LastError);
#endif
if (LastError != D3D_OK)
return FALSE;
Time3 = GetWindowsTickCount();
// End scene
LastError = d3d.lpD3DDevice->EndScene();
LOGDXERR(LastError);
if (LastError != D3D_OK)
return FALSE;
Time4 = GetWindowsTickCount();
return TRUE;
#endif
// With a bit of luck this should automatically
// release all the Direct3D and DirectDraw
// objects using their own functionality.
// A separate call to finiObjects
// is not required.
// NOTE!!! This depends on Microsoft macros
// in d3dmacs.h, which is in the win95 directory
// and must be upgraded from sdk upgrades!!!
void ReleaseDirect3D(void)
{
DeallocateAllImages();
RELEASE(d3d.lpD3DViewport);
RELEASE(d3d.lpD3DDevice);
#if SupportZBuffering
RELEASE(lpZBuffer);
#endif
RELEASE(lpDDPal[0]);
RELEASE(lpDDSBack);
RELEASE(lpDDSPrimary);
RELEASE(d3d.lpD3D);
RELEASE(lpDD);
/* release Direct Input stuff */
ReleaseDirectKeyboard();
ReleaseDirectMouse();
ReleaseDirectInput();
// Reset windows palette entry allocation
if ((VideoModeColourDepth == 8) && (WindowMode == WindowModeSubWindow))
{
HDC hdc = GetDC(NULL);
SetSystemPaletteUse(hdc, SYSPAL_STATIC);
ReleaseDC(NULL, hdc);
}
}
// Release all Direct3D objects
// but not DirectDraw
void ReleaseDirect3DNotDDOrImages(void)
{
RELEASE(d3d.lpD3DViewport);
RELEASE(d3d.lpD3DDevice);
#if SupportZBuffering
RELEASE(lpZBuffer);
#endif
RELEASE(d3d.lpD3D);
}
void ReleaseDirect3DNotDD(void)
{
DeallocateAllImages();
RELEASE(d3d.lpD3DViewport);
RELEASE(d3d.lpD3DDevice);
#if SupportZBuffering
RELEASE(lpZBuffer);
#endif
RELEASE(d3d.lpD3D);
}
// NOTE!!! These functions depend on Microsoft macros
// in d3dmacs.h, which is in the win95 directory
// and must be upgraded from sdk upgrades!!!
// ALSO NOTE!!! All this stuff involves heavy
// use of floating point assembler in software
// emulation, probably hand parallelised between
// the FPU and the processor or something bizarre,
// implying that this stuff SHOULD NOT be used
// one anything below a Pentium.
// AND AGAIN!!! Due to the nature of the item
// format, the rasterisation module MUST RECEIVE
// repeated vertices in the data area. Tough shit,
// Microsoft, that's what I say...
void WritePolygonToExecuteBuffer(int* itemptr)
{
}
void WriteGouraudPolygonToExecuteBuffer(int* itemptr)
{
}
void Write2dTexturedPolygonToExecuteBuffer(int* itemptr)
{
}
void WriteGouraud2dTexturedPolygonToExecuteBuffer(int* itemptr)
{
}
void Write3dTexturedPolygonToExecuteBuffer(int* itemptr)
{
}
void WriteGouraud3dTexturedPolygonToExecuteBuffer(int* itemptr)
{
}
#if SupportZBuffering
// To make effective use of 16 bit z buffers (common
// on hardware accelerators) we must have a z coordinate
// which has been transformed into screen space in such a
// way that linearity and planearity are preserved, i.e. as
// if we had done a homogeneous transformation. For the case
// in which the far clipping plane is much further away than the
// near one (effectively true for 3dc, especially as there is
// no far clipping plane as such), the appropriate transformation
// can be reduced to zScreen = (ZWorld - ZNear) / ZWorld. This
// calculation is therefore (unfortunately) done for each vertex
// for z buffered items, taking ZNear to be the current
// VDB_ClipZ * GlobalScale.
void WriteZBPolygonToExecuteBuffer(int* itemptr)
{
}
void WriteZBGouraudPolygonToExecuteBuffer(int* itemptr)
{
}
void WriteZB2dTexturedPolygonToExecuteBuffer(int* itemptr)
{
}
void WriteZBGouraud2dTexturedPolygonToExecuteBuffer(int* itemptr)
{
}
void WriteZB3dTexturedPolygonToExecuteBuffer(int* itemptr)
{
}
void WriteZBGouraud3dTexturedPolygonToExecuteBuffer(int* itemptr)
{
}
#endif
void WriteBackdrop2dTexturedPolygonToExecuteBuffer(int* itemptr)
{
}
// Same as ordinary 2d textured draw at present, but may e.g.
// require different texture wrapping behaviour or
// w values.
void WriteBackdrop3dTexturedPolygonToExecuteBuffer(int* itemptr)
{
}
// Note that this is all dead crap and deeply unoptimised
// But then... a) it's really only a test and
// b) it's for the tools group anyway...
void DirectWriteD3DLine(VECTOR2D* LineStart, VECTOR2D* LineEnd, int LineColour)
{
}
// reload D3D image -- assumes a base pointer points to the image loaded
// from disc, in a suitable format
void ReloadImageIntoD3DImmediateSurface(IMAGEHEADER* iheader)
{
void *reloadedTexturePtr = ReloadImageIntoD3DTexture(iheader);
LOCALASSERT(reloadedTexturePtr != NULL);
int gotTextureHandle = GetTextureHandle(iheader);
LOCALASSERT(gotTextureHandle == TRUE);
}
void* ReloadImageIntoD3DTexture(IMAGEHEADER* iheader)
{
// NOTE FIXME BUG HACK
// what if the image was a DD surface ??
if (iheader->hBackup)
{
iheader->D3DTexture = AwCreateTexture("rf",AW_TLF_PREVSRC|AW_TLF_COMPRESS);
return iheader->D3DTexture;
}
else return NULL;
}
int GetTextureHandle(IMAGEHEADER *imageHeaderPtr)
{
LPDIRECT3DTEXTURE Texture = (LPDIRECT3DTEXTURE) imageHeaderPtr->D3DTexture;
LastError = Texture->GetHandle(d3d.lpD3DDevice, (D3DTEXTUREHANDLE*)&(imageHeaderPtr->D3DHandle));
if (LastError != D3D_OK) return FALSE;
return TRUE;
}
void ReleaseD3DTexture(void* D3DTexture)
{
LPDIRECT3DTEXTURE lpTexture;
lpTexture = (LPDIRECT3DTEXTURE) D3DTexture;
RELEASE(lpTexture);
}
#if SupportZBuffering
BOOL CreateD3DZBuffer(void)
{
DDSURFACEDESC ddsd;
// For safety, kill any existing z buffer
#if SupportZBuffering
RELEASE(lpZBuffer);
#endif
// If we do not have z buffering support
// on this driver, give up now
if (!(d3d.Driver[d3d.CurrentDriver].ZBuffer))
return FALSE;
memset(&ddsd,0,sizeof(DDSURFACEDESC));
ddsd.dwSize = sizeof(DDSURFACEDESC);
ddsd.dwFlags = (DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_ZBUFFERBITDEPTH);
ddsd.dwHeight = ScreenDescriptorBlock.SDB_Height;
ddsd.dwWidth = ScreenDescriptorBlock.SDB_Width;
ddsd.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
// If we are on a hardware driver, then the z buffer
// MUST be in video memory. Otherwise, it MUST be
// in system memory. I think.
if (d3d.Driver[d3d.CurrentDriver].Hardware)
ddsd.ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY;
else
ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
// Get the Z buffer bit depth from this driver's
// D3D device description and add it to the description
// of the surface we want to create
devZBufDepth = d3d.Driver[d3d.CurrentDriver].Desc.dwDeviceZBufferBitDepth;
if (devZBufDepth & DDBD_32)
ddsd.dwZBufferBitDepth = 32;
else if (devZBufDepth & DDBD_24)
ddsd.dwZBufferBitDepth = 24;
else if (devZBufDepth & DDBD_16)
ddsd.dwZBufferBitDepth = 16;
else if (devZBufDepth & DDBD_8)
ddsd.dwZBufferBitDepth = 8;
else
{
#if debug
ReleaseDirect3D();
exit(0x511621);
#else
return FALSE;
#endif
}
// Eight-bit z buffer? Fuck off.
if (ddsd.dwZBufferBitDepth == 8)
return FALSE;
// Now we must actually make the z buffer
LastError = lpDD->CreateSurface(&ddsd,&lpZBuffer, NULL);
if (LastError != DD_OK)
{
RELEASE(lpZBuffer);
return FALSE;
}
LastError = lpDDSBack->AddAttachedSurface(lpZBuffer);
if (LastError != DD_OK)
{
RELEASE(lpZBuffer);
return FALSE;
}
return TRUE;
}
#define ZFlushVal 0xffffffff
// At present we are using my z flush function, with the
// (undocumented) addition of a fill colour for the
// actual depth fill, since it seems to work and at least
// I know what it does. If it starts failing we'll probably
// have to go back to invoking the viewport clear through
// Direct3D.
void FlushD3DZBuffer(void)
{
DDBLTFX ddbltfx;
memset(&ddbltfx, 0, sizeof(ddbltfx));
ddbltfx.dwSize = sizeof(ddbltfx);
ddbltfx.dwFillDepth = devZBufDepth;
ddbltfx.dwFillColor = ZFlushVal;
/* lets blt a color to the surface*/
LastError = lpZBuffer->Blt(NULL, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &ddbltfx);
}
void SecondFlushD3DZBuffer(void)
{
#if 1
{
WriteEndCodeToExecuteBuffer();
UnlockExecuteBufferAndPrepareForUse();
ExecuteBuffer();
LockExecuteBuffer();
}
DDBLTFX ddbltfx;
memset(&ddbltfx, 0, sizeof(ddbltfx));
ddbltfx.dwSize = sizeof(ddbltfx);
ddbltfx.dwFillDepth = devZBufDepth;
ddbltfx.dwFillColor = ZFlushVal;
/* lets blt a color to the surface*/
LastError = lpZBuffer->Blt(NULL, NULL, NULL, DDBLT_DEPTHFILL | DDBLT_WAIT, &ddbltfx);
#else
extern void ClearZBufferWithPolygon(void);
ClearZBufferWithPolygon();
#endif
}
#endif
void FlushZB(void)
{
HRESULT hRes;
D3DRECT d3dRect;
d3dRect.lX1 = 0;
d3dRect.lX2 = 640;
d3dRect.lY1 = 0;
d3dRect.lY2 = 480;
hRes = d3d.lpD3DViewport->Clear(1, &d3dRect, D3DCLEAR_ZBUFFER);
}
// For extern "C"
};

106
src/win95/d3_func.h Normal file
View file

@ -0,0 +1,106 @@
#ifndef _included_d3_func_h_
#define _included_d3_func_h_
#ifdef __cplusplus
extern "C" {
#endif
/*
Direct3D globals
*/
/*
Maximum number of Direct3D drivers ever
expected to be resident on the system.
*/
#define MAX_D3D_DRIVERS 5
/*
Maximum number of texture formats ever
expected to be reported by a Direct3D
driver.
*/
#define MAX_TEXTURE_FORMATS 10
/*
Description of a D3D driver.
*/
typedef struct D3DDriverInfo {
char Name[30]; /* short name of driver */
char About[50]; /* string about driver */
D3DDEVICEDESC Desc; /* full driver description */
GUID Guid; /* wacky universally unique id thingy */
BOOL Hardware; /* accelerated driver? */
BOOL Textures; /* Texture mapping available? */
BOOL ZBuffer; /* Z Buffering available? */
} D3DDRIVERINFO;
/*
Description of a D3D driver texture
format.
*/
typedef struct D3DTextureFormat {
DDSURFACEDESC ddsd; /* DDSURFACEDESC for the surface description */
BOOL Palette; /* is Palettized? */
int RedBPP; /* #red bits per pixel */
int BlueBPP; /* #blue bits per pixel */
int GreenBPP; /* #green bits per pixel */
int IndexBPP; /* number of bits in palette index */
} D3DTEXTUREFORMAT;
typedef struct D3DInfo {
LPDIRECT3D lpD3D;
LPDIRECT3DDEVICE lpD3DDevice;
LPDIRECT3DVIEWPORT lpD3DViewport;
int NumDrivers;
int CurrentDriver;
D3DDEVICEDESC ThisDriver;
D3DDRIVERINFO Driver[MAX_D3D_DRIVERS];
int CurrentTextureFormat;
int NumTextureFormats;
D3DTEXTUREFORMAT TextureFormat[MAX_TEXTURE_FORMATS];
} D3DINFO;
/* KJL 14:24:45 12/4/97 - render state information */
enum TRANSLUCENCY_TYPE
{
TRANSLUCENCY_OFF,
TRANSLUCENCY_NORMAL,
TRANSLUCENCY_INVCOLOUR,
TRANSLUCENCY_COLOUR,
TRANSLUCENCY_GLOWING,
TRANSLUCENCY_DARKENINGCOLOUR,
TRANSLUCENCY_JUSTSETZ,
TRANSLUCENCY_NOT_SET
};
enum FILTERING_MODE_ID
{
FILTERING_BILINEAR_OFF,
FILTERING_BILINEAR_ON,
FILTERING_NOT_SET
};
typedef struct
{
enum TRANSLUCENCY_TYPE TranslucencyMode;
enum FILTERING_MODE_ID FilteringMode;
int FogDistance;
unsigned int FogIsOn :1;
unsigned int WireFrameModeIsOn :1;
} RENDERSTATES;
#ifdef __cplusplus
}
#endif
#endif /* ! _included_d3_func_h_ */

2491
src/win95/d3_image.cpp Normal file

File diff suppressed because it is too large Load diff

1223
src/win95/d3_image.hpp Normal file

File diff suppressed because it is too large Load diff

147
src/win95/d3dmacs.h Normal file
View file

@ -0,0 +1,147 @@
/*
* Copyright (C) 1995, 1996 Microsoft Corporation. All Rights Reserved.
*
* File: d3dmacs.h
*
* Useful macros for generating execute buffers. Consult the D3D sample
* code for examples of their usage.
*
* Use OP_NOP to QWORD align triangle and line instructions.
*/
#ifndef __D3DMACS_H__
#define __D3DMACS_H__
#undef RELEASE
#ifndef __cplusplus
#define MAKE_MATRIX(lpDev, handle, data) \
if (lpDev->lpVtbl->CreateMatrix(lpDev, &handle) != D3D_OK) \
return FALSE; \
if (lpDev->lpVtbl->SetMatrix(lpDev, handle, &data) != D3D_OK) \
return FALSE
#define RELEASE(x) if (x != NULL) {x->lpVtbl->Release(x); x = NULL;}
#endif
#ifdef __cplusplus
#define MAKE_MATRIX(lpDev, handle, data) \
if (lpDev->CreateMatrix(&handle) != D3D_OK) \
return FALSE; \
if (lpDev->SetMatrix(handle, &data) != D3D_OK) \
return FALSE
#define RELEASE(x) if (x != NULL) {x->Release(); x = NULL;}
#endif
#define PUTD3DINSTRUCTION(op, sz, cnt, ptr) \
((LPD3DINSTRUCTION) ptr)->bOpcode = op; \
((LPD3DINSTRUCTION) ptr)->bSize = sz; \
((LPD3DINSTRUCTION) ptr)->wCount = cnt; \
ptr = (void *)(((LPD3DINSTRUCTION) ptr) + 1)
#define VERTEX_DATA(loc, cnt, ptr) \
if ((ptr) != (loc)) memcpy((ptr), (loc), sizeof(D3DVERTEX) * (cnt)); \
ptr = (void *)(((LPD3DVERTEX) (ptr)) + (cnt))
// OP_MATRIX_MULTIPLY size: 4 (sizeof D3DINSTRUCTION)
#define OP_MATRIX_MULTIPLY(cnt, ptr) \
PUTD3DINSTRUCTION(D3DOP_MATRIXMULTIPLY, sizeof(D3DMATRIXMULTIPLY), cnt, ptr)
// MATRIX_MULTIPLY_DATA size: 12 (sizeof MATRIXMULTIPLY)
#define MATRIX_MULTIPLY_DATA(src1, src2, dest, ptr) \
((LPD3DMATRIXMULTIPLY) ptr)->hSrcMatrix1 = src1; \
((LPD3DMATRIXMULTIPLY) ptr)->hSrcMatrix2 = src2; \
((LPD3DMATRIXMULTIPLY) ptr)->hDestMatrix = dest; \
ptr = (void *)(((LPD3DMATRIXMULTIPLY) ptr) + 1)
// OP_STATE_LIGHT size: 4 (sizeof D3DINSTRUCTION)
#define OP_STATE_LIGHT(cnt, ptr) \
PUTD3DINSTRUCTION(D3DOP_STATELIGHT, sizeof(D3DSTATE), cnt, ptr)
// OP_STATE_TRANSFORM size: 4 (sizeof D3DINSTRUCTION)
#define OP_STATE_TRANSFORM(cnt, ptr) \
PUTD3DINSTRUCTION(D3DOP_STATETRANSFORM, sizeof(D3DSTATE), cnt, ptr)
// OP_STATE_RENDER size: 4 (sizeof D3DINSTRUCTION)
#define OP_STATE_RENDER(cnt, ptr) \
PUTD3DINSTRUCTION(D3DOP_STATERENDER, sizeof(D3DSTATE), cnt, ptr)
// STATE_DATA size: 8 (sizeof D3DSTATE)
#define STATE_DATA(type, arg, ptr) \
((LPD3DSTATE) ptr)->drstRenderStateType = (D3DRENDERSTATETYPE)type; \
((LPD3DSTATE) ptr)->dwArg[0] = arg; \
ptr = (void *)(((LPD3DSTATE) ptr) + 1)
// OP_PROCESS_VERTICES size: 4 (sizeof D3DINSTRUCTION)
#define OP_PROCESS_VERTICES(cnt, ptr) \
PUTD3DINSTRUCTION(D3DOP_PROCESSVERTICES, sizeof(D3DPROCESSVERTICES), cnt, ptr)
// PROCESSVERTICES_DATA size: 16 (sizeof D3DPROCESSVERTICES)
#define PROCESSVERTICES_DATA(flgs, strt, cnt, ptr) \
((LPD3DPROCESSVERTICES) ptr)->dwFlags = flgs; \
((LPD3DPROCESSVERTICES) ptr)->wStart = strt; \
((LPD3DPROCESSVERTICES) ptr)->wDest = strt; \
((LPD3DPROCESSVERTICES) ptr)->dwCount = cnt; \
((LPD3DPROCESSVERTICES) ptr)->dwReserved = 0; \
ptr = (void *)(((LPD3DPROCESSVERTICES) ptr) + 1)
// OP_TRIANGLE_LIST size: 4 (sizeof D3DINSTRUCTION)
#define OP_TRIANGLE_LIST(cnt, ptr) \
PUTD3DINSTRUCTION(D3DOP_TRIANGLE, sizeof(D3DTRIANGLE), cnt, ptr)
#define TRIANGLE_LIST_DATA(loc, count, ptr) \
if ((ptr) != (loc)) memcpy((ptr), (loc), sizeof(D3DTRIANGLE) * (count)); \
ptr = (void *)(((LPD3DTRIANGLE) (ptr)) + (count))
// OP_LINE_LIST size: 4 (sizeof D3DINSTRUCTION)
#define OP_LINE_LIST(cnt, ptr) \
PUTD3DINSTRUCTION(D3DOP_LINE, sizeof(D3DLINE), cnt, ptr)
#define LINE_LIST_DATA(loc, count, ptr) \
if ((ptr) != (loc)) memcpy((ptr), (loc), sizeof(D3DLINE) * (count)); \
ptr = (void *)(((LPD3DLINE) (ptr)) + (count))
// OP_POINT_LIST size: 8 (sizeof D3DINSTRUCTION + sizeof D3DPOINT)
#define OP_POINT_LIST(first, cnt, ptr) \
PUTD3DINSTRUCTION(D3DOP_POINT, sizeof(D3DPOINT), 1, ptr); \
((LPD3DPOINT)(ptr))->wCount = cnt; \
((LPD3DPOINT)(ptr))->wFirst = first; \
ptr = (void*)(((LPD3DPOINT)(ptr)) + 1)
// OP_SPAN_LIST size: 8 (sizeof D3DINSTRUCTION + sizeof D3DSPAN)
#define OP_SPAN_LIST(first, cnt, ptr) \
PUTD3DINSTRUCTION(D3DOP_SPAN, sizeof(D3DSPAN), 1, ptr); \
((LPD3DSPAN)(ptr))->wCount = cnt; \
((LPD3DSPAN)(ptr))->wFirst = first; \
ptr = (void*)(((LPD3DSPAN)(ptr)) + 1)
// OP_BRANCH_FORWARD size: 18 (sizeof D3DINSTRUCTION + sizeof D3DBRANCH)
#define OP_BRANCH_FORWARD(tmask, tvalue, tnegate, toffset, ptr) \
PUTD3DINSTRUCTION(D3DOP_BRANCHFORWARD, sizeof(D3DBRANCH), 1, ptr); \
((LPD3DBRANCH) ptr)->dwMask = tmask; \
((LPD3DBRANCH) ptr)->dwValue = tvalue; \
((LPD3DBRANCH) ptr)->bNegate = tnegate; \
((LPD3DBRANCH) ptr)->dwOffset = toffset; \
ptr = (void *)(((LPD3DBRANCH) (ptr)) + 1)
// OP_SET_STATUS size: 20 (sizeof D3DINSTRUCTION + sizeof D3DSTATUS)
#define OP_SET_STATUS(flags, status, _x1, _y1, _x2, _y2, ptr) \
PUTD3DINSTRUCTION(D3DOP_SETSTATUS, sizeof(D3DSTATUS), 1, ptr); \
((LPD3DSTATUS)(ptr))->dwFlags = flags; \
((LPD3DSTATUS)(ptr))->dwStatus = status; \
((LPD3DSTATUS)(ptr))->drExtent.x1 = _x1; \
((LPD3DSTATUS)(ptr))->drExtent.y1 = _y1; \
((LPD3DSTATUS)(ptr))->drExtent.x2 = _x2; \
((LPD3DSTATUS)(ptr))->drExtent.y2 = _y2; \
ptr = (void *)(((LPD3DSTATUS) (ptr)) + 1)
// OP_NOP size: 4
#define OP_NOP(ptr) \
PUTD3DINSTRUCTION(D3DOP_TRIANGLE, sizeof(D3DTRIANGLE), 0, ptr)
#define OP_EXIT(ptr) \
PUTD3DINSTRUCTION(D3DOP_EXIT, 0, 0, ptr)
#define QWORD_ALIGNED(ptr) \
!(0x00000007L & (ULONG)(ptr))
#endif // __D3DMACS_H__

316
src/win95/d3load.c Normal file
View file

@ -0,0 +1,316 @@
/***************************************************************************/
/* Loading a PPM file into a surface */
/***************************************************************************/
/*
* LoadSurface
* Loads a ppm file into a texture map DD surface of the given format. The
* memory flag specifies DDSCAPS_SYSTEMMEMORY or DDSCAPS_VIDEOMEMORY.
*/
LPDIRECTDRAWSURFACE
D3DAppILoadSurface(LPDIRECTDRAW lpDD, LPCSTR lpName,
LPDDSURFACEDESC lpFormat, DWORD memoryflag)
{
LPDIRECTDRAWSURFACE lpDDS;
DDSURFACEDESC ddsd, format;
D3DCOLOR colors[256];
D3DCOLOR c;
DWORD dwWidth, dwHeight;
int i, j;
FILE *fp;
char *lpC;
CHAR buf[100];
LPDIRECTDRAWPALETTE lpDDPal;
PALETTEENTRY ppe[256];
int psize;
DWORD pcaps;
int color_count;
BOOL bQuant = FALSE;
HRESULT ddrval;
/*
* Find the image file and open it
*/
fp = D3DAppIFindFile(lpName, "rb");
if (fp == NULL) {
D3DAppISetErrorString("Cannot find %s.\n", lpName);
return NULL;
}
/*
* Is it a PPM file?
*/
fgets(buf, sizeof buf, fp);
if (lstrcmp(buf, "P6\n")) {
fclose(fp);
D3DAppISetErrorString("%s is not a PPM file.\n", lpName);
return NULL;
}
/*
* Skip any comments
*/
do {
fgets(buf, sizeof buf, fp);
} while (buf[0] == '#');
/*
* Read the width and height
*/
sscanf(buf, "%d %d\n", &dwWidth, &dwHeight);
fgets(buf, sizeof buf, fp); /* skip next line */
/*
* Create a surface of the given format using the dimensions of the PPM
* file.
*/
memcpy(&format, lpFormat, sizeof(DDSURFACEDESC));
if (format.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8) {
bQuant = TRUE;
psize = 256;
pcaps = DDPCAPS_8BIT | DDPCAPS_ALLOW256;
} else if (format.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED4) {
bQuant = TRUE;
psize = 16;
pcaps = DDPCAPS_4BIT;
}
memcpy(&ddsd, &format, sizeof(DDSURFACEDESC));
ddsd.dwSize = sizeof(DDSURFACEDESC);
ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | memoryflag;
ddsd.dwHeight = dwHeight;
ddsd.dwWidth = dwWidth;
ddrval = lpDD->lpVtbl->CreateSurface(lpDD, &ddsd, &lpDDS, NULL);
if (ddrval != DD_OK) {
D3DAppISetErrorString("CreateSurface for texture failed (loadtex).\n%s",
D3DAppErrorToString(ddrval));
return NULL;
}
/*
* Lock the surface so it can be filled with the PPM file
*/
memset(&ddsd, 0, sizeof(DDSURFACEDESC));
ddsd.dwSize = sizeof(DDSURFACEDESC);
ddrval = lpDDS->lpVtbl->Lock(lpDDS, NULL, &ddsd, 0, NULL);
if (ddrval != DD_OK) {
lpDDS->lpVtbl->Release(lpDDS);
D3DAppISetErrorString("Lock failed while loading surface (loadtex).\n%s",
D3DAppErrorToString(ddrval));
return NULL;
}
/*
* The method of loading depends on the pixel format of the dest surface
*/
if (!bQuant) {
/*
* The texture surface is not palettized
*/
unsigned long* lpLP;
unsigned short* lpSP;
unsigned char* lpCP;
unsigned long m;
int s;
int red_shift, red_scale;
int green_shift, green_scale;
int blue_shift, blue_scale;
/*
* Determine the red, green and blue masks' shift and scale.
*/
for (s = 0, m = format.ddpfPixelFormat.dwRBitMask; !(m & 1);
s++, m >>= 1);
red_shift = s;
red_scale = 255 / (format.ddpfPixelFormat.dwRBitMask >> s);
for (s = 0, m = format.ddpfPixelFormat.dwGBitMask; !(m & 1);
s++, m >>= 1);
green_shift = s;
green_scale = 255 / (format.ddpfPixelFormat.dwGBitMask >> s);
for (s = 0, m = format.ddpfPixelFormat.dwBBitMask; !(m & 1);
s++, m >>= 1);
blue_shift = s;
blue_scale = 255 / (format.ddpfPixelFormat.dwBBitMask >> s);
/*
* Each RGB bit count requires different pointers
*/
switch (format.ddpfPixelFormat.dwRGBBitCount) {
case 32 :
for (j = 0; j < (int)dwHeight; j++) {
/*
* Point to next row in texture surface
*/
lpLP = (unsigned long*)(((char*)ddsd.lpSurface) +
ddsd.lPitch * j);
for (i = 0; i < (int)dwWidth; i++) {
int r, g, b;
/*
* Read each value, scale it and shift it into position
*/
r = getc(fp) / red_scale;
g = getc(fp) / green_scale;
b = getc(fp) / blue_scale;
*lpLP = (r << red_shift) | (g << green_shift) |
(b << blue_shift);
lpLP++;
}
}
break;
case 16 :
for (j = 0; j < (int)dwHeight; j++) {
lpSP = (unsigned short*)(((char*)ddsd.lpSurface) +
ddsd.lPitch * j);
for (i = 0; i < (int)dwWidth; i++) {
int r, g, b;
r = getc(fp) / red_scale;
g = getc(fp) / green_scale;
b = getc(fp) / blue_scale;
*lpSP = (r << red_shift) | (g << green_shift) |
(b << blue_shift);
lpSP++;
}
}
break;
case 8:
for (j = 0; j < (int)dwHeight; j++) {
lpCP = (unsigned char*)(((char*)ddsd.lpSurface) +
ddsd.lPitch * j);
for (i = 0; i < (int)dwWidth; i++) {
int r, g, b;
r = getc(fp) / red_scale;
g = getc(fp) / green_scale;
b = getc(fp) / blue_scale;
*lpCP = (r << red_shift) | (g << green_shift) |
(b << blue_shift);
lpCP++;
}
}
break;
default:
/*
* This wasn't a format I recognize
*/
lpDDS->lpVtbl->Unlock(lpDDS, NULL);
fclose(fp);
lpDDS->lpVtbl->Release(lpDDS);
D3DAppISetErrorString("Unknown pixel format (loadtex).");
return NULL;
}
/*
* Unlock the texture and return the surface pointer
*/
lpDDS->lpVtbl->Unlock(lpDDS, NULL);
fclose(fp);
return (lpDDS);
}
/*
* We assume the 8-bit palettized case
*/
color_count = 0; /* number of colors in the texture */
for (j = 0; j < (int)dwHeight; j++) {
/*
* Point to next row in surface
*/
lpC = ((char*)ddsd.lpSurface) + ddsd.lPitch * j;
for (i = 0; i < (int)dwWidth; i++) {
int r, g, b, k;
/*
* Get the next red, green and blue values and turn them into a
* D3DCOLOR
*/
r = getc(fp);
g = getc(fp);
b = getc(fp);
c = RGB_MAKE(r, g, b);
/*
* Search for this color in a table of colors in this texture
*/
for (k = 0; k < color_count; k++)
if (c == colors[k]) break;
if (k == color_count) {
/*
* This is a new color, so add it to the list
*/
color_count++;
/*
* More than 256 and we fail (8-bit)
*/
if (color_count > psize) {
color_count--;
k = color_count - 1;
//goto burst_colors;
}
colors[k] = c;
}
/*
* Set the "pixel" value on the surface to be the index into the
* color table
*/
if (psize == 16) {
if ((i & 1) == 0)
*lpC = k & 0xf;
else {
*lpC |= (k & 0xf) << 4;
lpC++;
}
} else {
*lpC = (char)k;
lpC++;
}
}
}
/*
* Close the file and unlock the surface
*/
fclose(fp);
lpDDS->lpVtbl->Unlock(lpDDS, NULL);
//burst_colors:
if (color_count > psize) {
/*
* If there are more than 256 colors, we overran our palette
*/
lpDDS->lpVtbl->Unlock(lpDDS, NULL);
lpDDS->lpVtbl->Release(lpDDS);
D3DAppISetErrorString("Palette burst. (loadtex).\n");
return (NULL);
}
/*
* Create a palette with the colors in our color table
*/
memset(ppe, 0, sizeof(PALETTEENTRY) * 256);
for (i = 0; i < color_count; i++) {
ppe[i].peRed = (unsigned char)RGB_GETRED(colors[i]);
ppe[i].peGreen = (unsigned char)RGB_GETGREEN(colors[i]);
ppe[i].peBlue = (unsigned char)RGB_GETBLUE(colors[i]);
}
/*
* Set all remaining entry flags to D3DPAL_RESERVED, which are ignored by
* the renderer.
*/
for (; i < 256; i++)
ppe[i].peFlags = D3DPAL_RESERVED;
/*
* Create the palette with the DDPCAPS_ALLOW256 flag because we want to
* have access to all entries.
*/
ddrval = lpDD->lpVtbl->CreatePalette(lpDD,
DDPCAPS_INITIALIZE | pcaps,
ppe, &lpDDPal, NULL);
if (ddrval != DD_OK) {
lpDDS->lpVtbl->Release(lpDDS);
D3DAppISetErrorString("Create palette failed while loading surface (loadtex).\n%s",
D3DAppErrorToString(ddrval));
return (NULL);
}
/*
* Finally, bind the palette to the surface
*/
ddrval = lpDDS->lpVtbl->SetPalette(lpDDS, lpDDPal);
if (ddrval != DD_OK) {
lpDDS->lpVtbl->Release(lpDDS);
lpDDPal->lpVtbl->Release(lpDDPal);
D3DAppISetErrorString("SetPalette failed while loading surface (loadtex).\n%s",
D3DAppErrorToString(ddrval));
return (NULL);
}
lpDDPal->lpVtbl->Release(lpDDPal);
return lpDDS;
}

1039
src/win95/db.c Normal file

File diff suppressed because it is too large Load diff

363
src/win95/db.h Normal file
View file

@ -0,0 +1,363 @@
/* ******************************************************************** *
* *
* DB.H - Header for debugging functions and macros. *
* *
* By: Garry Lancaster Version: 2.0 *
* *
* ******************************************************************** */
/* N O T E S ********************************************************** */
/* Define NDEBUG here to switch off all debugging. */
/* Set the DB_LEVEL here or before this file is included. Most db macros
* have a level from 1 to 5. They
* will only compile to code if the DB_LEVEL is at or greater than their
* level, otherwise they will be translated to ((void) 0) (i.e. no
* code.). The levels should be used as follows:
*
* 1 - Very low cost debugging. Negligible speed penalty. Could easily
* be left in a finished game.
* 2 - Low cost debugging. Small speed penalty. Use during development
* for well-tested code.
* 3 - Medium cost debugging. Obvious but tolerable speed penalty. Use
* during development most of the time.
* 4 - High cost debugging. Large speed penalty. Use during development
* when actively bug hunting.
* 5 - Very high cost debugging. Massive speed penalty. Use when trying
* to track down one of THOSE bugs.
*
* The level of a macro is part of its name e.g. to code a db_assert
* that fires at level 3 or above, use db_assert3().
*/
#pragma once
/* If you do not set the DB_LEVEL, it is set for you: to 3 */
#ifndef DB_LEVEL
#define DB_LEVEL 3
#endif
/* N.B. If NDEBUG is set, it over-rides DB_LEVEL and switches off all
* debugging.
*/
#ifdef NDEBUG
#undef DB_LEVEL
#define DB_LEVEL 0
#endif
/* Some db macros can be made optional dependent on the setting of the
* global variable db_option by appending _opt e.g. db_assert_opt(). The
* only code that is executed for any _opt macro if db_option is zero is
*
* if(db_option)
*
* However, this is still more than the macros controlled by the DB_LEVEL
* - if they are above the current DB_LEVEL they cause no code execution
* whatsoever. Therefore, avoid using _opt type macros inside extremely
* time critical code - use macros contolled by the DB_LEVEL instead,
* unless you are prepared to put up with the speed penalty.
* The only time that _opt type macros generate no code is when NDEBUG is
* defined.
*/
/* S T A R T W R A P P E R ****************************************** */
/* Avoid multiple inclusions of this file in a single source file. */
#ifndef DB_H_INCLUDED
#define DB_H_INCLUDED
/* I N C L U D E D S ************************************************** */
#include "advwin32.h"
#ifndef DB_NOWINDOWS
#include <windows.h>
#include "advwin32.h"
#endif
/* Permit use in a C++ source file. */
#ifdef __cplusplus
extern "C" {
#endif
/* ******************************************************************** *
* *
* I N T E R F A C E - both internal and external. *
* *
* ******************************************************************** */
/* C O N S T A N T S ************************************************** */
/* Possible values for the global variable, db_display_type. */
#define DB_DOS 0
#define DB_WINDOWS 1
#define DB_DIRECTDRAW 2
/* Possible values for the bltOrFlip field of db_dd_mode_tag structure. */
#define DB_FLIP 0
#define DB_BLT 1
/* M A C R O S ******************************************************** */
#if (!defined(DB_NOASSUME)) && defined(_MSC_VER) && (_MSC_VER >= 1200)
#define _db_assume(x) __assume(x)
#else
#define _db_assume(x) ((void)0)
#endif
#if DB_LEVEL >= 1
/* Fn like macro. */
#define db_set_mode(md, miP) db_set_mode_ex(md, miP, NULL)
#define db_set_log_file(strP) db_set_log_file_ex(strP)
#else
#define db_set_mode(md, miP) ((void) 0)
#define db_set_log_file(strP) ((void) 0)
#endif
/* Final use macros after testing of DB_LEVEL / db_option. */
#define db_assert_final(expr) \
((expr) ? ((void) 0) : db_assert_fail(#expr, __FILE__, __LINE__))
/* Macros whose compilation is conditional on the value of DB_LEVEL. */
#if DB_LEVEL >= 1
#define db_assert1(expr) db_assert_final(expr)
#define db_onlyassert1(expr) db_assert_final(expr)
#define db_verify1(expr) db_assert_final(expr)
#define db_print1(x, y, strP) db_print_fired(x, y, strP)
#define db_msg1(strP) db_msg_fired(strP)
#define db_log1(strP) db_log_fired(strP)
#define db_code1(code) code
#define db_printf1(params) db_printf_fired params
#define db_msgf1(params) db_msgf_fired params
#define db_logf1(params) db_logf_fired params
#else
#define db_assert1(expr) _db_assume(expr)
#define db_onlyassert1(__ignore) ((void) 0)
#define db_verify1(expr) (expr)
#define db_print1(x, y, __ignore) ((void) 0)
#define db_msg1(__ignore) _db_assume(0)
#define db_log1(__ignore) ((void) 0)
#define db_code1(__ignore)
#define db_printf1(x, y, __ignore) ((void) 0)
#define db_msgf1(__ignore) _db_assume(0)
#define db_logf1(__ignore) ((void) 0)
#endif
#if DB_LEVEL >= 2
#define db_assert2(expr) db_assert_final(expr)
#define db_onlyassert2(expr) db_assert_final(expr)
#define db_verify2(expr) db_assert_final(expr)
#define db_print2(x, y, strP) db_print_fired(x, y, strP)
#define db_msg2(strP) db_msg_fired(strP)
#define db_log2(strP) db_log_fired(strP)
#define db_code2(code) code
#define db_printf2(params) db_printf_fired params
#define db_msgf2(params) db_msgf_fired params
#define db_logf2(params) db_logf_fired params
#else
#define db_assert2(expr) _db_assume(expr)
#define db_onlyassert2(__ignore) ((void) 0)
#define db_verify2(expr) (expr)
#define db_print2(x, y, __ignore) ((void) 0)
#define db_msg2(__ignore) _db_assume(0)
#define db_log2(__ignore) ((void) 0)
#define db_code2(__ignore)
#define db_printf2(x, y, __ignore) ((void) 0)
#define db_msgf2(__ignore) _db_assume(0)
#define db_logf2(__ignore) ((void) 0)
#endif
#if DB_LEVEL >= 3
#define db_assert3(expr) db_assert_final(expr)
#define db_onlyassert3(expr) db_assert_final(expr)
#define db_verify3(expr) db_assert_final(expr)
#define db_print3(x, y, strP) db_print_fired(x, y, strP)
#define db_msg3(strP) db_msg_fired(strP)
#define db_log3(strP) db_log_fired(strP)
#define db_code3(code) code
#define db_printf3(params) db_printf_fired params
#define db_msgf3(params) db_msgf_fired params
#define db_logf3(params) db_logf_fired params
#else
#define db_assert3(expr) _db_assume(expr)
#define db_onlyassert3(__ignore) ((void) 0)
#define db_verify3(expr) (expr)
#define db_print3(x, y, __ignore) ((void) 0)
#define db_msg3(__ignore) _db_assume(0)
#define db_log3(__ignore) ((void) 0)
#define db_code3(__ignore)
#define db_printf3(x, y, __ignore) ((void) 0)
#define db_msgf3(__ignore) _db_assume(0)
#define db_logf3(__ignore) ((void) 0)
#endif
#if DB_LEVEL >= 4
#define db_assert4(expr) db_assert_final(expr)
#define db_onlyassert4(expr) db_assert_final(expr)
#define db_verify4(expr) db_assert_final(expr)
#define db_print4(x, y, strP) db_print_fired(x, y, strP)
#define db_msg4(strP) db_msg_fired(strP)
#define db_log4(strP) db_log_fired(strP)
#define db_code4(code) code
#define db_printf4(params) db_printf_fired params
#define db_msgf4(params) db_msgf_fired params
#define db_logf4(params) db_logf_fired params
#else
#define db_assert4(expr) _db_assume(expr)
#define db_onlyassert4(__ignore) ((void) 0)
#define db_verify4(expr) (expr)
#define db_print4(x, y, __ignore) ((void) 0)
#define db_msg4(__ignore) _db_assume(0)
#define db_log4(__ignore) ((void) 0)
#define db_code4(__ignore)
#define db_printf4(x, y, __ignore) ((void) 0)
#define db_msgf4(__ignore) _db_assume(0)
#define db_logf4(__ignore) ((void) 0)
#endif
#if DB_LEVEL >= 5
#define db_assert5(expr) db_assert_final(expr)
#define db_onlyassert5(expr) db_assert_final(expr)
#define db_verify5(expr) db_assert_final(expr)
#define db_print5(x, y, strP) db_print_fired(x, y, strP)
#define db_msg5(strP) db_msg_fired(strP)
#define db_log5(strP) db_log_fired(strP)
#define db_code5(code) code
#define db_printf5(params) db_printf_fired params
#define db_msgf5(params) db_msgf_fired params
#define db_logf5(params) db_logf_fired params
#else
#define db_assert5(expr) _db_assume(expr)
#define db_onlyassert5(__ignore) ((void) 0)
#define db_verify5(expr) (expr)
#define db_print5(x, y, __ignore) ((void) 0)
#define db_msg5(__ignore) _db_assume(0)
#define db_log5(__ignore) ((void) 0)
#define db_code5(__ignore)
#define db_printf5(x, y, __ignore) ((void) 0)
#define db_msgf5(__ignore) _db_assume(0)
#define db_logf5(__ignore) ((void) 0)
#endif
/* Macros which fire if db_option is non-zero (and NDEBUG is not
* defined).
*/
#ifndef NDEBUG
#define db_assert_opt(expr) if(db_option) db_assert_final(expr)
#define db_onlyassert_opt(expr) if(db_option) db_assert_final(expr)
#define db_verify_opt(expr) ((db_option) ? db_assert_final(expr) : (expr))
#define db_print_opt(x, y, strP) if(db_option) db_print_fired(x, y, strP)
#define db_msg_opt(strP) if(db_option) db_msg_fired(strP)
#define db_log_opt(strP) if(db_option) db_log_fired(strP)
#define db_code_opt(code) if(db_option) code
#define db_printf_opt(params) if(db_option) db_printf_fired params
#define db_msgf_opt(params) if(db_option) db_msgf_fired params
#define db_logf_opt(params) if(db_option) db_logf_fired params
#else
#define db_assert_opt(expr) _db_assume(expr)
#define db_onlyassert_opt(__ignore) ((void) 0)
#define db_verify_opt(expr) (expr)
#define db_print_opt(x,y,__ignore) ((void) 0)
#define db_msg_opt(__ignore) _db_assume(0)
#define db_log_opt(__ignore) ((void) 0)
#define db_code_opt(code)
#define db_printf_opt(params) ((void) 0)
#define db_msgf_opt(params) _db_assume(0)
#define db_logf_opt(params) ((void) 0)
#endif
/* Macros for setting and getting db_option. */
#ifndef NDEBUG
#define db_option_set(status) db_option = (status)
#define db_option_on() db_option = 1
#define db_option_off() db_option = 0
#define db_option_get() (db_option)
#else
#define db_option_set(__ignore) ((void) 0)
#define db_option_on() ((void) 0)
#define db_option_off() ((void) 0)
#define db_option_get() (0)
#endif
/* T Y P E S ********************************************************** */
struct db_dd_mode_tag
{
void *directDrawP;
void *visibleSurfaceP;
void *drawSurfaceP;
int width, height, bitsPerPixel;
unsigned short foreCol, backCol;
int bltOrFlip;
int bltXOffset, bltYOffset;
};
/* P R O T O S ******************************************************** */
/* Don't prototype anything or declare globals if NDEBUG is defined. */
#ifndef NDEBUG
/* New formatted debugging fns. */
extern void __cdecl db_logf_fired(const char *fmtStrP, ...);
extern void __cdecl db_printf_fired(int x, int y, const char *fmtStrP, ...);
extern void __cdecl db_msgf_fired(const char *fmtStrP, ...);
/* Called whenever an assertion fails. */
extern void db_assert_fail(const char *exprP, const char *fileP, int line);
/* Displays a message and has the program pause until the user responds
* to it.
*/
extern void db_msg_fired(const char *strP);
/* Displays a message (on platforms that support positioning, at (x, y))
* and continues program execution immediately.
*/
extern void db_print_fired(int x, int y, const char *strP);
/* Writes a message to a log file. */
extern void db_log_fired(const char *strP);
/* Deletes the old log file, so that the log file only contains messages
* saved from this point on. Use ONCE at the start of any program that
* uses any of the db_log macros.
*/
extern void db_log_init(void);
/* Gets the current infomation needed for the display mode. Used to enable
* other code to use the same debugging stuff. The return value is modeInfoP
*/
extern int db_get_mode(void **modeInfoPP, void **FontPP);
/* Changes the log file name */
extern void db_set_log_file_ex(const char *strP);
/* Sets the display mode for the debugging functions to use. mode must
* be one of DB_DOS, DB_WINDOWS or DB_DIRECTDRAW. The modeInfoP parameter
* is NULL except for Direct Draw. The Last parameter can be NULL.
*/
extern void db_set_mode_ex(int mode, void *modeInfoP, void *newFontP);
/* Called to set whether exceptions or brakepoints are called. */
extern void DbUseBrakepoints(BOOL use_brakepoints);
/* Call this to de-allocate memory used to store the debugging font. This
* fn does nothing unless you are in DirectDraw mode, since this is the
* only mode which loads its own font. Calling this fn is not strictly
* necessary since the OS will de-allocate a process' outstanding dynamic
* memory allocations when it ends anyway. However, calling this fn is
* cleaner and avoids BoundsChecker hits.
*/
extern void db_uninit(void);
/* G L O B A L S ****************************************************** */
/* Should we expand _opt type macros? */
extern int db_option;
#endif /* of #ifndef NDEBUG */
/* E N D W R A P P E R ********************************************** */
/* Permit use in a C++ source file. */
#ifdef __cplusplus
}
#endif
/* Avoid multiple inclusions of this file in a single source file. */
#endif

2260
src/win95/dd_func.cpp Normal file

File diff suppressed because it is too large Load diff

122
src/win95/debuglog.cpp Normal file
View file

@ -0,0 +1,122 @@
#include <string.h>
#include <stdlib.h>
#include <windows.h>
#include "debuglog.hpp"
LogFile::LogFile(char const * const _fname) : fname(0) , ever_written(0)
{
FILE * fp = fopen(_fname,"w");
if (fp)
{
fclose(fp);
fname = new char[strlen(_fname)+1];
strcpy(fname,_fname);
return;
}
char const * path = getenv("TEMP");
if (!path) path = getenv("TMP");
if (!path) return;
fname = new char[strlen(path)+1+strlen(_fname)+1];
strcpy(fname,path);
strncat(fname,"\\",1);
strcat(fname,_fname);
fp = fopen(fname,"w");
if (fp)
fclose(fp);
else
{
delete[] fname;
fname = 0;
}
}
LogFile::~LogFile()
{
if (unwritten.size())
{
FILE * fp = fopen(fname,"a");
for (int attempt=0; !fp && attempt<10; ++attempt)
{
Sleep(100);
fp = fopen(fname,"a");
}
if (fp)
{
FlushOut(fp);
fclose(fp);
}
}
if (fname) delete[] fname;
}
LogFile & LogFile::operator = (LogFile const & l)
{
if (&l != this)
{
if (fname) delete[] fname;
if (l.fname)
{
fname = new char[strlen(l.fname)+1];
strcpy(fname,l.fname);
}
else
fname = 0;
unwritten = l.unwritten;
ever_written = l.ever_written;
}
return *this;
}
LogFile::LogFile(LogFile const & l)
: unwritten(l.unwritten)
, ever_written(l.ever_written)
{
if (l.fname)
{
fname = new char[strlen(l.fname)+1];
strcpy(fname,l.fname);
}
else
fname = 0;
}
void LogFile::FlushOut(FILE * fp)
{
while (unwritten.size())
{
char * str = unwritten.first_entry();
unwritten.delete_first_entry();
fputs(str,fp);
delete[] str;
}
}
int vlfprintf(LOGFILE * lfp, char const * format, va_list args )
{
return lfp->vlprintf(format,args);
}
int lfprintf(LOGFILE * lfp, char const * format, ... )
{
va_list ap;
va_start(ap, format);
int rv = lfp->vlprintf(format,ap);
va_end(ap);
return rv;
}
int lfputs(LOGFILE * lfp, char const * str)
{
return lfp->lputs(str);
}
LOGFILE * lfopen(char const * fname)
{
return new LogFile(fname);
}
void lfclose(LOGFILE * lfp)
{
delete lfp;
}

26
src/win95/debuglog.h Normal file
View file

@ -0,0 +1,26 @@
#ifndef _included_debuglog_h_
#define _included_debuglog_h_
#ifdef __cplusplus
extern "C" {
#endif
#include <stdarg.h>
typedef struct LogFile LOGFILE;
int vlfprintf(LOGFILE * lfp, char const * format, va_list args );
int lfprintf(LOGFILE * lfp, char const * format, ... );
int lfputs(LOGFILE * lfp, char const * str);
LOGFILE * lfopen(char const * fname);
void lfclose(LOGFILE * lfp);
#ifdef __cplusplus
}
#endif
#endif /* ! _included_debuglog_h_ */

179
src/win95/debuglog.hpp Normal file
View file

@ -0,0 +1,179 @@
#ifndef _included_debuglog_hpp_
#define _included_debuglog_hpp_
#include <stdio.h>
#include "debuglog.h"
#include "list_tem.hpp"
/* Changed 27/1/98 by DHM:
-----------------------
Made LogFile derived from R_DumpContext rather than being a base class.
This is in order to give a clean interface for debug dumps to e.g. the
screen, with the same interface as to a log file. This base class will
perform an analagous role to the class CDumpContext in the Microsoft
Foundation Class library.
The virtual functions dputs(), dprintf() and vdprintf() will eventually replace
lputs(), lprintf() and vlprintf().
For the moment I've copied and pasted the implementations of both. I would prefer
in the short term to make one call the other, but this isn't easy with variable
arguments. In the long term I want to eliminate the l* functions (lputs() etc)
but can't because of heritage code (and heritage libraries).
*/
#ifndef _dcontext_hpp
#include "dcontext.hpp"
#endif
struct LogFile : public R_DumpContext
{
private:
char * fname;
List<char *> unwritten;
int ever_written;
void FlushOut(FILE * fp);
public:
LogFile(char const * const _fname);
virtual ~LogFile();
LogFile & operator = (LogFile const & l);
LogFile(LogFile const & l);
// {{{ Virtual dump implementations:
inline int dputs(char const * const buf)
{
if (!fname) return EOF;
FILE * fp = fopen(fname,"a");
if (!fp)
{
if (!ever_written) return EOF;
char * newtxt = new char [strlen(buf)+1];
strcpy(newtxt,buf);
unwritten.add_entry_end(newtxt);
return 0;
}
if (unwritten.size()) FlushOut(fp);
ever_written = 1;
int rv = fputs(buf,fp);
fclose(fp);
return rv;
}
inline int dprintf(char const * format, ... )
{
if (!fname) return -1;
FILE * fp = fopen(fname,"a");
if (!fp && !ever_written) return -1;
va_list ap;
va_start(ap, format);
int rv;
if (fp)
{
if (unwritten.size()) FlushOut(fp);
rv = vfprintf(fp,format,ap);
ever_written = 1;
}
else
{
char buf[4096];
rv = vsprintf(buf,format,ap);
char * newtxt = new char [strlen(buf)+1];
strcpy(newtxt,buf);
unwritten.add_entry_end(newtxt);
}
va_end(ap);
if (fp) fclose(fp);
return rv;
}
inline int vdprintf(char const * format, va_list ap)
{
if (!fname) return -1;
FILE * fp = fopen(fname,"a");
if (!fp && !ever_written) return -1;
int rv;
if (fp)
{
if (unwritten.size()) FlushOut(fp);
rv = vfprintf(fp,format,ap);
ever_written = 1;
fclose(fp);
}
else
{
char buf[4096];
rv = vsprintf(buf,format,ap);
char * newtxt = new char [strlen(buf)+1];
strcpy(newtxt,buf);
unwritten.add_entry_end(newtxt);
}
return rv;
}
// }}}
// {{{ Deprecated logging functions:
inline int lputs(char const * const buf)
{
return dputs(buf);
}
inline int lprintf(char const * format, ... )
{
if (!fname) return -1;
FILE * fp = fopen(fname,"a");
if (!fp && !ever_written) return -1;
va_list ap;
va_start(ap, format);
int rv;
if (fp)
{
if (unwritten.size()) FlushOut(fp);
rv = vfprintf(fp,format,ap);
ever_written = 1;
}
else
{
char buf[4096];
rv = vsprintf(buf,format,ap);
char * newtxt = new char [strlen(buf)+1];
strcpy(newtxt,buf);
unwritten.add_entry_end(newtxt);
}
va_end(ap);
if (fp) fclose(fp);
return rv;
}
inline int vlprintf(char const * format, va_list ap)
{
if (!fname) return -1;
FILE * fp = fopen(fname,"a");
if (!fp && !ever_written) return -1;
int rv;
if (fp)
{
if (unwritten.size()) FlushOut(fp);
rv = vfprintf(fp,format,ap);
ever_written = 1;
fclose(fp);
}
else
{
char buf[4096];
rv = vsprintf(buf,format,ap);
char * newtxt = new char [strlen(buf)+1];
strcpy(newtxt,buf);
unwritten.add_entry_end(newtxt);
}
return rv;
}
// }}}
};
#endif // ! _included_debuglog_hpp_

1344
src/win95/di_func.cpp Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,181 @@
#include "DummyObjectChunk.hpp"
#ifdef cencon
#define new my_new
#endif
//macro for helping to force inclusion of chunks when using libraries
FORCE_CHUNK_INCLUDE_IMPLEMENT(dummyobjectchunk)
RIF_IMPLEMENT_DYNCREATE("DUMMYOBJ",Dummy_Object_Chunk)
CHUNK_WITH_CHILDREN_LOADER("DUMMYOBJ",Dummy_Object_Chunk)
/*
Children for Dummy_Object_Chunk :
"DUMOBJDT" Dummy_Object_Data_Chunk
"DUMOBJTX" Dummy_Object_Text_Chunk
*/
Dummy_Object_Chunk::Dummy_Object_Chunk(Chunk_With_Children* parent,const char* _name,ChunkVectorInt& _location,ChunkVectorInt& min ,ChunkVectorInt& max ,ChunkQuat& orient)
:Chunk_With_Children(parent,"DUMMYOBJ")
{
new Dummy_Object_Data_Chunk(this,_name,_location,min,max,orient);
}
Dummy_Object_Data_Chunk* Dummy_Object_Chunk::get_data_chunk()
{
return (Dummy_Object_Data_Chunk*) lookup_single_child("DUMOBJDT");
}
const char* Dummy_Object_Chunk::get_text()
{
//find the text
Dummy_Object_Text_Chunk* text_chunk = (Dummy_Object_Text_Chunk*) lookup_single_child("DUMOBJTX");
if(!text_chunk)
{
//no text
return NULL;
}
return text_chunk->get_text();
}
void Dummy_Object_Chunk::set_text(const char* text)
{
//find the text chunk
Dummy_Object_Text_Chunk* text_chunk = (Dummy_Object_Text_Chunk*) lookup_single_child("DUMOBJTX");
if(!text || strlen(text)==0)
{
//delete the text chunk if it exists
delete text_chunk;
}
else
{
if(text_chunk)
{
//alter the existing text
text_chunk->set_text(text);
}
else
{
//create a new text chunk
new Dummy_Object_Text_Chunk(this,text);
}
}
}
//////////////////////////////Dummy_Object_Data_Chunk////////////////////////////////
RIF_IMPLEMENT_DYNCREATE("DUMOBJDT",Dummy_Object_Data_Chunk)
Dummy_Object_Data_Chunk::Dummy_Object_Data_Chunk(Dummy_Object_Chunk* parent,const char* _name ,ChunkVectorInt& _location,ChunkVectorInt& min ,ChunkVectorInt& max ,ChunkQuat& orient)
:Chunk(parent,"DUMOBJDT")
{
location=_location;
min_extents=min;
max_extents=max;
orientation=orient;
name=new char[strlen(_name)+1];
strcpy(name,_name);
}
Dummy_Object_Data_Chunk::Dummy_Object_Data_Chunk(Chunk_With_Children* parent,const char* data,size_t)
:Chunk(parent,"DUMOBJDT")
{
CHUNK_EXTRACT(location,ChunkVectorInt)
CHUNK_EXTRACT(min_extents,ChunkVectorInt)
CHUNK_EXTRACT(max_extents,ChunkVectorInt)
CHUNK_EXTRACT(orientation,ChunkQuat)
CHUNK_EXTRACT_STRING(name)
}
Dummy_Object_Data_Chunk::~Dummy_Object_Data_Chunk()
{
if(name) delete [] name;
}
void Dummy_Object_Data_Chunk::fill_data_block(char* data)
{
CHUNK_FILL_START
CHUNK_FILL(location,ChunkVectorInt)
CHUNK_FILL(min_extents,ChunkVectorInt)
CHUNK_FILL(max_extents,ChunkVectorInt)
CHUNK_FILL(orientation,ChunkQuat)
CHUNK_FILL_STRING(name)
}
size_t Dummy_Object_Data_Chunk::size_chunk()
{
chunk_size=12+3*sizeof(ChunkVectorInt)+sizeof(ChunkQuat);
chunk_size+=(strlen(name)+4)&~3;
return chunk_size;
}
/////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////Dummy_Object_Text_Chunk////////////////////////////////
RIF_IMPLEMENT_DYNCREATE("DUMOBJTX",Dummy_Object_Text_Chunk)
Dummy_Object_Text_Chunk::Dummy_Object_Text_Chunk(Dummy_Object_Chunk* parent,const char* _text)
:Chunk(parent,"DUMOBJTX"),text(NULL)
{
set_text(_text);
}
Dummy_Object_Text_Chunk::Dummy_Object_Text_Chunk(Chunk_With_Children* parent,const char* data,size_t)
:Chunk(parent,"DUMOBJTX")
{
CHUNK_EXTRACT_STRING(text)
}
Dummy_Object_Text_Chunk::~Dummy_Object_Text_Chunk()
{
delete [] text;
}
void Dummy_Object_Text_Chunk::fill_data_block(char* data)
{
CHUNK_FILL_START
CHUNK_FILL_STRING(text)
}
void Dummy_Object_Text_Chunk::set_text(const char* _text)
{
char* new_text = NULL;
if(_text)
{
new_text = new char[strlen(_text)+1];
strcpy(new_text,_text);
}
delete [] text;
text = new_text;
}
size_t Dummy_Object_Text_Chunk::size_chunk()
{
chunk_size=12;
if(text)
chunk_size+=(strlen(text)+4)&~3;
else
chunk_size+=4;
return chunk_size;
}

View file

@ -0,0 +1,81 @@
#ifndef _DummyObjectChunk_hpp
#define _DummyObjectChunk_hpp 1
#include "chunk.hpp"
#include "list_tem.hpp"
#include "chnktype.hpp"
class Dummy_Object_Data_Chunk;
class Dummy_Object_Chunk : public Chunk_With_Children
{
public:
Dummy_Object_Chunk(Chunk_With_Children* parent,const char* _name ,ChunkVectorInt& _location,ChunkVectorInt& min ,ChunkVectorInt& max ,ChunkQuat& orient);
// constructor from buffer
Dummy_Object_Chunk (Chunk_With_Children * const parent,const char *, size_t const);
Dummy_Object_Data_Chunk * get_data_chunk();//gets data chunk (name and location)
const char* get_text(); //get text attached to a dummy object
void set_text(const char* text); //change the text attached to a dummy object
};
//chunk containing name and location of dummy object
class Dummy_Object_Data_Chunk : public Chunk
{
public :
Dummy_Object_Data_Chunk(Dummy_Object_Chunk* parent,const char* _name ,ChunkVectorInt& _location,ChunkVectorInt& min ,ChunkVectorInt& max ,ChunkQuat& orient);
Dummy_Object_Data_Chunk (Chunk_With_Children * parent, const char * data, size_t );
~Dummy_Object_Data_Chunk();
/*------------------------**
** Main dummy object data **
**------------------------*/
char* name;
ChunkVectorInt location;
ChunkQuat orientation;
ChunkVectorInt min_extents;
ChunkVectorInt max_extents;
/*------------------------**
** Main dummy object data **
**------------------------*/
size_t size_chunk();
void fill_data_block (char * data);
private :
friend class Dummy_Object_Chunk;
};
//contains the 'user text' from 3dsmax
class Dummy_Object_Text_Chunk : public Chunk
{
public :
Dummy_Object_Text_Chunk(Dummy_Object_Chunk* parent,const char* _text);
Dummy_Object_Text_Chunk(Chunk_With_Children * parent, const char * data, size_t );
~Dummy_Object_Text_Chunk();
size_t size_chunk();
void fill_data_block (char * data);
const char* get_text() {return text;}
void set_text(const char* _text);
private :
char* text;
};
#endif

389
src/win95/dxlog.c Normal file
View file

@ -0,0 +1,389 @@
#include "3dc.h"
#if debug
#include "ourasert.h"
#include "dxlog.h"
#include "debuglog.h"
/*
* D3DAppErrorToString
*/
static char*
D3DAppErrorToString(HRESULT error)
{
switch(error) {
case DD_OK:
return "No error.\0";
case DDERR_ALREADYINITIALIZED:
return "This object is already initialized.\0";
case DDERR_BLTFASTCANTCLIP:
return "Return if a clipper object is attached to the source surface passed into a BltFast call.\0";
case DDERR_CANNOTATTACHSURFACE:
return "This surface can not be attached to the requested surface.\0";
case DDERR_CANNOTDETACHSURFACE:
return "This surface can not be detached from the requested surface.\0";
case DDERR_CANTCREATEDC:
return "Windows can not create any more DCs.\0";
case DDERR_CANTDUPLICATE:
return "Can't duplicate primary & 3D surfaces, or surfaces that are implicitly created.\0";
case DDERR_CLIPPERISUSINGHWND:
return "An attempt was made to set a cliplist for a clipper object that is already monitoring an hwnd.\0";
case DDERR_COLORKEYNOTSET:
return "No src color key specified for this operation.\0";
case DDERR_CURRENTLYNOTAVAIL:
return "Support is currently not available.\0";
case DDERR_DIRECTDRAWALREADYCREATED:
return "A DirectDraw object representing this driver has already been created for this process.\0";
case DDERR_EXCEPTION:
return "An exception was encountered while performing the requested operation.\0";
case DDERR_EXCLUSIVEMODEALREADYSET:
return "An attempt was made to set the cooperative level when it was already set to exclusive.\0";
case DDERR_GENERIC:
return "Generic failure.\0";
case DDERR_HEIGHTALIGN:
return "Height of rectangle provided is not a multiple of reqd alignment.\0";
case DDERR_HWNDALREADYSET:
return "The CooperativeLevel HWND has already been set. It can not be reset while the process has surfaces or palettes created.\0";
case DDERR_HWNDSUBCLASSED:
return "HWND used by DirectDraw CooperativeLevel has been subclassed, this prevents DirectDraw from restoring state.\0";
case DDERR_IMPLICITLYCREATED:
return "This surface can not be restored because it is an implicitly created surface.\0";
case DDERR_INCOMPATIBLEPRIMARY:
return "Unable to match primary surface creation request with existing primary surface.\0";
case DDERR_INVALIDCAPS:
return "One or more of the caps bits passed to the callback are incorrect.\0";
case DDERR_INVALIDCLIPLIST:
return "DirectDraw does not support the provided cliplist.\0";
case DDERR_INVALIDDIRECTDRAWGUID:
return "The GUID passed to DirectDrawCreate is not a valid DirectDraw driver identifier.\0";
case DDERR_INVALIDMODE:
return "DirectDraw does not support the requested mode.\0";
case DDERR_INVALIDOBJECT:
return "DirectDraw received a pointer that was an invalid DIRECTDRAW object.\0";
case DDERR_INVALIDPARAMS:
return "One or more of the parameters passed to the function are incorrect.\0";
case DDERR_INVALIDPIXELFORMAT:
return "The pixel format was invalid as specified.\0";
case DDERR_INVALIDPOSITION:
return "Returned when the position of the overlay on the destination is no longer legal for that destination.\0";
case DDERR_INVALIDRECT:
return "Rectangle provided was invalid.\0";
case DDERR_LOCKEDSURFACES:
return "Operation could not be carried out because one or more surfaces are locked.\0";
case DDERR_NO3D:
return "There is no 3D present.\0";
case DDERR_NOALPHAHW:
return "Operation could not be carried out because there is no alpha accleration hardware present or available.\0";
case DDERR_NOBLTHW:
return "No blitter hardware present.\0";
case DDERR_NOCLIPLIST:
return "No cliplist available.\0";
case DDERR_NOCLIPPERATTACHED:
return "No clipper object attached to surface object.\0";
case DDERR_NOCOLORCONVHW:
return "Operation could not be carried out because there is no color conversion hardware present or available.\0";
case DDERR_NOCOLORKEY:
return "Surface doesn't currently have a color key\0";
case DDERR_NOCOLORKEYHW:
return "Operation could not be carried out because there is no hardware support of the destination color key.\0";
case DDERR_NOCOOPERATIVELEVELSET:
return "Create function called without DirectDraw object method SetCooperativeLevel being called.\0";
case DDERR_NODC:
return "No DC was ever created for this surface.\0";
case DDERR_NODDROPSHW:
return "No DirectDraw ROP hardware.\0";
case DDERR_NODIRECTDRAWHW:
return "A hardware-only DirectDraw object creation was attempted but the driver did not support any hardware.\0";
case DDERR_NOEMULATION:
return "Software emulation not available.\0";
case DDERR_NOEXCLUSIVEMODE:
return "Operation requires the application to have exclusive mode but the application does not have exclusive mode.\0";
case DDERR_NOFLIPHW:
return "Flipping visible surfaces is not supported.\0";
case DDERR_NOGDI:
return "There is no GDI present.\0";
case DDERR_NOHWND:
return "Clipper notification requires an HWND or no HWND has previously been set as the CooperativeLevel HWND.\0";
case DDERR_NOMIRRORHW:
return "Operation could not be carried out because there is no hardware present or available.\0";
case DDERR_NOOVERLAYDEST:
return "Returned when GetOverlayPosition is called on an overlay that UpdateOverlay has never been called on to establish a destination.\0";
case DDERR_NOOVERLAYHW:
return "Operation could not be carried out because there is no overlay hardware present or available.\0";
case DDERR_NOPALETTEATTACHED:
return "No palette object attached to this surface.\0";
case DDERR_NOPALETTEHW:
return "No hardware support for 16 or 256 color palettes.\0";
case DDERR_NORASTEROPHW:
return "Operation could not be carried out because there is no appropriate raster op hardware present or available.\0";
case DDERR_NOROTATIONHW:
return "Operation could not be carried out because there is no rotation hardware present or available.\0";
case DDERR_NOSTRETCHHW:
return "Operation could not be carried out because there is no hardware support for stretching.\0";
case DDERR_NOT4BITCOLOR:
return "DirectDrawSurface is not in 4 bit color palette and the requested operation requires 4 bit color palette.\0";
case DDERR_NOT4BITCOLORINDEX:
return "DirectDrawSurface is not in 4 bit color index palette and the requested operation requires 4 bit color index palette.\0";
case DDERR_NOT8BITCOLOR:
return "DirectDrawSurface is not in 8 bit color mode and the requested operation requires 8 bit color.\0";
case DDERR_NOTAOVERLAYSURFACE:
return "Returned when an overlay member is called for a non-overlay surface.\0";
case DDERR_NOTEXTUREHW:
return "Operation could not be carried out because there is no texture mapping hardware present or available.\0";
case DDERR_NOTFLIPPABLE:
return "An attempt has been made to flip a surface that is not flippable.\0";
case DDERR_NOTFOUND:
return "Requested item was not found.\0";
case DDERR_NOTLOCKED:
return "Surface was not locked. An attempt to unlock a surface that was not locked at all, or by this process, has been attempted.\0";
case DDERR_NOTPALETTIZED:
return "The surface being used is not a palette-based surface.\0";
case DDERR_NOVSYNCHW:
return "Operation could not be carried out because there is no hardware support for vertical blank synchronized operations.\0";
case DDERR_NOZBUFFERHW:
return "Operation could not be carried out because there is no hardware support for zbuffer blitting.\0";
case DDERR_NOZOVERLAYHW:
return "Overlay surfaces could not be z layered based on their BltOrder because the hardware does not support z layering of overlays.\0";
case DDERR_OUTOFCAPS:
return "The hardware needed for the requested operation has already been allocated.\0";
case DDERR_OUTOFMEMORY:
return "DirectDraw does not have enough memory to perform the operation.\0";
case DDERR_OUTOFVIDEOMEMORY:
return "DirectDraw does not have enough video memory to perform the operation.\0";
case DDERR_OVERLAYCANTCLIP:
return "The hardware does not support clipped overlays.\0";
case DDERR_OVERLAYCOLORKEYONLYONEACTIVE:
return "Can only have ony color key active at one time for overlays.\0";
case DDERR_OVERLAYNOTVISIBLE:
return "Returned when GetOverlayPosition is called on a hidden overlay.\0";
case DDERR_PALETTEBUSY:
return "Access to this palette is being refused because the palette is already locked by another thread.\0";
case DDERR_PRIMARYSURFACEALREADYEXISTS:
return "This process already has created a primary surface.\0";
case DDERR_REGIONTOOSMALL:
return "Region passed to Clipper::GetClipList is too small.\0";
case DDERR_SURFACEALREADYATTACHED:
return "This surface is already attached to the surface it is being attached to.\0";
case DDERR_SURFACEALREADYDEPENDENT:
return "This surface is already a dependency of the surface it is being made a dependency of.\0";
case DDERR_SURFACEBUSY:
return "Access to this surface is being refused because the surface is already locked by another thread.\0";
case DDERR_SURFACEISOBSCURED:
return "Access to surface refused because the surface is obscured.\0";
case DDERR_SURFACELOST:
return "Access to this surface is being refused because the surface memory is gone. The DirectDrawSurface object representing this surface should have Restore called on it.\0";
case DDERR_SURFACENOTATTACHED:
return "The requested surface is not attached.\0";
case DDERR_TOOBIGHEIGHT:
return "Height requested by DirectDraw is too large.\0";
case DDERR_TOOBIGSIZE:
return "Size requested by DirectDraw is too large, but the individual height and width are OK.\0";
case DDERR_TOOBIGWIDTH:
return "Width requested by DirectDraw is too large.\0";
case DDERR_UNSUPPORTED:
return "Action not supported.\0";
case DDERR_UNSUPPORTEDFORMAT:
return "FOURCC format requested is unsupported by DirectDraw.\0";
case DDERR_UNSUPPORTEDMASK:
return "Bitmask in the pixel format requested is unsupported by DirectDraw.\0";
case DDERR_VERTICALBLANKINPROGRESS:
return "Vertical blank is in progress.\0";
case DDERR_WASSTILLDRAWING:
return "Informs DirectDraw that the previous Blt which is transfering information to or from this Surface is incomplete.\0";
case DDERR_WRONGMODE:
return "This surface can not be restored because it was created in a different mode.\0";
case DDERR_XALIGN:
return "Rectangle provided was not horizontally aligned on required boundary.\0";
case D3DERR_BADMAJORVERSION:
return "D3DERR_BADMAJORVERSION\0";
case D3DERR_BADMINORVERSION:
return "D3DERR_BADMINORVERSION\0";
case D3DERR_EXECUTE_LOCKED:
return "D3DERR_EXECUTE_LOCKED\0";
case D3DERR_EXECUTE_NOT_LOCKED:
return "D3DERR_EXECUTE_NOT_LOCKED\0";
case D3DERR_EXECUTE_CREATE_FAILED:
return "D3DERR_EXECUTE_CREATE_FAILED\0";
case D3DERR_EXECUTE_DESTROY_FAILED:
return "D3DERR_EXECUTE_DESTROY_FAILED\0";
case D3DERR_EXECUTE_LOCK_FAILED:
return "D3DERR_EXECUTE_LOCK_FAILED\0";
case D3DERR_EXECUTE_UNLOCK_FAILED:
return "D3DERR_EXECUTE_UNLOCK_FAILED\0";
case D3DERR_EXECUTE_FAILED:
return "D3DERR_EXECUTE_FAILED\0";
case D3DERR_EXECUTE_CLIPPED_FAILED:
return "D3DERR_EXECUTE_CLIPPED_FAILED\0";
case D3DERR_TEXTURE_NO_SUPPORT:
return "D3DERR_TEXTURE_NO_SUPPORT\0";
case D3DERR_TEXTURE_NOT_LOCKED:
return "D3DERR_TEXTURE_NOT_LOCKED\0";
case D3DERR_TEXTURE_LOCKED:
return "D3DERR_TEXTURELOCKED\0";
case D3DERR_TEXTURE_CREATE_FAILED:
return "D3DERR_TEXTURE_CREATE_FAILED\0";
case D3DERR_TEXTURE_DESTROY_FAILED:
return "D3DERR_TEXTURE_DESTROY_FAILED\0";
case D3DERR_TEXTURE_LOCK_FAILED:
return "D3DERR_TEXTURE_LOCK_FAILED\0";
case D3DERR_TEXTURE_UNLOCK_FAILED:
return "D3DERR_TEXTURE_UNLOCK_FAILED\0";
case D3DERR_TEXTURE_LOAD_FAILED:
return "D3DERR_TEXTURE_LOAD_FAILED\0";
case D3DERR_MATRIX_CREATE_FAILED:
return "D3DERR_MATRIX_CREATE_FAILED\0";
case D3DERR_MATRIX_DESTROY_FAILED:
return "D3DERR_MATRIX_DESTROY_FAILED\0";
case D3DERR_MATRIX_SETDATA_FAILED:
return "D3DERR_MATRIX_SETDATA_FAILED\0";
case D3DERR_SETVIEWPORTDATA_FAILED:
return "D3DERR_SETVIEWPORTDATA_FAILED\0";
case D3DERR_MATERIAL_CREATE_FAILED:
return "D3DERR_MATERIAL_CREATE_FAILED\0";
case D3DERR_MATERIAL_DESTROY_FAILED:
return "D3DERR_MATERIAL_DESTROY_FAILED\0";
case D3DERR_MATERIAL_SETDATA_FAILED:
return "D3DERR_MATERIAL_SETDATA_FAILED\0";
case D3DERR_LIGHT_SET_FAILED:
return "D3DERR_LIGHT_SET_FAILED\0";
case D3DRMERR_BADOBJECT:
return "D3DRMERR_BADOBJECT\0";
case D3DRMERR_BADTYPE:
return "D3DRMERR_BADTYPE\0";
case D3DRMERR_BADALLOC:
return "D3DRMERR_BADALLOC\0";
case D3DRMERR_FACEUSED:
return "D3DRMERR_FACEUSED\0";
case D3DRMERR_NOTFOUND:
return "D3DRMERR_NOTFOUND\0";
case D3DRMERR_NOTDONEYET:
return "D3DRMERR_NOTDONEYET\0";
case D3DRMERR_FILENOTFOUND:
return "The file was not found.\0";
case D3DRMERR_BADFILE:
return "D3DRMERR_BADFILE\0";
case D3DRMERR_BADDEVICE:
return "D3DRMERR_BADDEVICE\0";
case D3DRMERR_BADVALUE:
return "D3DRMERR_BADVALUE\0";
case D3DRMERR_BADMAJORVERSION:
return "D3DRMERR_BADMAJORVERSION\0";
case D3DRMERR_BADMINORVERSION:
return "D3DRMERR_BADMINORVERSION\0";
case D3DRMERR_UNABLETOEXECUTE:
return "D3DRMERR_UNABLETOEXECUTE\0";
default:
return "Unrecognized error value.\0";
}
}
#ifdef __WATCOMC__
#define LOGFILE_NAME "dx_error.log"
#else
#define LOGFILE_NAME "dx_errorM.log"
#endif
static LOGFILE * dxlog = 0;
static int closed_once = 0;
void dx_err_log(HRESULT error, int line, char const * file)
{
if (DD_OK==error) return;
if (closed_once) return;
if (!dxlog) dxlog = lfopen(LOGFILE_NAME);
lfprintf(dxlog,"Line %d of %s:\n%s\n\n",line,file,D3DAppErrorToString(error));
}
void dx_str_log(char const * str, int line, char const * file)
{
if (closed_once) return;
if (!dxlog) dxlog = lfopen(LOGFILE_NAME);
lfprintf(dxlog,"Line %d of %s:\n%s\n\n",line,file,str);
}
void dx_line_log(int line, char const * file)
{
if (closed_once) return;
if (!dxlog) dxlog = lfopen(LOGFILE_NAME);
lfprintf(dxlog,"Line %d of %s:\n",line,file);
}
void dx_strf_log(char const * fmt, ... )
{
if (closed_once) return;
if (!dxlog) dxlog = lfopen(LOGFILE_NAME);
{
va_list ap;
va_start(ap, fmt);
vlfprintf(dxlog,fmt,ap);
va_end(ap);
}
lfputs(dxlog,"\n\n");
}
#undef exit
int GlobalAssertFired(char * Filename, int LineNum,char * Condition)
{
extern void exit_break_point_fucntion ();
exit_break_point_fucntion();
if (closed_once) return 0;
if (!dxlog) dxlog = lfopen(LOGFILE_NAME);
lfprintf(dxlog,"Line %d of %s:\nGAF: %s\n",LineNum,Filename,Condition);
lfclose(dxlog);
closed_once = 1;
textprint("Line %d of %s:\nGAF: %s\n",LineNum,Filename,Condition);
WaitForReturn();
ExitSystem();
exit(0xffff);
}
int LocalAssertFired(char * Filename, int LineNum,char * Condition)
{
extern void exit_break_point_fucntion ();
exit_break_point_fucntion();
if (closed_once) return 0;
if (!dxlog) dxlog = lfopen(LOGFILE_NAME);
lfprintf(dxlog,"Line %d of %s:\nLAF: %s\n",LineNum,Filename,Condition);
lfclose(dxlog);
closed_once = 1;
textprint("Line %d of %s:\nLAF: %s\n",LineNum,Filename,Condition);
WaitForReturn();
ExitSystem();
exit(0xfffe);
}
void DXLOGHandleCompilerWarningMessage(void)
{
int temp;
temp = D3DRMMAP_PERSPCORRECT;
temp = D3DRMMAP_WRAPU;
temp = D3DRMMAP_WRAPV;
temp = D3DRMGROUP_ALLGROUPS;
}
void ExitFired(char* Filename, int LineNum, int ExitCode)
{
extern void exit_break_point_fucntion ();
exit_break_point_fucntion();
if (closed_once) return ;
if (!dxlog) dxlog = lfopen(LOGFILE_NAME);
lfprintf(dxlog,"Line %d of %s:\nExit: %x\n",LineNum,Filename,ExitCode);
lfclose(dxlog);
closed_once = 1;
exit(ExitCode);
}
#endif

37
src/win95/dxlog.h Normal file
View file

@ -0,0 +1,37 @@
#ifndef _included_dxlog_h_
#define _included_dxlog_h_
#include "system.h"
#include "ddraw.h"
#include "d3d.h"
#include "d3drm.h"
#ifdef __cplusplus
extern "C" {
#endif
#if debug
void dx_err_log(HRESULT error, int line, char const * file);
void dx_str_log(char const * str, int line, char const * file);
void dx_line_log(int line, char const * file);
void dx_strf_log(char const * fmt, ...);
#define LOGDXERR(error) dx_err_log(error,__LINE__,__FILE__)
#define LOGDXSTR(str) dx_str_log(str,__LINE__,__FILE__)
#define LOGDXFMT(args) (dx_line_log(__LINE__,__FILE__),dx_strf_log args)
#else
#define LOGDXERR(error) (void)0
#define LOGDXSTR(str) (void)0
#define LOGDXFMT(args) (void)0
#endif
#ifdef __cplusplus
}
#endif
#endif /* ! _included_dxlog_h_ */

131
src/win95/enumchnk.cpp Normal file
View file

@ -0,0 +1,131 @@
#include "enumchnk.hpp"
//#include "enumsch.hpp"
#ifdef cencon
#define new my_new
#endif
//macro for helping to force inclusion of chunks when using libraries
FORCE_CHUNK_INCLUDE_IMPLEMENT(enumchnk)
// Class Enum_Chunk functions
RIF_IMPLEMENT_DYNCREATE("REBENUMS",Enum_Chunk)
// constructor from buffer
LOCKABLE_CHUNK_WITH_CHILDREN_LOADER("REBENUMS",Enum_Chunk)
/*
Children for Enum_Chunk :
"ENUMHEAD" Enum_Header_Chunk
"BMPENUMS" BMP_Enums_Chunk
*/
// empty constructor
Enum_Chunk::Enum_Chunk (Chunk_With_Children * parent)
:Lockable_Chunk_With_Children (parent, "REBENUMS")
{
// as necessary, generated automatically
new Enum_Header_Chunk (this);
}
BOOL Enum_Chunk::file_equals (HANDLE & /*rif_file*/)
{
return(TRUE);
}
Enum_Header_Chunk * Enum_Chunk::get_header()
{
return (Enum_Header_Chunk *) this->lookup_single_child ("ENUMHEAD");
}
const char * Enum_Chunk::get_head_id()
{
Enum_Header_Chunk * hdptr = get_header();
if (!hdptr) return (0);
return(hdptr->identifier);
}
void Enum_Chunk::set_lock_user (char * user)
{
Enum_Header_Chunk * hdptr = get_header();
if (!hdptr) return;
strncpy (hdptr->lock_user, user,16);
hdptr->lock_user[16] = 0;
}
void Enum_Chunk::post_input_processing()
{
if (get_header())
if (get_header()->flags & GENERAL_FLAG_LOCKED)
external_lock = TRUE;
Chunk_With_Children::post_input_processing();
}
///////////////////////////////////////
// Class Enum_Header_Chunk functions
RIF_IMPLEMENT_DYNCREATE("ENUMHEAD",Enum_Header_Chunk)
// from buffer
Enum_Header_Chunk::Enum_Header_Chunk (Chunk_With_Children * parent, const char * hdata, size_t /*hsize*/)
: Chunk (parent, "ENUMHEAD"),
flags (0), version_no (0)
{
flags = *((int *) hdata);
strncpy (lock_user, (hdata + 4), 16);
lock_user[16] = '\0';
version_no = *((int *) (hdata + 20));
}
BOOL Enum_Header_Chunk::output_chunk (HANDLE & hand)
{
unsigned long junk;
BOOL ok;
char * data_block;
data_block = make_data_block_from_chunk();
ok = WriteFile (hand, (long *) data_block, (unsigned long) chunk_size, &junk, 0);
delete [] data_block;
if (!ok) return FALSE;
return TRUE;
}
void Enum_Header_Chunk::fill_data_block ( char * data_start)
{
strncpy (data_start, identifier, 8);
data_start += 8;
*((int *) data_start) = chunk_size;
data_start += 4;
*((int *) data_start) = flags;
strncpy ((data_start + 4), lock_user, 16);
*((int *) (data_start+20)) = version_no;
}
void Enum_Header_Chunk::prepare_for_output()
{
version_no ++;
}

82
src/win95/enumchnk.hpp Normal file
View file

@ -0,0 +1,82 @@
#ifndef _included_enumchnk_hpp_
#define _included_enumchnk_hpp_
#include "chunk.hpp"
#include "mishchnk.hpp"
class Enum_Header_Chunk;
class Enum_Chunk : public Lockable_Chunk_With_Children
{
public:
// empty constructor
Enum_Chunk (Chunk_With_Children * parent);
// constructor from buffer
Enum_Chunk (Chunk_With_Children * const parent,const char *, size_t const);
Enum_Header_Chunk * get_header();
// functions for the locking functionality
BOOL file_equals (HANDLE &);
const char * get_head_id();
void set_lock_user(char *);
void post_input_processing();
private:
friend class File_Chunk;
friend class GodFather_Chunk;
};
///////////////////////////////////////////////
class Enum_Header_Chunk : public Chunk
{
public:
// constructor from buffer
Enum_Header_Chunk (Chunk_With_Children * parent, const char * pdata, size_t psize);
virtual size_t size_chunk ()
{
chunk_size = 36;
return chunk_size;
}
virtual BOOL output_chunk (HANDLE &);
virtual void fill_data_block (char * data_start);
void prepare_for_output();
private:
friend class Enum_Chunk;
friend class File_Chunk;
int flags;
int version_no;
char lock_user[17];
// constructor from parent
Enum_Header_Chunk (Enum_Chunk * parent)
: Chunk (parent, "ENUMHEAD"),
flags (0), version_no (0)
{}
};
#endif // _included_enumchnk_hpp_

163
src/win95/enumsch.cpp Normal file
View file

@ -0,0 +1,163 @@
#include <string.h>
#include "enumsch.hpp"
#ifdef cencon
#define new my_new
#endif
//macro for helping to force inclusion of chunks when using libraries
FORCE_CHUNK_INCLUDE_IMPLEMENT(enumsch)
Enum_Constant::Enum_Constant(char const * const _cname, int const _value) : cname(0), value(_value), reserved(0)
{
if (_cname)
{
cname = new char[strlen(_cname)+1];
strcpy(cname,_cname);
}
}
Enum_Constant::Enum_Constant(Enum_Constant const & ec2) : reserved(ec2.reserved), value(ec2.value), cname(0)
{
if (ec2.cname)
{
cname = new char[strlen(ec2.cname)+1];
strcpy(cname,ec2.cname);
}
}
Enum_Constant & Enum_Constant::operator = (Enum_Constant const & ec2)
{
if (cname) delete[] cname;
cname = 0;
value = ec2.value;
reserved = ec2.reserved;
if (ec2.cname)
{
cname = new char[strlen(ec2.cname)+1];
strcpy(cname,ec2.cname);
}
return *this;
}
BOOL Enum_Constant::operator == (Enum_Constant const & ec2) const
{
if (cname && ec2.cname)
if (!strcmp(cname,ec2.cname)) return TRUE;
return FALSE;
}
BOOL Enum_Constant::operator != (Enum_Constant const & ec2) const
{
if (cname && ec2.cname)
if (!strcmp(cname,ec2.cname)) return FALSE;
return TRUE;
}
BOOL Enum_Constant::operator < (Enum_Constant const & ec2) const
{
if (cname && ec2.cname)
if (strcmp(cname,ec2.cname)<0) return TRUE;
return FALSE;
}
Enum_Constant::Enum_Constant(char const * sdata)
: value(*(int *)sdata), reserved(*(int *)(sdata+4)), cname(0)
{
sdata+=8;
if (*sdata)
{
cname = new char[strlen(sdata)+1];
strcpy(cname,sdata);
}
}
size_t Enum_Constant::size_chunk() const
{
return 8 + ((cname ? strlen(cname)+1 : 1) +3 &~3);
}
void Enum_Constant::fill_data_block (char * data_start)
{
*(int*)data_start = value;
*(int*)(data_start+4) = reserved;
data_start += 8;
strcpy(data_start,cname ? cname : "");
}
///////
RIF_IMPLEMENT_DYNCREATE("BMPENUMS",BMP_Enums_Chunk)
BMP_Enums_Chunk::BMP_Enums_Chunk(Chunk_With_Children * const parent, char const * sdata, size_t const /*ssize*/)
: Chunk(parent,"BMPENUMS")
, reserved1(*(int *)sdata)
, reserved2(*(int *)(sdata+4))
, ctype(0)
{
sdata+=8;
unsigned int const len = strlen(sdata)+1;
if (len>1)
{
ctype = new char[len];
strcpy(ctype,sdata);
}
sdata += len + 3 &~3;
unsigned int const enlistsize = *(int *)sdata;
sdata += 4;
for (unsigned int i = enlistsize; i; --i)
{
Enum_Constant current(sdata);
sdata += current.size_chunk();
enums.add_entry(current);
}
}
size_t BMP_Enums_Chunk::size_chunk ()
{
chunk_size = 12 + 8 + (ctype ? strlen(ctype)+1 : 1) + 4 +3 &~3;
for (LIF<Enum_Constant> li(&enums); !li.done(); li.next())
{
chunk_size += li().size_chunk();
}
return chunk_size;
}
void BMP_Enums_Chunk::fill_data_block (char * data_start)
{
strncpy (data_start, identifier, 8);
data_start += 8;
*(int *) data_start = chunk_size;
data_start += 4;
*(int*)data_start = reserved1;
*(int*)(data_start+4) = reserved2;
data_start += 8;
strcpy(data_start,ctype ? ctype : "");
data_start += strlen(data_start)+1 +3 &~3;
*(int *)data_start = enums.size();
data_start += 4;
for (LIF<Enum_Constant> li(&enums); !li.done(); li.next())
{
Enum_Constant current(li());
current.fill_data_block(data_start);
data_start += current.size_chunk();
}
}

91
src/win95/enumsch.hpp Normal file
View file

@ -0,0 +1,91 @@
#ifndef _included_enumsch_hpp_
#define _included_enumsch_hpp_
#include "chunk.hpp"
class Enum_Constant
{
public:
char * cname;
int value;
int reserved;
Enum_Constant() : cname(0), value(0), reserved(0) {}
~Enum_Constant()
{
if (cname) delete[] cname;
}
Enum_Constant(char const * const _cname, int const _value);
Enum_Constant(Enum_Constant const & ec2);
Enum_Constant & operator = (Enum_Constant const & ec2);
BOOL operator == (Enum_Constant const & ec2) const;
BOOL operator != (Enum_Constant const & ec2) const;
BOOL operator < (Enum_Constant const & ec2) const;
private:
friend class BMP_Enums_Chunk;
// constructor from buffer
Enum_Constant(char const * sdata);
size_t size_chunk() const;
void fill_data_block(char * data_start);
};
class Enum_Const_List
{
public:
List<Enum_Constant> enums;
virtual ~Enum_Const_List(){}
#if cencon
int lowest_free_index(void);
void Sort_By_Name(void);
#endif
};
class BMP_Enums_Chunk : public Chunk, public Enum_Const_List
{
public:
// constructor from buffer
BMP_Enums_Chunk (Chunk_With_Children * const parent, char const * sdata, size_t const ssize);
#if cencon
// empty constructor
BMP_Enums_Chunk (Chunk_With_Children * const parent)
: Chunk(parent,"BMPENUMS")
, ctype(0)
, reserved1(0)
, reserved2(0)
{}
#endif
~BMP_Enums_Chunk ()
{
if (ctype) delete[] ctype;
}
virtual size_t size_chunk ();
virtual void fill_data_block (char * data_start);
char * ctype;
int reserved1;
int reserved2;
// List<Enum_Constant> enums;
private:
friend class Enum_Chunk;
};
#endif // !_included_enumsch_hpp_

325
src/win95/envchunk.cpp Normal file
View file

@ -0,0 +1,325 @@
#include "chunk.hpp"
#include "envchunk.hpp"
//macro for helping to force inclusion of chunks when using libraries
FORCE_CHUNK_INCLUDE_IMPLEMENT(envchunk)
// Class Environment_Data_Chunk functions
RIF_IMPLEMENT_DYNCREATE("REBENVDT",Environment_Data_Chunk)
// constructor from buffer
LOCKABLE_CHUNK_WITH_CHILDREN_LOADER("REBENVDT",Environment_Data_Chunk)
/*
Children for Enviornment_Data_Chunk :
"ENVSDSCL" Environment_Scale_Chunk
"GAMEMODE" Environment_Game_Mode_Chunk
"ENVPALET" Environment_Palette_Chunk
"ENVTXLIT" Environment_TLT_Chunk
"TLTCONFG" TLT_Config_Chunk
"CLRLOOKP" Coloured_Polygons_Lookup_Chunk
"MATCHIMG" Matching_Images_Chunk
"BMPNAMES" Global_BMP_Name_Chunk
"BMNAMVER" BMP_Names_Version_Chunk
"BMNAMEXT" BMP_Names_ExtraData_Chunk
"RIFFNAME" RIF_Name_Chunk
"ENDTHEAD" Environment_Data_Header_Chunk
"LIGHTSET" Light_Set_Chunk
"PRSETPAL" Preset_Palette_Chunk
"SPECLOBJ" Special_Objects_Chunk
"AVPEXSTR" AVP_External_Strategy_Chunk
"BMPMD5ID" Bitmap_MD5_Chunk
"GLOGENDC" Global_Generator_Data_Chunk
"FRAGTYPE" Fragment_Type_Chunk
"ENVACOUS" Environment_Acoustics_Chunk
"AVPENVIR" AVP_Environment_Settings_Chunk
"SOUNDDIR" Sound_Directory_Chunk
"RANTEXID" Random_Texture_ID_Chunk
*/
// empty constructor
Environment_Data_Chunk::Environment_Data_Chunk (Chunk_With_Children * parent)
:Lockable_Chunk_With_Children (parent, "REBENVDT")
{
// as necessary, generated automatically
new Environment_Data_Header_Chunk (this);
}
BOOL Environment_Data_Chunk::file_equals (HANDLE & /*rif_file*/)
{
return(TRUE);
}
Environment_Data_Header_Chunk * Environment_Data_Chunk::get_header()
{
return (Environment_Data_Header_Chunk *) this->lookup_single_child ("ENDTHEAD");
}
const char * Environment_Data_Chunk::get_head_id()
{
Environment_Data_Header_Chunk * hdptr = get_header();
if (!hdptr) return (0);
return(hdptr->identifier);
}
void Environment_Data_Chunk::set_lock_user (char * user)
{
Environment_Data_Header_Chunk * hdptr = get_header();
if (!hdptr) return;
strncpy (hdptr->lock_user, user,16);
hdptr->lock_user[16] = 0;
}
void Environment_Data_Chunk::post_input_processing()
{
if (get_header())
if (get_header()->flags & GENERAL_FLAG_LOCKED)
external_lock = TRUE;
Chunk_With_Children::post_input_processing();
}
///////////////////////////////////////
// Class Environment_Data_Header_Chunk functions
RIF_IMPLEMENT_DYNCREATE("ENDTHEAD",Environment_Data_Header_Chunk)
// from buffer
Environment_Data_Header_Chunk::Environment_Data_Header_Chunk (Chunk_With_Children * parent, const char * hdata, size_t /*hsize*/)
: Chunk (parent, "ENDTHEAD"),
flags (0), version_no (0)
{
flags = *((int *) hdata);
strncpy (lock_user, (hdata + 4), 16);
lock_user[16] = '\0';
version_no = *((int *) (hdata + 20));
}
BOOL Environment_Data_Header_Chunk::output_chunk (HANDLE & hand)
{
unsigned long junk;
BOOL ok;
char * data_block;
data_block = make_data_block_from_chunk();
ok = WriteFile (hand, (long *) data_block, (unsigned long) chunk_size, &junk, 0);
delete [] data_block;
if (!ok) return FALSE;
return TRUE;
}
void Environment_Data_Header_Chunk::fill_data_block ( char * data_start)
{
strncpy (data_start, identifier, 8);
data_start += 8;
*((int *) data_start) = chunk_size;
data_start += 4;
*((int *) data_start) = flags;
strncpy ((data_start + 4), lock_user, 16);
*((int *) (data_start+20)) = version_no;
}
void Environment_Data_Header_Chunk::prepare_for_output()
{
version_no ++;
}
///////////////////////////////////////
// Class Environment_Scale_Chunk functions
RIF_IMPLEMENT_DYNCREATE("ENVSDSCL",Environment_Scale_Chunk)
void Environment_Scale_Chunk::fill_data_block ( char * data_start)
{
strncpy (data_start, identifier, 8);
data_start += 8;
*((int *) data_start) = chunk_size;
data_start += 4;
*((double *) data_start) = scale;
}
///////////////////////////////////////
RIF_IMPLEMENT_DYNCREATE("ENVACOUS",Environment_Acoustics_Chunk)
Environment_Acoustics_Chunk::Environment_Acoustics_Chunk(Environment_Data_Chunk* parent)
:Chunk(parent,"ENVACOUS")
{
env_index=0;
reverb=2;
spare=0;
}
Environment_Acoustics_Chunk::Environment_Acoustics_Chunk(Chunk_With_Children* parent,const char* data,size_t)
:Chunk(parent,"ENVACOUS")
{
env_index=*(int*)data;
data+=4;
reverb=*(float*)data;
data+=4;
spare=*(int*)data;
}
void Environment_Acoustics_Chunk::fill_data_block(char* data_start)
{
strncpy (data_start, identifier, 8);
data_start += 8;
*((int *) data_start) = chunk_size;
data_start += 4;
*(int*)data_start=env_index;
data_start+=4;
*(float*)data_start=reverb;
data_start+=4;
*(int*)data_start=spare;
}
///////////////////////////////////////
RIF_IMPLEMENT_DYNCREATE("SOUNDDIR",Sound_Directory_Chunk)
Sound_Directory_Chunk::Sound_Directory_Chunk(Environment_Data_Chunk* parent,const char* dir)
:Chunk(parent,"SOUNDDIR")
{
directory=new char[strlen(dir)+1];
strcpy(directory,dir);
}
Sound_Directory_Chunk::Sound_Directory_Chunk(Chunk_With_Children * const parent, const char* data, size_t const )
:Chunk(parent,"SOUNDDIR")
{
directory=new char[strlen(data)+1];
strcpy(directory,data);
}
Sound_Directory_Chunk::~Sound_Directory_Chunk()
{
delete [] directory;
}
void Sound_Directory_Chunk::fill_data_block(char* data_start)
{
strncpy (data_start, identifier, 8);
data_start += 8;
*((int *) data_start) = chunk_size;
data_start += 4;
strcpy(data_start,directory);
}
///////////////////////////////////////
/////////////////////Available shape set collections////////////////////////////////////////
RIF_IMPLEMENT_DYNCREATE("RANTEXID",Random_Texture_ID_Chunk)
Random_Texture_ID_Chunk::Random_Texture_ID_Chunk(Chunk_With_Children* parent,const char* _name)
:Chunk(parent,"RANTEXID")
{
name=new char[strlen(_name)+1];
strcpy(name,_name);
spare1=spare2=0;
}
Random_Texture_ID_Chunk::Random_Texture_ID_Chunk(Chunk_With_Children* parent,const char* data,size_t)
:Chunk(parent,"RANTEXID")
{
CHUNK_EXTRACT_STRING(name);
int num_types,type;
CHUNK_EXTRACT(num_types,int);
for(int i=0;i<num_types;i++)
{
CHUNK_EXTRACT(type,int);
random_types.add_entry(type);
}
CHUNK_EXTRACT(spare1,int);
CHUNK_EXTRACT(spare2,int);
}
Random_Texture_ID_Chunk::~Random_Texture_ID_Chunk()
{
delete [] name;
}
void Random_Texture_ID_Chunk::fill_data_block(char* data)
{
CHUNK_FILL_START
CHUNK_FILL_STRING(name)
CHUNK_FILL(random_types.size(),int);
for(LIF<int> rlif(&random_types);!rlif.done();rlif.next())
{
CHUNK_FILL(rlif(),int)
}
CHUNK_FILL(spare1,int)
CHUNK_FILL(spare2,int)
}
size_t Random_Texture_ID_Chunk::size_chunk()
{
chunk_size=12+12+random_types.size()*4;
chunk_size+=(strlen(name)+4)&~3;
return chunk_size;
}
///////////////////////////////////////
//Class Special_Objects_Chunk :
RIF_IMPLEMENT_DYNCREATE("SPECLOBJ",Special_Objects_Chunk)
CHUNK_WITH_CHILDREN_LOADER("SPECLOBJ",Special_Objects_Chunk)
/*
Children for Special_Objects_Chunk :
"AVPGENER" AVP_Generator_Chunk
"SOUNDOB2" Sound_Object_Chunk
"VIOBJECT" Virtual_Object_Chunk
"AVPCABLE" AVP_Power_Cable_Chunk
"AVPSTART" AVP_Player_Start_Chunk
"AVPPATH2" AVP_Path_Chunk
"AVPGENEX" AVP_Generator_Extra_Data_Chunk
"SOUNDEXD" Sound_Object_Extra_Data_Chunk
"PARGENER" AVP_Particle_Generator_Chunk
"PLACHIER" Placed_Hierarchy_Chunk
"CAMORIGN" Camera_Origin_Chunk
"AVPDECAL" AVP_Decal_Chunk
"R6WAYPNT" R6_Waypoint_Chunk
*/

201
src/win95/envchunk.hpp Normal file
View file

@ -0,0 +1,201 @@
#ifndef _envchunk_hpp
#define _envchunk_hpp 1
#include "chunk.hpp"
#include "chnktype.hpp"
#include "mishchnk.hpp"
class Environment_Data_Header_Chunk;
class Environment_Data_Chunk : public Lockable_Chunk_With_Children
{
public:
// empty constructor
Environment_Data_Chunk (Chunk_With_Children * parent);
// constructor from buffer
Environment_Data_Chunk (Chunk_With_Children * const parent,const char *, size_t const);
Environment_Data_Header_Chunk * get_header();
// functions for the locking functionality
BOOL file_equals (HANDLE &);
const char * get_head_id();
void set_lock_user(char *);
void post_input_processing();
private:
friend class File_Chunk;
friend class GodFather_Chunk;
friend class RIF_File_Chunk;
};
///////////////////////////////////////////////
class Environment_Data_Header_Chunk : public Chunk
{
public:
// constructor from buffer
Environment_Data_Header_Chunk (Chunk_With_Children * parent, const char * pdata, size_t psize);
virtual size_t size_chunk ()
{
chunk_size = 36;
return chunk_size;
}
virtual BOOL output_chunk (HANDLE &);
virtual void fill_data_block (char * data_start);
void prepare_for_output();
private:
friend class Environment_Data_Chunk;
friend class File_Chunk;
int flags;
int version_no;
char lock_user[17];
// constructor from parent
Environment_Data_Header_Chunk (Environment_Data_Chunk * parent)
: Chunk (parent, "ENDTHEAD"),
flags (0), version_no (0)
{}
};
///////////////////////////////////////////////
class Environment_Scale_Chunk : public Chunk
{
public:
// constructor from data
Environment_Scale_Chunk (Environment_Data_Chunk * parent, double _scale)
: Chunk (parent, "ENVSDSCL"),
scale (_scale)
{}
// constructor from buffer
Environment_Scale_Chunk (Chunk_With_Children * parent, const char * sdata, size_t /*ssize*/)
: Chunk (parent, "ENVSDSCL"),
scale ( *((double *) sdata) )
{}
virtual size_t size_chunk ()
{
chunk_size = 20;
return chunk_size;
}
virtual void fill_data_block (char * data_start);
const double scale;
private:
friend class Environment_Data_Chunk;
};
///////////////////////////////////////////////
class Special_Objects_Chunk : public Chunk_With_Children
{
public:
Special_Objects_Chunk(Chunk_With_Children * parent)
: Chunk_With_Children (parent, "SPECLOBJ")
{}
// constructor from buffer
Special_Objects_Chunk (Chunk_With_Children * const parent,const char *, size_t const);
private:
friend class Environment_Data_Chunk;
friend class AVP_Generator_Chunk;
};
///////////////////////////////////////////////
class Environment_Acoustics_Chunk : public Chunk
{
public:
Environment_Acoustics_Chunk(Environment_Data_Chunk * parent);
Environment_Acoustics_Chunk(Chunk_With_Children* parent, const char * data, size_t );
virtual void fill_data_block(char*);
virtual size_t size_chunk()
{return chunk_size=24;}
int env_index;
float reverb;
int spare;
private:
friend class Environment_Data_Chunk;
};
///////////////////////////////////////////////
class Sound_Directory_Chunk : public Chunk
{
public :
Sound_Directory_Chunk(Environment_Data_Chunk* parent,const char* dir);
~Sound_Directory_Chunk();
// constructor from buffer
Sound_Directory_Chunk (Chunk_With_Children * const parent,const char *, size_t const);
char* directory;
size_t size_chunk()
{
return (chunk_size =12 + ((strlen (directory)+4)&~3));
}
void fill_data_block(char* data_start);
private:
friend class Environment_Data_Chunk;
};
/////////////////////Available shape set collections////////////////////////////////////////
class Random_Texture_ID_Chunk : public Chunk
{
public :
Random_Texture_ID_Chunk(Chunk_With_Children* parent,const char* _name);
Random_Texture_ID_Chunk(Chunk_With_Children* parent,const char* data, size_t);
~Random_Texture_ID_Chunk();
void fill_data_block(char* data);
size_t size_chunk();
char* name;
List<int> random_types;
int spare1,spare2;
};
#endif

37
src/win95/fail.c Normal file
View file

@ -0,0 +1,37 @@
/* LotU: Error handling functions.
Copyright (C) 1995, Jamie Lokier.
Written for Rebellion Developments, Ltd.
Permission to use, copy, modify and distribute this file for any
purpose by Rebellion Developments, Ltd. is hereby granted. If you
want to use this file outside the company, please let me know.
*/
#include "3dc.h"
#include "fail.h"
#include "dxlog.h"
void
fail (const char * format, ...)
{
va_list ap;
LOGDXSTR(format);
va_start (ap, format);
if (format != 0)
vfprintf (stderr, format, ap);
va_end (ap);
exit (EXIT_FAILURE);
}
void FAILHandleCompilerWarningMessage(void)
{
int temp;
temp = D3DRMMAP_PERSPCORRECT;
temp = D3DRMMAP_WRAPU;
temp = D3DRMMAP_WRAPV;
temp = D3DRMGROUP_ALLGROUPS;
}

44
src/win95/fail.h Normal file
View file

@ -0,0 +1,44 @@
/* LotU: Error handling functions.
Copyright (C) 1995, Jamie Lokier.
Written for Rebellion Developments, Ltd.
Permission to use, copy, modify and distribute this file for any
purpose by Rebellion Developments, Ltd. is hereby granted. If you
want to use this file outside the company, please let me know.
*/
#ifndef __fail_h
#define __fail_h 1
#ifdef __cplusplus
extern "C" {
#endif
#ifdef _MSC_VER
#define VARARG_DECL __cdecl
#else
#define VARARG_DECL
#endif
#ifdef __GNUC__
#if __GNUC__ >= 2 && __GNUC_MINOR__ >= 5
extern void
VARARG_DECL fail (const char * __format, ...)
__attribute__ ((noreturn, format (printf, 1, 2)));
#else
extern __volatile__ void VARARG_DECL fail (const char * __format, ...);
#endif
#else
extern void VARARG_DECL fail (const char * __format, ...);
#endif
#ifdef __cplusplus
}
#endif
#endif /* __fail_h */

255
src/win95/fragchnk.cpp Normal file
View file

@ -0,0 +1,255 @@
#include "fragchnk.hpp"
//macro for helping to force inclusion of chunks when using libraries
FORCE_CHUNK_INCLUDE_IMPLEMENT(fragchnk)
RIF_IMPLEMENT_DYNCREATE("FRAGTYPE",Fragment_Type_Chunk)
CHUNK_WITH_CHILDREN_LOADER("FRAGTYPE",Fragment_Type_Chunk)
/*
Children for Fragment_Type_Chunk :
Fragment_Type_Data_Chunk "FRGTYPDC"
Fragment_Type_Shape_Chunk "FRGTYPSC"
Fragment_Type_Sound_Chunk "FRGSOUND"
*/
const char* Fragment_Type_Chunk::get_name()
{
Fragment_Type_Data_Chunk* ftdc=(Fragment_Type_Data_Chunk*)lookup_single_child("FRGTYPDC");
if(ftdc)
return ftdc->frag_type_name;
else
return 0;
}
////////////////////////////////////////////////////////////////////////
RIF_IMPLEMENT_DYNCREATE("FRGTYPDC",Fragment_Type_Data_Chunk)
Fragment_Type_Data_Chunk::Fragment_Type_Data_Chunk(Chunk_With_Children* parent,const char* name)
:Chunk(parent,"FRGTYPDC")
{
frag_type_name=new char[strlen(name)+1];
strcpy(frag_type_name,name);
pad1=pad2=pad3=0;
}
Fragment_Type_Data_Chunk::Fragment_Type_Data_Chunk(Chunk_With_Children* const parent,const char* data,size_t const )
:Chunk(parent,"FRGTYPDC")
{
int length=strlen(data)+1;
frag_type_name=new char[length];
strcpy(frag_type_name,data);
data+=(length+3)&~3;
pad1=*(int*)data;
data+=4;
pad2=*(int*)data;
data+=4;
pad3=*(int*)data;
data+=4;
}
Fragment_Type_Data_Chunk::~Fragment_Type_Data_Chunk()
{
if(frag_type_name) delete frag_type_name;
}
void Fragment_Type_Data_Chunk::fill_data_block(char* data_start)
{
strncpy (data_start, identifier, 8);
data_start += 8;
*((int *) data_start) = chunk_size;
data_start += 4;
strcpy(data_start,frag_type_name);
data_start+=(strlen(frag_type_name)+4)&~3;
*(int*)data_start=pad1;
data_start+=4;
*(int*)data_start=pad2;
data_start+=4;
*(int*)data_start=pad3;
data_start+=4;
}
size_t Fragment_Type_Data_Chunk::size_chunk()
{
chunk_size=12+12;
chunk_size+=(strlen(frag_type_name)+4)&~3;
return chunk_size;
}
////////////////////////////////////////////////////////////////////////
RIF_IMPLEMENT_DYNCREATE("FRGTYPSC",Fragment_Type_Shape_Chunk)
Fragment_Type_Shape_Chunk::Fragment_Type_Shape_Chunk(Chunk_With_Children* parent,const char* _name,int number,ChunkVectorInt _location)
:Chunk(parent,"FRGTYPSC")
{
name=new char[strlen(_name)+1];
strcpy(name,_name);
num_fragments=number;
location=_location;
pad1=pad2=pad3=0;
}
#if UseOldChunkLoader
Fragment_Type_Shape_Chunk::Fragment_Type_Shape_Chunk(Chunk_With_Children* const parent,const char* data,size_t const )
:Chunk(parent,"FRGTYPSC")
{
int length=strlen(data)+1;
name=new char[length];
strcpy(name,data);
data+=(length+3)&~3;
num_fragments=*(int*)data;
data+=4;
location=*(ChunkVector*)data;
data+=sizeof(ChunkVector);
pad1=*(int*)data;
data+=4;
pad2=*(int*)data;
data+=4;
pad3=*(int*)data;
data+=4;
};
#else
Fragment_Type_Shape_Chunk::Fragment_Type_Shape_Chunk(Chunk_With_Children* const parent,const char* data,size_t const )
:Chunk(parent,"FRGTYPSC")
{
int length=strlen(data)+1;
name=new char[length];
strcpy(name,data);
data+=(length+3)&~3;
num_fragments=*(int*)data;
data+=4;
location=*(ChunkVectorInt*)data;
data+=sizeof(ChunkVectorInt);
pad1=*(int*)data;
data+=4;
pad2=*(int*)data;
data+=4;
pad3=*(int*)data;
data+=4;
}
#endif
Fragment_Type_Shape_Chunk::~Fragment_Type_Shape_Chunk()
{
if(name) delete name;
}
void Fragment_Type_Shape_Chunk::fill_data_block(char* data_start)
{
strncpy (data_start, identifier, 8);
data_start += 8;
*((int *) data_start) = chunk_size;
data_start += 4;
strcpy(data_start,name);
data_start+=(strlen(name)+4)&~3;
*(int*)data_start=num_fragments;
data_start+=4;
*(ChunkVectorInt*)data_start=location;
data_start+=sizeof(ChunkVectorInt);
*(int*)data_start=pad1;
data_start+=4;
*(int*)data_start=pad2;
data_start+=4;
*(int*)data_start=pad3;
data_start+=4;
}
size_t Fragment_Type_Shape_Chunk::size_chunk()
{
chunk_size=12+16+sizeof(ChunkVectorInt);
chunk_size+=(strlen(name)+4)&~3;
return chunk_size;
}
////////////////////////////////////////////////////////////////////////
RIF_IMPLEMENT_DYNCREATE("FRGSOUND",Fragment_Type_Sound_Chunk)
Fragment_Type_Sound_Chunk::Fragment_Type_Sound_Chunk(Chunk_With_Children* parent)
:Chunk(parent,"FRGSOUND")
{
wav_name=0;
inner_range=5000;
outer_range=40000;
max_volume=127;
pitch=0;
pad=0;
}
Fragment_Type_Sound_Chunk::Fragment_Type_Sound_Chunk(Chunk_With_Children* const parent,const char* data,size_t const )
:Chunk(parent,"FRGSOUND")
{
inner_range=*(unsigned long*)data;
data+=4;
outer_range=*(unsigned long*)data;
data+=4;
max_volume=*(int*)data;
data+=4;
pitch=*(int*)data;
data+=4;
pad=*(int*)data;
data+=4;
wav_name=new char[strlen(data)+1];
strcpy(wav_name,data);
}
Fragment_Type_Sound_Chunk::~Fragment_Type_Sound_Chunk()
{
if(wav_name) delete wav_name;
}
void Fragment_Type_Sound_Chunk::fill_data_block(char* data_start)
{
strncpy (data_start, identifier, 8);
data_start += 8;
*((int *) data_start) = chunk_size;
data_start += 4;
*(unsigned long*)data_start=inner_range;
data_start+=4;
*(unsigned long*)data_start=outer_range;
data_start+=4;
*(int*)data_start=max_volume;
data_start+=4;
*(int*)data_start=pitch;
data_start+=4;
*(int*)data_start=pad;
data_start+=4;
strcpy(data_start,wav_name);
}
size_t Fragment_Type_Sound_Chunk::size_chunk()
{
chunk_size=12+20;
chunk_size+=(strlen(wav_name)+4)&~3;
return chunk_size;
}

82
src/win95/fragchnk.hpp Normal file
View file

@ -0,0 +1,82 @@
#ifndef _fragchnk_hpp_
#define _fragchnk_hpp_
#include "chunk.hpp"
#include "chnktype.hpp"
class Fragment_Type_Data_Chunk : public Chunk
{
public :
Fragment_Type_Data_Chunk(Chunk_With_Children* parent,const char* name);
Fragment_Type_Data_Chunk (Chunk_With_Children * const parent,const char *, size_t const);
~Fragment_Type_Data_Chunk();
size_t size_chunk ();
void fill_data_block (char * data_start);
char* frag_type_name;
int pad1,pad2,pad3;
};
class Fragment_Type_Shape_Chunk : public Chunk
{
public:
Fragment_Type_Shape_Chunk(Chunk_With_Children* parent,const char* _name,int number,ChunkVectorInt _location);
Fragment_Type_Shape_Chunk (Chunk_With_Children * const parent,const char *, size_t const);
~Fragment_Type_Shape_Chunk();
size_t size_chunk ();
void fill_data_block (char * data_start);
int num_fragments;
ChunkVectorInt location;
char* name;
int pad1,pad2,pad3;
};
class Fragment_Type_Sound_Chunk : public Chunk
{
public:
Fragment_Type_Sound_Chunk(Chunk_With_Children* parent);
Fragment_Type_Sound_Chunk (Chunk_With_Children * const parent,const char *, size_t const);
~Fragment_Type_Sound_Chunk();
size_t size_chunk ();
void fill_data_block (char * data_start);
char* wav_name;
unsigned long inner_range;
unsigned long outer_range;
int max_volume;
int pitch;
int pad;
};
class Fragment_Type_Chunk : public Chunk_With_Children
{
public :
Fragment_Type_Chunk(Chunk_With_Children * parent,const char* name)
: Chunk_With_Children (parent, "FRAGTYPE")
{new Fragment_Type_Data_Chunk(this,name);}
Fragment_Type_Chunk (Chunk_With_Children * const parent,const char *, size_t const);
const char* get_name();
};
#endif

130
src/win95/gsprchnk.cpp Normal file
View file

@ -0,0 +1,130 @@
#include "gsprchnk.hpp"
#ifdef cencon
#define new my_new
#endif
//macro for helping to force inclusion of chunks when using libraries
FORCE_CHUNK_INCLUDE_IMPLEMENT(gsprchnk)
// Class AllSprites_Chunk functions
RIF_IMPLEMENT_DYNCREATE("RSPRITES",AllSprites_Chunk)
// constructor from buffer
LOCKABLE_CHUNK_WITH_CHILDREN_LOADER("RSPRITES",AllSprites_Chunk)
/*
Children for AllSprites_Chunk :
"ASPRHEAD" AllSprites_Header_Chunk
"SPRIHEAD" Sprite_Header_Chunk
*/
// empty constructor
AllSprites_Chunk::AllSprites_Chunk (Chunk_With_Children * parent)
:Lockable_Chunk_With_Children (parent, "RSPRITES")
{
// as necessary, generated automatically
new AllSprites_Header_Chunk (this);
}
BOOL AllSprites_Chunk::file_equals (HANDLE & /*rif_file*/)
{
return(TRUE);
}
AllSprites_Header_Chunk * AllSprites_Chunk::get_header()
{
return (AllSprites_Header_Chunk *) this->lookup_single_child ("ASPRHEAD");
}
const char * AllSprites_Chunk::get_head_id()
{
AllSprites_Header_Chunk * hdptr = get_header();
if (!hdptr) return (0);
return(hdptr->identifier);
}
void AllSprites_Chunk::set_lock_user (char * user)
{
AllSprites_Header_Chunk * hdptr = get_header();
if (!hdptr) return;
strncpy (hdptr->lock_user, user,16);
hdptr->lock_user[16] = 0;
}
void AllSprites_Chunk::post_input_processing()
{
if (get_header())
if (get_header()->flags & GENERAL_FLAG_LOCKED)
external_lock = TRUE;
Chunk_With_Children::post_input_processing();
}
///////////////////////////////////////
// Class AllSprites_Header_Chunk functions
RIF_IMPLEMENT_DYNCREATE("ASPRHEAD",AllSprites_Header_Chunk)
// from buffer
AllSprites_Header_Chunk::AllSprites_Header_Chunk (Chunk_With_Children * parent, const char * hdata, size_t /*hsize*/)
: Chunk (parent, "ASPRHEAD"),
flags (0), version_no (0)
{
flags = *((int *) hdata);
strncpy (lock_user, (hdata + 4), 16);
lock_user[16] = '\0';
version_no = *((int *) (hdata + 20));
}
BOOL AllSprites_Header_Chunk::output_chunk (HANDLE & hand)
{
unsigned long junk;
BOOL ok;
char * data_block;
data_block = make_data_block_from_chunk();
ok = WriteFile (hand, (long *) data_block, (unsigned long) chunk_size, &junk, 0);
delete [] data_block;
if (!ok) return FALSE;
return TRUE;
}
void AllSprites_Header_Chunk::fill_data_block ( char * data_start)
{
strncpy (data_start, identifier, 8);
data_start += 8;
*((int *) data_start) = chunk_size;
data_start += 4;
*((int *) data_start) = flags;
strncpy ((data_start + 4), lock_user, 16);
*((int *) (data_start+20)) = version_no;
}
void AllSprites_Header_Chunk::prepare_for_output()
{
version_no ++;
}

82
src/win95/gsprchnk.hpp Normal file
View file

@ -0,0 +1,82 @@
#ifndef _included_gsprchnk_hpp_
#define _included_gsprchnk_hpp_
#include "chunk.hpp"
#include "mishchnk.hpp"
class AllSprites_Header_Chunk;
class AllSprites_Chunk : public Lockable_Chunk_With_Children
{
public:
// empty constructor
AllSprites_Chunk (Chunk_With_Children * parent);
// constructor from buffer
AllSprites_Chunk (Chunk_With_Children * const parent,const char *, size_t const);
AllSprites_Header_Chunk * get_header();
// functions for the locking functionality
BOOL file_equals (HANDLE &);
const char * get_head_id();
void set_lock_user(char *);
void post_input_processing();
private:
friend class File_Chunk;
friend class GodFather_Chunk;
};
///////////////////////////////////////////////
class AllSprites_Header_Chunk : public Chunk
{
public:
// constructor from buffer
AllSprites_Header_Chunk (Chunk_With_Children * parent, const char * pdata, size_t psize);
virtual size_t size_chunk ()
{
chunk_size = 36;
return chunk_size;
}
virtual BOOL output_chunk (HANDLE &);
virtual void fill_data_block (char * data_start);
void prepare_for_output();
private:
friend class AllSprites_Chunk;
friend class File_Chunk;
int flags;
int version_no;
char lock_user[17];
// constructor from parent
AllSprites_Header_Chunk (AllSprites_Chunk * parent)
: Chunk (parent, "ASPRHEAD"),
flags (0), version_no (0)
{}
};
#endif // _included_gsprchnk_hpp_

882
src/win95/hash_tem.hpp Normal file
View file

@ -0,0 +1,882 @@
/********************************************************/
/* Hash Table template class - v1.2 */
/* */
/* Author: Jake Hotson */
/* */
/* construct a hash table for objects of type TYPE */
/* */
/* HashTable<TYPE>(unsigned initialTableSizeShift */
/* = HT_DEFAULTTABLESIZESHIFT); */
/* */
/* TYPE must have boolean operator == defined, and */
/* there must be an overload of the function */
/* HashFunction() which acts as a hash */
/* function for the TYPE, taking an argument of type */
/* TYPE or a suitable conversion thereof, and returning */
/* unsigned */
/* Also, if a==b then HashFunction(a)==HashFunction(b) */
/* Additionally, TYPE must have valid assignment */
/* operator and copy constructor */
/****************************************************Jake*/
/************************************************************/
/* */
/* v1.0 public classes and functions and macros */
/* */
/* HASH_TEMPLATE_VERSION */
/* */
/* major version * 100 + minor version */
/* in this version (1.0) the value is 100 */
/* */
/* HT_NODEFAULTFNS */
/* */
/* #define to not compile default hash functions */
/* */
/* HT_DEFAULTABLESIZESHIFT */
/* */
/* #define to override default table size shift */
/* of 6 (which gives a default table size of 64) */
/* */
/* HT_FAIL(sP) */
/* */
/* this macro should expand to a function (which */
/* takes a char const * parameter) to be called */
/* in the event of an error */
/* */
/* HashFunction(unsigned) */
/* */
/* default hash function for integers */
/* */
/* HashFunction(void const *) */
/* */
/* default hash function for pointers */
/* */
/* HashFunction(char const *) */
/* */
/* default hash function for strings */
/* */
/* class HashTable<TYPE> */
/* */
/* hash table template class */
/* TYPE should have == operator defined and an */
/* overloaded HashFunction() defined which can */
/* take an argument type TYPE or suitable */
/* conversion thereof */
/* */
/* HashTable::HashTable() */
/* */
/* constructs an empty table with default table */
/* size */
/* */
/* HashTable::HashTable(unsigned) */
/* */
/* constructs an empty table with specific */
/* table size determined by 2^arg */
/* */
/* bool HashTable::AddChecked(TYPE) */
/* */
/* adds object to hash table unless it already */
/* contains it. Returns non-zero if object was */
/* added, and zero if it was already contained */
/* */
/* void HashTable::AddRegardless(TYPE) */
/* */
/* adds object to hash table but does not check */
/* if it already exists, so duplicates could */
/* occur */
/* */
/* void HashTable::AddAsserted(TYPE) */
/* */
/* adds object to hash table but throws a failure if it */
/* already exists unless NDEBUG is defined in which case */
/* this function is identical to AddRegardless */
/* */
/* TYPE const * HashTable::Contains(TYPE) const */
/* */
/* returns pointer to equivalent entry in table, */
/* or NULL, if none exists */
/* */
/* bool HashTable::Remove(TYPE) */
/* */
/* removes object from table if it exists. */
/* Returns non-zero if object was removed, or */
/* zero if object was not contained */
/* */
/* void HashTable::RemoveAll() */
/* */
/* empties the table */
/* */
/* void HashTable::RemoveAsserted(TYPE) */
/* */
/* removes object from table, but throws a */
/* failure if object was not contained */
/* */
/* unsigned HashTable::Size() const */
/* */
/* returns number of objects in table */
/* */
/* class HashTable<TYPE>::ConstIterator */
/* */
/* class for iterating through objects contained */
/* in hash table, without modifying the contents */
/* of the table */
/* */
/* HashTable::ConstIterator::ConstIterator(HashTable const) */
/* */
/* constructs an iterator linked to a table, */
/* ready for a Get() */
/* */
/* TYPE const & HashTable::ConstIterator::Get() const */
/* HashTable::ConstIterator::operator TYPE const & () const */
/* */
/* gets a constant reference to the object in */
/* the table pointed to by the iterator object */
/* */
/* bool HashTable::ConstIterator::Done() const */
/* */
/* returns non-zero only if there is no more */
/* iterating to do */
/* */
/* void HashTable::ConstIterator::Next() */
/* */
/* moves iterator to a fresh entry in the table */
/* */
/* class HashTable<TYPE>::Iterator */
/* */
/* class for iterating through objects contained */
/* in hash table, allowing their removal */
/* */
/* HashTable::Iterator::Iterator(HashTable) */
/* */
/* constructs an iterator linked to a table, */
/* ready for a Get() */
/* */
/* HashTable::Iterator::Remove() */
/* */
/* removes the current object pointed to by the */
/* iterator from the table, and advances the */
/* iterator to the next entry */
/* */
/*******************************************************Jake*/
/************************************************************/
/* */
/* v1.1 - v1.11 extended functionality */
/* */
/* class HashTable<TYPE>::Node */
/* */
/* this is the internal class for nodes in the table */
/* */
/* TYPE HashTable::Node::d */
/* */
/* this is the value of a node's data */
/* */
/* Node * HashTable::NewNode() */
/* */
/* allocates a node without inserting it into the table; */
/* you are expected to set Node::d to the required value */
/* to be added to the table, and call one of these methods */
/* to link the node into the table */
/* */
/* void HashTable::AddAsserted(Node *) */
/* */
/* like AddAsserted(TYPE const &) but takes a Node * */
/* created with NewNode(); do not use the Node * pointer */
/* after calling this method */
/* */
/* void HashTable::AddRegardless(Node *) */
/* */
/* like AddRegardless(TYPE const &) but takes a Node * */
/* created with NewNode(); do not use the Node * pointer */
/* after calling this method */
/* */
/* bool HashTable::AddChecked(Node *) */
/* */
/* like AddChecked(TYPE const &) but takes a Node * */
/* created with NewNode(); do not use the Node * pointer */
/* after calling this method if it returns true, but if it */
/* returns false (i.e. the Node was not added, then you */
/* can re-use the Node or use the following function to */
/* delete it. */
/* */
/* void HashTable::DeleteNode(Node *) */
/* */
/* destroys a Node created with NewNode. Use this only if */
/* the node created was not added to the hash table */
/* */
/*******************************************************Jake*/
/************************************************************/
/* */
/* v1.2 */
/* */
/* HashTable::Iterator::Restart() */
/* restarts the iterator */
/* */
/* HashTable::HashTable(HashTable<TYPE>) */
/* copy constructor */
/* */
/* HashTable::ValueIterator(unsigned) */
/* iterate through all entries of a specific hashvalue */
/* */
/*******************************************************Alex*/
#ifndef HASH_TEMPLATE_VERSION
#define HASH_TEMPLATE_VERSION 12 // v1.2
#include <stddef.h>
#include <ctype.h>// for toupper
// v1,0 Default Hash Functions defined:
// HashFunction(unsigned), HashFunction(void const *), HashFunction(char const *)
// you can disable the default hash functions by defining HT_NODEFAULTFNS
#ifndef HT_NODEFAULTFNS
// a hash function for integral (unsigned) values
inline unsigned HashFunction(unsigned const _i)
{
return _i ^ _i>>4 ^ _i>>9 ^ _i>>15 ^ _i>>22;
}
// a hash function for pointers
inline unsigned HashFunction(void const * const _vP)
{
// treat as integer
return HashFunction(reinterpret_cast<unsigned>(_vP));
}
// a hash function for strings
inline unsigned HashFunction(char const * _sP)
{
unsigned rv = 0;
while (*_sP) rv += toupper(*_sP++);
return rv;
}
#endif
// v1,0 Default (initial) table size (log2 of)
// Define this to another value if you like,
// or just override in the constructor.
// in v1.0, the table is not self-expanding,
// but if this feature is implememted, then
// this value will become the log2(initial table size),
// and if table becomes is self-contracting,
// this value will also give the minimum table size
#ifndef HT_DEFAULTTABLESIZESHIFT
#define HT_DEFAULTTABLESIZESHIFT 6
#endif
// for asserted functions, define HT_FAIL to be your function
// to be triggered upon a failure, eg.
// #define HT_FAIL(strP) fprintf(stderr,"%s\n",strP)
#ifndef HT_FAIL
#define HT_FAIL(strP) ((void)0)
#endif
template <class TYPE, class ARG_TYPE, class CMP_ARG_TYPE>
class _base_HashTable
{
public:
class Iterator;
class ConstIterator;
class ValueIterator;
class Node;
public:
// V1.0 Functionality
// empty constructor, with argument specifying initial table size (log2 of)
_base_HashTable(unsigned = HT_DEFAULTTABLESIZESHIFT);
// destructor
~_base_HashTable();
// copy constructor and assignment not provided in v1.0
_base_HashTable(_base_HashTable<TYPE,ARG_TYPE,CMP_ARG_TYPE> const &);
_base_HashTable<TYPE,ARG_TYPE,CMP_ARG_TYPE> & operator = (_base_HashTable<TYPE,ARG_TYPE,CMP_ARG_TYPE> const &);
// add, checking that an equivalent entry does not already exist
// returns non-zero if entry was added
bool AddChecked(ARG_TYPE);
// add, regardless of whether an equivalent entry already exists
void AddRegardless(ARG_TYPE);
// add, checking that an equivalent entry does not already exist
// triggering fail function if one does
void AddAsserted(ARG_TYPE);
// see if entry exists, get pointer to it if it does
TYPE const * Contains(CMP_ARG_TYPE) const;
// remove an entry (once only in the case of equivalent entries listed multiple times)
// returns non-zero if entry existed and was removed
bool Remove(CMP_ARG_TYPE);
// remove an entry (once only in the case of equivalent entries listed multiple times)
// triggers fail function if no entry existed to remove
void RemoveAsserted(CMP_ARG_TYPE);
// empty the table
void RemoveAll();
// return num entries in table
unsigned Size() const;
// a _base_HashTable const iterator
class ConstIterator
{
// Nested class functions apparently have to be declared here for MSVC compatability
public:
// construct from const hash table
ConstIterator(_base_HashTable<TYPE,ARG_TYPE,CMP_ARG_TYPE> const & tableR)
: chainPP(tableR.chainPA)
, nChainsRemaining(tableR.tableSize)
, nEntriesRemaining(tableR.nEntries)
{
if (nEntriesRemaining)
{
while (!*chainPP)
{
++ chainPP;
-- nChainsRemaining;
}
nodePP = chainPP;
}
}
// returns non-zero if there are no more entries to get
inline bool Done() const
{
return ! nEntriesRemaining;
}
inline void Restart(_base_HashTable<TYPE,ARG_TYPE,CMP_ARG_TYPE> const & tableR)
{
chainPP = tableR.chainPA;
nChainsRemaining = tableR.tableSize;
nEntriesRemaining = tableR.nEntries;
if (nEntriesRemaining)
{
while (!*chainPP)
{
++ chainPP;
-- nChainsRemaining;
}
nodePP = chainPP;
}
}
// get the current entry pointed to, either with Get() or cast operator
inline operator ARG_TYPE () const
{
return Get();
}
inline ARG_TYPE Get() const
{
if( Done() )
{
HT_FAIL("HTT: Tried to Get() from an iterator which was Done()");
}
return (*nodePP)->d;
}
// advance to the next entry
void Next()
{
if (!nEntriesRemaining)
{
HT_FAIL("HTT: Tried to do Next() on an iterator which was Done()");
}
if ((*nodePP)->nextP)
{
nodePP = &(*nodePP)->nextP;
}
else
{
do
{
++ chainPP;
-- nChainsRemaining;
}
while (nChainsRemaining && !*chainPP);
nodePP = chainPP;
}
-- nEntriesRemaining;
}
private:
Node * * chainPP;
Node * * nodePP;
unsigned nChainsRemaining;
unsigned nEntriesRemaining;
friend class Iterator;
};
// a _base_HashTable non-const iterator - can remove entry pointed to
class Iterator : public ConstIterator
{
// Nested class functions apparently have to be declared here for MSVC compatability
public:
// construct from hash table
inline Iterator(_base_HashTable<TYPE,ARG_TYPE,CMP_ARG_TYPE> & tableR)
: ConstIterator(tableR)
, tableNEntriesP(&tableR.nEntries)
{
}
// remove the current entry pointed to, advancing to the next
void Remove()
{
if (!nEntriesRemaining)
{
HT_FAIL("HTT: Tried to Remove() via an iterator which was Done()");
}
Node * oldP = *nodePP;
*nodePP = oldP->nextP;
delete oldP;
if (!*nodePP)
{
do
{
++ chainPP;
-- nChainsRemaining;
}
while (nChainsRemaining && !*chainPP);
nodePP = chainPP;
}
-- nEntriesRemaining;
-- *tableNEntriesP;
}
private:
unsigned * tableNEntriesP;
};
// v1.2 extended functionality
// a _base_HashTable iterator through a specific hash value
class ValueIterator
{
// Nested class functions apparently have to be declared here for MSVC compatability
public:
// construct from const hash table
ValueIterator(_base_HashTable<TYPE,ARG_TYPE,CMP_ARG_TYPE> & tableR, unsigned value)
: chainPP(tableR.chainPA)
, value(value)
, tableNEntriesP(&tableR.nEntries)
{
chainPP += (value & tableR.tableSizeMask);
nodePP = chainPP;
}
// returns non-zero if there are no more entries to get
inline bool Done() const
{
return( !(*nodePP) );
}
inline operator ARG_TYPE () const
{
return Get();
}
inline ARG_TYPE Get() const
{
if( Done() )
{
HT_FAIL("HTT: Tried to Get() from an iterator which was Done()");
}
return (*nodePP)->d;
}
inline void Restart(_base_HashTable<TYPE,ARG_TYPE,CMP_ARG_TYPE> const & tableR)
{
chainPP = tableR.chainPA + (value & tableR.tableSizeMask);
nodePP = chainPP;
}
// advance to the next entry
void Next()
{
if( *nodePP )
{
nodePP = &(*nodePP)->nextP; // even if it's NULL for ValueIterator
}
else
{
HT_FAIL("HTT: Tried to do Next() on a Value iterator which was Done()");
}
}
// remove the current entry pointed to, advancing to the next
void Remove()
{
if( *nodePP )
{
Node * oldP = *nodePP;
*nodePP = oldP->nextP;
delete oldP;
-- *tableNEntriesP;
}
else
{
HT_FAIL("HTT: Tried to Remove() via an iterator which was Done()");
}
}
private:
Node * * chainPP;
Node * * nodePP;
unsigned value;
unsigned * tableNEntriesP;
};
// V1.1 extended functionality
// allow user to create nodes, change
// the data using this pointer,
// then insert the node into the
// correct chain, without having
// to create a copy of the data to
// be added on the stack
virtual Node * NewNode();
// add, checking that an equivalent entry does not already exist
// triggering fail function if one does
void AddAsserted(Node *);
// add, regardless of whether an equivalent entry already exists
void AddRegardless(Node *);
// V1.11 allows AddChecked for the Node-adding interface
bool AddChecked(Node *);
// if add checked fails, you should avoid the memory leak with this function
virtual void DeleteNode(Node *);
class Node
{
public:
TYPE d;
private:
Node * nextP;
// Nested class functions apparently have to be declared here for MSVC compatability
inline Node(ARG_TYPE _dataR,Node * _nextP)
: d(_dataR)
, nextP(_nextP)
{
}
inline Node()
{
}
inline ~Node()
{
}
void DeleteChain()
{
if (nextP) nextP->DeleteChain();
delete this;
}
friend class ConstIterator;
friend class Iterator;
friend class ValueIterator;
friend class _base_HashTable<TYPE,ARG_TYPE,CMP_ARG_TYPE>;
};
private:
// virtual functions for future expansion
virtual Node * NewNode(ARG_TYPE,Node *);
unsigned nEntries;
unsigned tableSize;
unsigned tableSizeMask;
Node * * chainPA;
friend class ConstIterator;
friend class Iterator;
friend class ValueIterator;
inline void Xx(){}
};
/*******************/
/* Defined to Fail */
/**************Jake*/
template <class TYPE,class ARG_TYPE,class CMP_ARG_TYPE>
inline _base_HashTable<TYPE,ARG_TYPE,CMP_ARG_TYPE> & _base_HashTable<TYPE,ARG_TYPE,CMP_ARG_TYPE>::operator = (_base_HashTable<TYPE,ARG_TYPE,CMP_ARG_TYPE> const &)
{
HT_FAIL("HTT: assignment operator not allowed in this version");
return *this;
}
/*******************************/
/* Inline Function Definitions */
/**************************Jake*/
template <class TYPE,class ARG_TYPE,class CMP_ARG_TYPE>
inline void _base_HashTable<TYPE,ARG_TYPE,CMP_ARG_TYPE>::AddRegardless(ARG_TYPE _dataR)
{
Node * & chainPR = chainPA[HashFunction(_dataR) & tableSizeMask];
chainPR = new Node(_dataR,chainPR);
++ nEntries;
}
template <class TYPE,class ARG_TYPE,class CMP_ARG_TYPE>
inline void _base_HashTable<TYPE,ARG_TYPE,CMP_ARG_TYPE>::AddRegardless(Node * _nodeP)
{
Node * & chainPR = chainPA[HashFunction(_nodeP->d) & tableSizeMask];
_nodeP->nextP = chainPR;
chainPR = _nodeP;
++ nEntries;
}
// with NDEBUG on these functions evaluate to be identical to AddRegardless
#ifdef NDEBUG
template <class TYPE,class ARG_TYPE,class CMP_ARG_TYPE>
inline void _base_HashTable<TYPE,ARG_TYPE,CMP_ARG_TYPE>::AddAsserted(ARG_TYPE _dataR)
{
AddRegardless(_dataR);
}
template <class TYPE,class ARG_TYPE,class CMP_ARG_TYPE>
inline void _base_HashTable<TYPE,ARG_TYPE,CMP_ARG_TYPE>::AddAsserted(Node * _nodeP)
{
AddRegardless(_nodeP);
}
#endif
template <class TYPE,class ARG_TYPE,class CMP_ARG_TYPE>
inline TYPE const * _base_HashTable<TYPE,ARG_TYPE,CMP_ARG_TYPE>::Contains(CMP_ARG_TYPE _dataR) const
{
for (Node const * nodeP = chainPA[HashFunction(_dataR) & tableSizeMask]; nodeP; nodeP = nodeP->nextP)
{
if (nodeP->d == _dataR) return &nodeP->d;
}
return NULL;
}
template <class TYPE,class ARG_TYPE,class CMP_ARG_TYPE>
inline unsigned _base_HashTable<TYPE,ARG_TYPE,CMP_ARG_TYPE>::Size() const
{
return nEntries;
}
template <class TYPE,class ARG_TYPE,class CMP_ARG_TYPE>
inline void _base_HashTable<TYPE,ARG_TYPE,CMP_ARG_TYPE>::RemoveAll()
{
for (unsigned i=0; i<tableSize; ++i)
if (chainPA[i])
{
chainPA[i]->DeleteChain();
chainPA[i] = NULL;
}
nEntries = 0;
}
/*************************************************************/
/* Non inlines declared here since neither Watcom nor */
/* MS Visual C will link if they're in their own source file */
/********************************************************Jake*/
template <class TYPE,class ARG_TYPE,class CMP_ARG_TYPE>
_base_HashTable<TYPE,ARG_TYPE,CMP_ARG_TYPE>::_base_HashTable(unsigned _initialTableSizeShift)
: nEntries(0)
, tableSize(1<<_initialTableSizeShift)
, tableSizeMask(tableSize-1)
, chainPA(new Node * [tableSize])
{
for (unsigned i=0; i<tableSize; ++i)
chainPA[i] = NULL;
}
template <class TYPE,class ARG_TYPE,class CMP_ARG_TYPE>
inline _base_HashTable<TYPE,ARG_TYPE,CMP_ARG_TYPE>::_base_HashTable(_base_HashTable<TYPE,ARG_TYPE,CMP_ARG_TYPE> const & ht)
: nEntries(0)
, tableSize(ht.tableSize)
, tableSizeMask(tableSize-1)
, chainPA(new Node * [tableSize])
{
for (unsigned i=0; i<tableSize; ++i) { chainPA[i] = NULL; }
for( HashTable<TYPE>::ConstIterator it(ht); !it.Done(); it.Next() )
{
AddRegardless( it.Get() );
}
}
template <class TYPE,class ARG_TYPE,class CMP_ARG_TYPE>
_base_HashTable<TYPE,ARG_TYPE,CMP_ARG_TYPE>::~_base_HashTable()
{
for (unsigned i=0; i<tableSize; ++i)
if (chainPA[i])
chainPA[i]->DeleteChain();
delete[] chainPA;
}
template <class TYPE,class ARG_TYPE,class CMP_ARG_TYPE>
bool _base_HashTable<TYPE,ARG_TYPE,CMP_ARG_TYPE>::AddChecked(ARG_TYPE _dataR)
{
Node * & chainPR = chainPA[HashFunction(_dataR) & tableSizeMask];
for (Node const * nodeP = chainPR; nodeP; nodeP = nodeP->nextP)
{
if (nodeP->d == _dataR) return false;
}
chainPR = new Node(_dataR,chainPR);
++ nEntries;
return true;
}
template <class TYPE,class ARG_TYPE,class CMP_ARG_TYPE>
bool _base_HashTable<TYPE,ARG_TYPE,CMP_ARG_TYPE>::AddChecked(Node * _nodeP)
{
Node * & chainPR = chainPA[HashFunction(_nodeP->d) & tableSizeMask];
for (Node const * nodeP = chainPR; nodeP; nodeP = nodeP->nextP)
{
if (nodeP->d == _nodeP->d) return false;
}
_nodeP->nextP = chainPR;
chainPR = _nodeP;
++ nEntries;
return true;
}
// with NDEBUG on these functions evaluate to be identical to AddRegardless
#ifndef NDEBUG
template <class TYPE,class ARG_TYPE,class CMP_ARG_TYPE>
void _base_HashTable<TYPE,ARG_TYPE,CMP_ARG_TYPE>::AddAsserted(ARG_TYPE _dataR)
{
Node * & chainPR = chainPA[HashFunction(_dataR) & tableSizeMask];
for (Node const * nodeP = chainPR; nodeP; nodeP = nodeP->nextP)
{
if (nodeP->d == _dataR)
{
HT_FAIL("HTT: Tried to add entry which was already contained in table");
}
}
chainPR = new Node(_dataR,chainPR);
++ nEntries;
}
template <class TYPE,class ARG_TYPE,class CMP_ARG_TYPE>
void _base_HashTable<TYPE,ARG_TYPE,CMP_ARG_TYPE>::AddAsserted(Node * _nodeP)
{
Node * & chainPR = chainPA[HashFunction(_nodeP->d) & tableSizeMask];
for (Node const * nodeP = chainPR; nodeP; nodeP = nodeP->nextP)
{
if (nodeP->d == _nodeP->d)
{
HT_FAIL("HTT: Tried to add entry which was already contained in table");
}
}
_nodeP->nextP = chainPR;
chainPR = _nodeP;
++ nEntries;
}
#endif
template <class TYPE,class ARG_TYPE,class CMP_ARG_TYPE>
bool _base_HashTable<TYPE,ARG_TYPE,CMP_ARG_TYPE>::Remove(CMP_ARG_TYPE _dataR)
{
for (Node * * nodePP = &chainPA[HashFunction(_dataR) & tableSizeMask]; (*nodePP); nodePP = &(*nodePP)->nextP)
{
if ((*nodePP)->d == _dataR)
{
Node * oldP = *nodePP;
*nodePP = oldP->nextP;
delete oldP;
-- nEntries;
return true;
}
}
return false;
}
template <class TYPE,class ARG_TYPE,class CMP_ARG_TYPE>
void _base_HashTable<TYPE,ARG_TYPE,CMP_ARG_TYPE>::RemoveAsserted(CMP_ARG_TYPE _dataR)
{
for (Node * * nodePP = &chainPA[HashFunction(_dataR) & tableSizeMask]; (*nodePP); nodePP = &(*nodePP)->nextP)
{
if ((*nodePP)->d == _dataR)
{
Node * oldP = *nodePP;
*nodePP = oldP->nextP;
delete oldP;
-- nEntries;
return;
}
}
HT_FAIL("HTT: Tried to remove entry which was not contained in table");
}
template <class TYPE,class ARG_TYPE,class CMP_ARG_TYPE>
_base_HashTable<TYPE,ARG_TYPE,CMP_ARG_TYPE>::Node * _base_HashTable<TYPE,ARG_TYPE,CMP_ARG_TYPE>::NewNode(ARG_TYPE _dataR,Node * _nextP)
{
return new Node(_dataR,_nextP);
}
template <class TYPE,class ARG_TYPE,class CMP_ARG_TYPE>
_base_HashTable<TYPE,ARG_TYPE,CMP_ARG_TYPE>::Node * _base_HashTable<TYPE,ARG_TYPE,CMP_ARG_TYPE>::NewNode()
{
return new Node;
}
template <class TYPE,class ARG_TYPE,class CMP_ARG_TYPE>
void _base_HashTable<TYPE,ARG_TYPE,CMP_ARG_TYPE>::DeleteNode(Node * _nodeP)
{
delete _nodeP;
}
template <class TYPE> class HashTable;
#define HT_DEFINITION(T1,T2,T3) \
: public _base_HashTable<T1,T2,T3> { public: HashTable(unsigned _initialTableSizeShift = HT_DEFAULTTABLESIZESHIFT) : _base_HashTable<T1,T2,T3>(_initialTableSizeShift){} };
// for simple types
#define HT_WATCOM_DEFINE_FOR_SIMPLE_TYPE(TYPE) \
class HashTable<TYPE> HT_DEFINITION(TYPE,TYPE,TYPE)
#ifdef __WATCOMC__
//watcom generartes errors if template<> is added to the start of the line - Richard.
#define HT_DEFINE_FOR_SIMPLE_TYPE(SIMPLE_TYPE) HT_WATCOM_DEFINE_FOR_SIMPLE_TYPE(SIMPLE_TYPE)
#else
#define HT_DEFINE_FOR_SIMPLE_TYPE(SIMPLE_TYPE) template<> HT_WATCOM_DEFINE_FOR_SIMPLE_TYPE(SIMPLE_TYPE)
#endif
HT_DEFINE_FOR_SIMPLE_TYPE(unsigned long)
HT_DEFINE_FOR_SIMPLE_TYPE(signed long)
HT_DEFINE_FOR_SIMPLE_TYPE(unsigned)
HT_DEFINE_FOR_SIMPLE_TYPE(signed)
HT_DEFINE_FOR_SIMPLE_TYPE(unsigned short)
HT_DEFINE_FOR_SIMPLE_TYPE(signed short)
HT_DEFINE_FOR_SIMPLE_TYPE(unsigned char)
HT_DEFINE_FOR_SIMPLE_TYPE(signed char)
HT_DEFINE_FOR_SIMPLE_TYPE(char)
HT_DEFINE_FOR_SIMPLE_TYPE(float)
#undef HT_DEFINE_FOR_SIMPLE_TYPE
#undef HT_WATCOM_DEFINE_FOR_SIMPLE_TYPE
// for pointer types
#if 0 // doesnt't compile!!
template <class TYPE>
class HashTable<TYPE *> HT_DEFINITION(TYPE *, TYPE *, TYPE const *)
template <class TYPE>
class HashTable<TYPE const *> HT_DEFINITION(TYPE const *, TYPE const *, TYPE const *)
#endif
// for other types
template <class TYPE>
class HashTable HT_DEFINITION(TYPE,TYPE const &, TYPE const &)
//template <class TYPE *> class HashTable : public _base_HashTable<TYPE *,TYPE *,TYPE const *> {};
#undef HT_DEFINITION
#endif // ! HASH_TEMPLATE_VERSION

609
src/win95/hierchnk.cpp Normal file
View file

@ -0,0 +1,609 @@
#include "hierchnk.hpp"
#include "obchunk.hpp"
//#include "animobs.hpp"
//macro for helping to force inclusion of chunks when using libraries
FORCE_CHUNK_INCLUDE_IMPLEMENT(hierchnk)
/////////////Object_Hierarchy_Chunk////////////////////
RIF_IMPLEMENT_DYNCREATE("OBJCHIER",Object_Hierarchy_Chunk)
//loader for Object_Hierarchy_Chunk
CHUNK_WITH_CHILDREN_LOADER("OBJCHIER",Object_Hierarchy_Chunk)
/*
children for Object_Hierarchy_Chunk:
"OBJCHIER" Object_Hierarchy_Chunk)
"OBJHIERD" Object_Hierarchy_Data_Chunk)
"OBHIERNM" Object_Hierarchy_Name_Chunk)
"HIERBBOX" Hierarchy_Bounding_Box_Chunk)
"OBANSEQS" Object_Animation_Sequences_Chunk)
"OBANALLS" Object_Animation_All_Sequence_Chunk)
*/
List <Object_Hierarchy_Chunk *> Object_Hierarchy_Chunk::list_h_children()
{
List <Chunk *> cl;
lookup_child ("OBJCHIER",cl);
List <Object_Hierarchy_Chunk *> h_l;
for (LIF<Chunk *> cli(&cl); !cli.done(); cli.next())
{
h_l.add_entry((Object_Hierarchy_Chunk *)cli());
}
return(h_l);
}
Object_Hierarchy_Data_Chunk * Object_Hierarchy_Chunk::get_data ()
{
return((Object_Hierarchy_Data_Chunk *)lookup_single_child ("OBJHIERD"));
}
Object_Hierarchy_Name_Chunk * Object_Hierarchy_Chunk::get_name ()
{
return((Object_Hierarchy_Name_Chunk *)lookup_single_child ("OBHIERNM"));
}
//////////////////////////////////////////////////////
RIF_IMPLEMENT_DYNCREATE("OBJHIERD",Object_Hierarchy_Data_Chunk)
Object_Hierarchy_Data_Chunk::Object_Hierarchy_Data_Chunk (Object_Hierarchy_Chunk * parent, const char * obname)
: Chunk (parent, "OBJHIERD"), ob_name (0), object(0)
{
num_extra_data=0;
extra_data=0;
if (obname)
{
ob_name = new char [strlen(obname)+1];
strcpy (ob_name, obname);
Chunk_With_Children * root = GetRootChunk();
List<Chunk *> oblist;
root->lookup_child ("RBOBJECT",oblist);
for (LIF<Chunk *> oli(&oblist); !oli.done(); oli.next())
{
Object_Chunk * ob = (Object_Chunk *)oli();
if (!strcmp (ob->object_data.o_name, ob_name))
{
*((Object_Chunk **)&object) = ob;
break;
}
}
}
}
Object_Hierarchy_Data_Chunk::~Object_Hierarchy_Data_Chunk()
{
if (ob_name)
delete [] ob_name;
if(extra_data)
delete extra_data;
}
size_t Object_Hierarchy_Data_Chunk::size_chunk ()
{
if (ob_name)
{
chunk_size = 12 + 4+4*num_extra_data + strlen(ob_name) + 4 - strlen(ob_name)%4;
}
else
{
chunk_size = 12 + 4+4*num_extra_data + 4;
}
return chunk_size;
}
void Object_Hierarchy_Data_Chunk::fill_data_block (char *data_start)
{
strncpy (data_start, identifier, 8);
data_start += 8;
*((int *) data_start) = chunk_size;
data_start += 4;
*(int*) data_start=num_extra_data;
data_start+=4;
for (int i=0; i<num_extra_data; i++)
{
*((int *) data_start) = extra_data[i];
data_start += 4;
}
if (ob_name)
{
sprintf (data_start, "%s", ob_name);
}
else
{
*data_start = 0;
}
}
#if UseOldChunkLoader
Object_Hierarchy_Data_Chunk::Object_Hierarchy_Data_Chunk (Object_Hierarchy_Chunk * parent, const char * data_start, size_t /*ssize*/)
: Chunk (parent, "OBJHIERD"), object(0), ob_name (0)
{
num_extra_data=0;
extra_data=0;
data_start+=40;
if (strlen(data_start))
{
ob_name = new char [strlen(data_start) + 1];
strcpy (ob_name, data_start);
}
}
#else
Object_Hierarchy_Data_Chunk::Object_Hierarchy_Data_Chunk (Chunk_With_Children * parent, const char * data_start, size_t /*ssize*/)
: Chunk (parent, "OBJHIERD"), object(0), ob_name (0)
{
num_extra_data=*(int*)data_start;
data_start+=4;
if(num_extra_data)
extra_data=new int[num_extra_data];
else
extra_data=0;
for (int i=0; i<num_extra_data; i++)
{
extra_data[i] = *((int *) data_start);
data_start += 4;
}
if (strlen(data_start))
{
ob_name = new char [strlen(data_start) + 1];
strcpy (ob_name, data_start);
}
}
#endif
void Object_Hierarchy_Data_Chunk::post_input_processing ()
{
find_object_for_this_section();
}
void Object_Hierarchy_Data_Chunk::find_object_for_this_section ()
{
*((Object_Chunk **)&object) = NULL;
Chunk_With_Children * root = GetRootChunk();
List<Chunk *> oblist;
root->lookup_child ("RBOBJECT",oblist);
for (LIF<Chunk *> oli(&oblist); !oli.done(); oli.next())
{
Object_Chunk * ob = (Object_Chunk *)oli();
if (!strcmp (ob->object_data.o_name, ob_name))
{
*((Object_Chunk **)&object) = ob;
break;
}
}
}
//////////////////////////////////////
RIF_IMPLEMENT_DYNCREATE("OBHIERNM",Object_Hierarchy_Name_Chunk)
Object_Hierarchy_Name_Chunk::Object_Hierarchy_Name_Chunk (Object_Hierarchy_Chunk * parent, const char * hname)
: Chunk (parent, "OBHIERNM")
{
if (hname)
{
hierarchy_name = new char [strlen(hname)+1];
strcpy (hierarchy_name, hname);
}
else
{
hierarchy_name = new char [1];
*hierarchy_name = 0;
}
}
Object_Hierarchy_Name_Chunk::~Object_Hierarchy_Name_Chunk()
{
if (hierarchy_name)
{
delete [] hierarchy_name;
}
}
void Object_Hierarchy_Name_Chunk::fill_data_block (char *data_start)
{
strncpy (data_start, identifier, 8);
data_start += 8;
*((int *) data_start) = chunk_size;
data_start += 4;
strcpy (data_start, hierarchy_name);
}
Object_Hierarchy_Name_Chunk::Object_Hierarchy_Name_Chunk (Chunk_With_Children * parent, const char * data, size_t /*ssize*/)
: Chunk (parent, "OBHIERNM")
{
hierarchy_name = new char [strlen(data)+1];
strcpy (hierarchy_name, data);
}
///////////////////////////////////////////////////
RIF_IMPLEMENT_DYNCREATE("OBHALTSH",Object_Hierarchy_Alternate_Shape_Set_Chunk)
Object_Hierarchy_Alternate_Shape_Set_Chunk::Object_Hierarchy_Alternate_Shape_Set_Chunk(Chunk_With_Children* parent,int num,const char* name)
:Chunk(parent,"OBHALTSH")
{
Shape_Set_Name=new char[strlen(name)+1];
Shape_Set_Num=num;
strcpy(Shape_Set_Name,name);
flags=0;
spare[0]=spare[1]=spare[2]=0;
}
Object_Hierarchy_Alternate_Shape_Set_Chunk::Object_Hierarchy_Alternate_Shape_Set_Chunk(Chunk_With_Children* parent,const char* name)
:Chunk(parent,"OBHALTSH")
{
Shape_Set_Name=new char[strlen(name)+1];
strcpy(Shape_Set_Name,name);
flags=0;
spare[0]=spare[1]=spare[2]=0;
Shape_Set_Num=-1;
//find next available shape set number
List<Chunk*> chlist;
parent->lookup_child("OBHALTSH",chlist);
int num=0;
for(LIF<Chunk*> chlif(&chlist);!chlif.done();)
{
Object_Hierarchy_Alternate_Shape_Set_Chunk* ohassc=(Object_Hierarchy_Alternate_Shape_Set_Chunk*) chlif();
if(ohassc->Shape_Set_Num==num)
{
num++;
chlif.restart();
}
else
{
chlif.next();
}
}
Shape_Set_Num=num;
}
Object_Hierarchy_Alternate_Shape_Set_Chunk::Object_Hierarchy_Alternate_Shape_Set_Chunk(Chunk_With_Children* parent,const char* data,size_t)
:Chunk(parent,"OBHALTSH")
{
Shape_Set_Num=*(int*)data;
data+=4;
int name_length=strlen(data)+1;
Shape_Set_Name=new char[name_length];
strcpy(Shape_Set_Name,data);
data+=(name_length+3)&~3;
int num_shapes=*(int*)data;
data+=4;
for(int i=0;i<num_shapes;i++)
{
Replaced_Shape_Details* rsd=new Replaced_Shape_Details;
name_length=strlen(data)+1;
rsd->old_object_name=new char[name_length];
strcpy(rsd->old_object_name,data);
data+=(name_length+3)&~3;
name_length=strlen(data)+1;
rsd->new_object_name=new char[name_length];
strcpy(rsd->new_object_name,data);
data+=(name_length+3)&~3;
Replaced_Shape_List.add_entry(rsd);
}
flags=*(int*)data;
data+=4;
for(i=0;i<3;i++)
{
spare[i]=*(int*)data;
data+=4;
}
}
Object_Hierarchy_Alternate_Shape_Set_Chunk::~Object_Hierarchy_Alternate_Shape_Set_Chunk()
{
if(Shape_Set_Name) delete Shape_Set_Name;
while(Replaced_Shape_List.size())
{
delete Replaced_Shape_List.first_entry();
Replaced_Shape_List.delete_first_entry();
}
}
void Object_Hierarchy_Alternate_Shape_Set_Chunk::fill_data_block(char* data_start)
{
strncpy (data_start, identifier, 8);
data_start += 8;
*((int *) data_start) = chunk_size;
data_start += 4;
*(int*)data_start=Shape_Set_Num;
data_start+=4;
strcpy(data_start,Shape_Set_Name);
data_start+=(strlen(Shape_Set_Name)+4)&~3;
*(int*)data_start=Replaced_Shape_List.size();
data_start+=4;
for(LIF<Replaced_Shape_Details*> rlif(&Replaced_Shape_List);!rlif.done();rlif.next())
{
strcpy(data_start,rlif()->old_object_name);
data_start+=(strlen(rlif()->old_object_name)+4)&~3;
strcpy(data_start,rlif()->new_object_name);
data_start+=(strlen(rlif()->new_object_name)+4)&~3;
}
*(int*)data_start=flags;
data_start+=4;
for(int i=0;i<3;i++)
{
*(int*)data_start=spare[i];
data_start+=4;
}
}
size_t Object_Hierarchy_Alternate_Shape_Set_Chunk::size_chunk()
{
chunk_size=36;
chunk_size+=(strlen(Shape_Set_Name)+4)&~3;
for(LIF<Replaced_Shape_Details*> rlif(&Replaced_Shape_List);!rlif.done();rlif.next())
{
chunk_size+=(strlen(rlif()->old_object_name)+4)&~3;
chunk_size+=(strlen(rlif()->new_object_name)+4)&~3;
}
return chunk_size;
}
///////////////////////////////////////////////////
RIF_IMPLEMENT_DYNCREATE("HSETCOLL",Hierarchy_Shape_Set_Collection_Chunk)
Hierarchy_Shape_Set_Collection_Chunk::Hierarchy_Shape_Set_Collection_Chunk(Chunk_With_Children* parent,int num,const char* name)
:Chunk(parent,"HSETCOLL")
{
Set_Collection_Name=new char[strlen(name)+1];
Set_Collection_Num=num;
strcpy(Set_Collection_Name,name);
TypeIndex=flags=0;
}
Hierarchy_Shape_Set_Collection_Chunk::Hierarchy_Shape_Set_Collection_Chunk(Chunk_With_Children* parent,const char* data,size_t)
:Chunk(parent,"HSETCOLL")
{
Set_Collection_Num=*(int*)data;
data+=4;
int name_length=strlen(data)+1;
Set_Collection_Name=new char[name_length];
strcpy(Set_Collection_Name,data);
data+=(name_length+3)&~3;
int list_length=*(int*)data;
data+=4;
for(int i=0;i<list_length;i++)
{
Index_List.add_entry(*(int*)data);
data+=4;
}
TypeIndex=*(int*)data;
data+=4;
flags=*(int*)data;
data+=4;
}
Hierarchy_Shape_Set_Collection_Chunk::~Hierarchy_Shape_Set_Collection_Chunk()
{
if(Set_Collection_Name) delete Set_Collection_Name;
}
void Hierarchy_Shape_Set_Collection_Chunk::fill_data_block(char* data_start)
{
strncpy (data_start, identifier, 8);
data_start += 8;
*((int *) data_start) = chunk_size;
data_start += 4;
*(int*)data_start=Set_Collection_Num;
data_start+=4;
strcpy(data_start,Set_Collection_Name);
data_start+=(strlen(Set_Collection_Name)+4)&~3;
*(int*)data_start=Index_List.size();
data_start+=4;
for(LIF<int> slif(&Index_List);!slif.done();slif.next())
{
*(int*)data_start=slif();
data_start+=4;
}
*(int*)data_start=TypeIndex;
data_start+=4;
*(int*)data_start=flags;
data_start+=4;
}
size_t Hierarchy_Shape_Set_Collection_Chunk::size_chunk()
{
chunk_size=12+16;
chunk_size+=(strlen(Set_Collection_Name)+4)&~3;
chunk_size+=Index_List.size()*4;
return chunk_size;
}
///////////////////////////////////////////////////
RIF_IMPLEMENT_DYNCREATE("HIDEGDIS",Hierarchy_Degradation_Distance_Chunk)
Hierarchy_Degradation_Distance_Chunk::Hierarchy_Degradation_Distance_Chunk(Chunk_With_Children* parent,int _num_detail_levels)
:Chunk(parent,"HIDEGDIS")
{
num_detail_levels=_num_detail_levels;
if(num_detail_levels)
{
distance_array=new int[num_detail_levels];
}
else
{
distance_array=0;
}
//fill in some arbitrary distance values
for(int i=0;i<num_detail_levels;i++)
{
distance_array[i]=i*10000;
}
}
Hierarchy_Degradation_Distance_Chunk::Hierarchy_Degradation_Distance_Chunk(Chunk_With_Children* parent,const char* data,size_t)
:Chunk(parent,"HIDEGDIS")
{
num_detail_levels=*(int*)data;
data+=sizeof(int);
if(num_detail_levels)
{
distance_array=new int[num_detail_levels];
}
else
{
distance_array=0;
}
for(int i=0;i<num_detail_levels;i++)
{
distance_array[i]=*(int*)data;
data+=sizeof(int);
}
}
Hierarchy_Degradation_Distance_Chunk::~Hierarchy_Degradation_Distance_Chunk()
{
if(distance_array)delete distance_array;
}
void Hierarchy_Degradation_Distance_Chunk::fill_data_block(char* data_start)
{
strncpy (data_start, identifier, 8);
data_start += 8;
*((int *) data_start) = chunk_size;
data_start += 4;
*(int*)data_start=num_detail_levels;
data_start+=4;
for(int i=0;i<num_detail_levels;i++)
{
*(int*)data_start=distance_array[i];
data_start+=4;
}
}
size_t Hierarchy_Degradation_Distance_Chunk::size_chunk()
{
chunk_size=16+num_detail_levels*4;
return chunk_size;
}
///////////////////////////////////////////////////
RIF_IMPLEMENT_DYNCREATE("HIERBBOX",Hierarchy_Bounding_Box_Chunk)
#if UseOldChunkLoader
Hierarchy_Bounding_Box_Chunk::Hierarchy_Bounding_Box_Chunk(Chunk_With_Children* parent,const char* data,size_t datasize)
:Chunk(parent,"HIERBBOX")
{
assert(datasize==2*sizeof(ChunkVector));
min=*(ChunkVector*)data;
data+=sizeof(ChunkVector);
max=*(ChunkVector*)data;
}
#else
Hierarchy_Bounding_Box_Chunk::Hierarchy_Bounding_Box_Chunk(Chunk_With_Children* parent,const char* data,size_t datasize)
:Chunk(parent,"HIERBBOX")
{
assert(datasize==2*sizeof(ChunkVectorInt));
min=*(ChunkVectorInt*)data;
data+=sizeof(ChunkVectorInt);
max=*(ChunkVectorInt*)data;
}
#endif
void Hierarchy_Bounding_Box_Chunk::fill_data_block(char* data_start)
{
strncpy (data_start, identifier, 8);
data_start += 8;
*((int *) data_start) = chunk_size;
data_start += 4;
*(ChunkVectorInt*)data_start=min;
data_start+=sizeof(ChunkVectorInt);
*(ChunkVectorInt*)data_start=max;
}
///////////////////////////////////////////////////

203
src/win95/hierchnk.hpp Normal file
View file

@ -0,0 +1,203 @@
#ifndef _hierchnk_hpp
#define _hierchnk_hpp 1
#include "chunk.hpp"
#include "list_tem.hpp"
#include "chnktype.hpp"
class Object_Chunk;
class Object_Hierarchy_Data_Chunk;
class Object_Hierarchy_Name_Chunk;
class Shape_Chunk;
#ifdef MAXEXPORT
class INode;
#endif
class Object_Hierarchy_Chunk : public Chunk_With_Children
{
public:
Object_Hierarchy_Chunk(Chunk_With_Children * parent)
: Chunk_With_Children (parent, "OBJCHIER")
{}
// constructor from buffer
Object_Hierarchy_Chunk (Chunk_With_Children * const parent,const char *, size_t const);
List <Object_Hierarchy_Chunk *> list_h_children();
Object_Hierarchy_Data_Chunk * get_data ();
Object_Hierarchy_Name_Chunk * get_name ();
#ifdef MAXEXPORT
INode* node;
#endif
};
class Object_Hierarchy_Data_Chunk : public Chunk
{
public:
Object_Hierarchy_Data_Chunk (Object_Hierarchy_Chunk * parent, const char * obname);
Object_Hierarchy_Data_Chunk (Chunk_With_Children * parent, const char * sdata, size_t /*ssize*/);
~Object_Hierarchy_Data_Chunk ();
int num_extra_data;
int* extra_data;
Object_Chunk * const object;
virtual size_t size_chunk ();
virtual void fill_data_block (char * data_start);
virtual void post_input_processing();
void find_object_for_this_section(); //find the object_chunk from the name
char * ob_name;
private:
friend class Object_Hierarchy_Chunk;
};
// This chunk will normally go in the root as a way of identifiying the hierarchy
class Object_Hierarchy_Name_Chunk : public Chunk
{
public:
Object_Hierarchy_Name_Chunk (Object_Hierarchy_Chunk * parent, const char * hname);
Object_Hierarchy_Name_Chunk (Chunk_With_Children * parent, const char * sdata, size_t /*ssize*/);
~Object_Hierarchy_Name_Chunk();
char * hierarchy_name;
virtual size_t size_chunk ()
{
return(chunk_size = 12 + strlen (hierarchy_name) + 4 - strlen (hierarchy_name)%4);
}
virtual void fill_data_block (char * data_start);
private:
friend class Object_Hierarchy_Chunk;
};
struct Replaced_Shape_Details
{
~Replaced_Shape_Details()
{
if(old_object_name) delete old_object_name;
if(new_object_name) delete new_object_name;
}
//object name of shape to be replaced
char* old_object_name;
//object that replaces it.
char* new_object_name;
};
#define Avp_ShapeSet_Flag_Female 0x00000001
#define List_Object_Hierarchy_Alternate_Shape_Set_Chunk(parent,list) (parent)->lookup_child("OBHALTSH",list)
class Object_Hierarchy_Alternate_Shape_Set_Chunk : public Chunk
{
public :
Object_Hierarchy_Alternate_Shape_Set_Chunk(Chunk_With_Children* parent,int num,const char* name);
Object_Hierarchy_Alternate_Shape_Set_Chunk(Chunk_With_Children* parent,const char* name);
Object_Hierarchy_Alternate_Shape_Set_Chunk (Chunk_With_Children * parent, const char * data, size_t /*ssize*/);
~Object_Hierarchy_Alternate_Shape_Set_Chunk();
virtual size_t size_chunk();
virtual void fill_data_block (char * data_start);
char* Shape_Set_Name;
int Shape_Set_Num;
List<Replaced_Shape_Details*> Replaced_Shape_List;
int flags;
int spare[3];
private:
};
#define AvP_HColl_Flag_NotRandom 0x00000001
#define List_Hierarchy_Shape_Set_Collection_Chunk(parent,list) (parent)->lookup_child("HSETCOLL",list)
//this chunk hold a list of indeces for shape_set_chunks that should be applied
class Hierarchy_Shape_Set_Collection_Chunk : public Chunk
{
public :
Hierarchy_Shape_Set_Collection_Chunk(Chunk_With_Children* parent,int num,const char* name);
Hierarchy_Shape_Set_Collection_Chunk (Chunk_With_Children * parent, const char * data, size_t /*ssize*/);
~Hierarchy_Shape_Set_Collection_Chunk();
virtual size_t size_chunk();
virtual void fill_data_block (char * data_start);
char* Set_Collection_Name;
int Set_Collection_Num;
List<int> Index_List;
int TypeIndex;
int flags;
};
class Hierarchy_Degradation_Distance_Chunk : public Chunk
{
public :
Hierarchy_Degradation_Distance_Chunk(Chunk_With_Children * parent, const char * data, size_t /*ssize*/);
Hierarchy_Degradation_Distance_Chunk(Chunk_With_Children* parent,int _num_detail_levels);
~Hierarchy_Degradation_Distance_Chunk();
virtual size_t size_chunk();
virtual void fill_data_block (char * data_start);
int num_detail_levels;
int* distance_array;
private:
};
class Hierarchy_Bounding_Box_Chunk :public Chunk
{
public :
Hierarchy_Bounding_Box_Chunk(Chunk_With_Children * parent,const char*data,size_t datasize);
Hierarchy_Bounding_Box_Chunk(Chunk_With_Children * parent)
:Chunk(parent,"HIERBBOX")
{}
virtual void fill_data_block (char * data_start);
virtual size_t size_chunk()
{return chunk_size=12+6*4;}
ChunkVectorInt min;
ChunkVectorInt max;
};
#endif

520
src/win95/huffman.cpp Normal file
View file

@ -0,0 +1,520 @@
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "malloc.h"
#include "huffman.hpp"
/* KJL 17:12:25 17/09/98 - Huffman compression/decompression routines */
typedef struct
{
int Symbol;
unsigned int Count;
} HuffItem;
typedef struct HuffNode // 16-byte node structure
{
union
{ // the FIRST four bytes
struct HuffNode *zero; // points to the "zero" branch or...
unsigned int value; // holds the value of an end node
};
union
{ // the SECOND four bytes
struct HuffNode *one; // points to the "one" branch or...
struct HuffNode *link; // points to next end node in list
};
struct HuffNode *parent; // the THIRD four bytes, parent node
union
{ // the FOURTH four bytes
unsigned int bits; // the bit pattern of this end node
struct
{
unsigned char flag;
unsigned char curdepth;
unsigned char maxdepth;
unsigned char unused;
};
};
} HuffNode;
typedef struct
{
long wid;
long bits;
} HuffEncode;
static HuffItem SymbolCensus[257];
static HuffNode TreeNodes[2*257];
static int Depths[MAX_DEPTH+1];
static HuffEncode EncodingTable[257];
#define AllocateMemory malloc
/* KJL 17:16:03 17/09/98 - Compression */
static void PerformSymbolCensus(unsigned char *sourcePtr, int length);
#ifdef __WATCOMC__
static int HuffItemsSortSub(const void *cmp1, const void *cmp2);
#else
static int __cdecl HuffItemsSortSub(const void *cmp1, const void *cmp2);
#endif
static void SortCensusData(void);
static void BuildHuffmanTree(void);
static void MakeHuffTreeFromHuffItems(HuffNode *base, HuffItem *source, int count);
static void MakeCodeLengthsFromHuffTree(int *dest, HuffNode *source, int maxdepth);
static int HuffDepthsAdjust(int *depth, int maxdepth);
static void MakeHuffmanEncodeTable(HuffEncode *encodetable, HuffItem *item, int *depths);
static int HuffEncodeBytes(int *dest, unsigned char *source, int count, HuffEncode *table);
extern HuffmanPackage *HuffmanCompression(unsigned char *sourcePtr, int length)
{
HuffmanPackage *outpackage;
// Step 1: Perform the symbol census
PerformSymbolCensus(sourcePtr,length);
// Step 2: Sorting the census data
SortCensusData();
// Step 3: Building the Huffman tree
BuildHuffmanTree();
// Step 4: Making the code lengths table
MakeCodeLengthsFromHuffTree(Depths, TreeNodes, MAX_DEPTH);
// Step 5: Limiting code lengths
HuffDepthsAdjust(Depths, MAX_DEPTH);
// Step 6: Making the encoding table
MakeHuffmanEncodeTable(EncodingTable,&SymbolCensus[256],Depths);
// Step 7: Encoding data
outpackage = (HuffmanPackage*)AllocateMemory(sizeof(HuffmanPackage)+length);
strncpy(outpackage->Identifier,COMPRESSED_RIF_IDENTIFIER,8);
outpackage->CompressedDataSize = HuffEncodeBytes((int*)(outpackage+1), sourcePtr, length, EncodingTable);
outpackage->UncompressedDataSize = length;
for (int n = 0; n < MAX_DEPTH; n++)
{
outpackage->CodelengthCount[n] = Depths[n + 1];
}
for (n = 0; n < 256; n++)
{
outpackage->ByteAssignment[n] = SymbolCensus[n + 1].Symbol;
}
return outpackage;
}
static void PerformSymbolCensus(unsigned char *sourcePtr, int length)
{
// init array
for (int i=0; i<257; i++)
{
SymbolCensus[i].Symbol = i;
SymbolCensus[i].Count = 0;
}
// count 'em
do
{
SymbolCensus[*sourcePtr++].Count++;
}
while (--length);
}
#ifdef __WATCOMC__
static int HuffItemsSortSub(const void *cmp1, const void *cmp2)
#else
static int __cdecl HuffItemsSortSub(const void *cmp1, const void *cmp2)
#endif
{
if (((HuffItem *)cmp1)->Count > ((HuffItem *)cmp2)->Count)
return 1;
if (((HuffItem *)cmp1)->Count < ((HuffItem *)cmp2)->Count)
return -1;
return 0;
}
static void SortCensusData(void)
{
qsort(SymbolCensus, 257, sizeof(HuffItem), HuffItemsSortSub);
}
static void BuildHuffmanTree(void)
{
MakeHuffTreeFromHuffItems(TreeNodes,SymbolCensus,257);
}
static void MakeHuffTreeFromHuffItems(HuffNode *base, HuffItem *source, int count)
{
HuffNode *movdest, *temp;
int n, upperlim, lowerlim, index;
unsigned int sum;
if (!count) return;
movdest = base + 1;
temp = base + count;
memset(temp, 0, count * sizeof(HuffNode));
for (n = 0; n < count; n++)
{
temp[n].bits = source[n].Count;
}
while (upperlim = --count)
{
if (temp[0].zero)
temp[0].zero->parent = temp[0].one->parent = movdest;
if (temp[1].zero)
temp[1].zero->parent = temp[1].one->parent = movdest + 1;
movdest[0] = *temp++;
movdest[1] = *temp;
sum = movdest[0].bits + movdest[1].bits;
lowerlim = 1;
while (lowerlim != upperlim)
{
index = (lowerlim + upperlim) >> 1;
if (sum >= temp[index].bits)
{
lowerlim = index + 1;
}
else
{
upperlim = index;
}
}
index = lowerlim - 1;
memmove(temp, temp + 1, index * sizeof(HuffNode));
temp[index].bits = sum;
temp[index].zero = movdest;
temp[index].one = movdest + 1;
movdest += 2;
}
base[0] = temp[0];
if (base[0].zero)
base[0].zero->parent = base[0].one->parent = base;
}
static void MakeCodeLengthsFromHuffTree(int *dest, HuffNode *source, int maxdepth)
{
int n, depth;
HuffNode *back;
for (n = 0; n < maxdepth + 1; n++)
dest[n] = 0;
depth = 0;
while (1)
{
while (source->one)
{
source = source->one;
depth++;
}
if (depth > maxdepth) dest[maxdepth]++;
else dest[depth]++;
do
{
back = source;
source = source->parent;
if (!depth--)
return;
}
while (back == source->zero);
source = source->zero;
depth++;
}
}
static int HuffDepthsAdjust(int *depth, int maxdepth)
{
unsigned int n, m, items, sum, goal, gain, busts;
unsigned int promotions, excess, hi;
goal = 1 << maxdepth;
for (n = 0, sum = 0, items = 0; n <= maxdepth; n++)
{
items += depth[n];
sum += (goal >> n) * depth[n];
}
if (items > goal)
return -1; // failure
for (n = maxdepth - 1; sum > goal; n--)
{
if (depth[n])
{
gain = (1 << (maxdepth - n)) - 1;
busts = (sum - goal + gain - 1) / gain;
busts = depth[n] < busts ? depth[n] : busts;
depth[n] -= busts;
depth[maxdepth] += busts;
sum -= busts * gain;
}
}
excess = goal - sum;
for (n = 0; excess; n++)
{
hi = 1 << (maxdepth - n);
for (m = n + 1; m <= maxdepth; m++)
{
gain = hi - (1 << (maxdepth - m));
if (excess < gain)
break;
if (depth[m])
{
promotions = excess / gain;
promotions = depth[m] > promotions ? promotions : depth[m];
depth[n] += promotions;
depth[m] -= promotions;
excess -= promotions * gain;
}
}
}
return 0; // success
}
static void MakeHuffmanEncodeTable(HuffEncode *encodetable, HuffItem *item, int *depths)
{
unsigned int d, bitwidth, depthbit, bt, cur;
int *dep;
dep = depths + 1; // skip depth zero
bitwidth = 0; // start from small bitwidths
cur = 0; // current bit pattern
do
{
do
{
bitwidth++; // go deeper
depthbit = 1 << (bitwidth - 1); // keep depth marker
d = *dep++; // get count here
}
while (!d); // until count non-zero
while (d--)
{ // for all on this level
encodetable[item->Symbol].wid = bitwidth; // record width
encodetable[item->Symbol].bits = cur; // record bits
item--; // count backwards an item
bt = depthbit; // bt is a temp value
while (1)
{
cur ^= bt; // do an add modulo 1
if ((cur & bt) || !bt) // break if now a 1
break; // or out of bits
bt >>= 1; // do next bit position
}
}
}
while (cur); // until cur exhausted
}
static int HuffEncodeBytes(int *dest, unsigned char *source, int count, HuffEncode *table)
{
int *start;
int wid, val, available;
unsigned int accum, bits;
unsigned char *sourcelim, *sourceend;
if (!count) return 0;
start = dest;
sourcelim = sourceend = source + count;
available = 32;
if (sourcelim - 32 < sourcelim)
{
sourcelim -= 32;
}
else
{
sourcelim = source;
}
if (source < sourcelim)
{
do
{
goto lpstart;
do
{
accum = (accum >> wid) | (bits << (32 - wid));
lpstart: val = *source++;
wid = table[val].wid;
bits = table[val].bits;
}
while ((available -= wid) >= 0);
wid += available;
if (wid) accum = (accum >> wid) | (bits << (32 - wid));
*dest++ = accum;
wid -= available;
accum = bits << (32 - wid);
available += 32;
}
while (source < sourcelim);
}
while (1)
{
if (source < sourceend)
{
val = *source++;
}
else if (source == sourceend)
{
val = 0x100; // terminator
source++;
}
else break; // done
wid = table[val].wid;
bits = table[val].bits;
if ((available -= wid) < 0)
{
wid += available;
if (wid)
accum = (accum >> wid) | (bits << (32 - wid));
*dest++ = accum;
wid -= available;
accum = bits << (32 - wid);
available += 32;
}
else
{
accum = (accum >> wid) | (bits << (32 - wid));
}
}
*dest++ = accum >> available;
return (dest - start) * 4;
}
/* KJL 17:16:24 17/09/98 - Decompression */
static int DecodeTable[1<<MAX_DEPTH];
static void MakeHuffmanDecodeTable(int *depth, int depthmax, unsigned char *list);
static int HuffmanDecode(unsigned char *dest, int *source, int *table, int length);
extern char *HuffmanDecompress(HuffmanPackage *inpackage)
{
unsigned char *uncompressedData = NULL;
// Step 1: Make the decoding table
MakeHuffmanDecodeTable(inpackage->CodelengthCount, MAX_DEPTH, inpackage->ByteAssignment);
// Step 2: Decode data
uncompressedData = (unsigned char*)AllocateMemory(inpackage->UncompressedDataSize+16);
if (uncompressedData)
{
HuffmanDecode(uncompressedData,(int*)(inpackage+1),DecodeTable,inpackage->UncompressedDataSize);
}
return (char*)uncompressedData;
}
static void MakeHuffmanDecodeTable(int *depth, int depthmax, unsigned char *list)
{
int thisdepth, depthbit, repcount, repspace, lenbits, temp, count;
int *outp;
int o = 0;
unsigned char *p;
int *outtbl = DecodeTable;
lenbits = 0;
repcount = 1 << depthmax;
repspace = 1;
thisdepth = 0;
depthbit = 4;
p = (unsigned char *)list + 255;
while (1)
{
do
{
lenbits++;
depthbit <<= 1;
repspace <<= 1;
repcount >>= 1;
}
while (!(thisdepth = *depth++));
do
{
if (p < list)
{
temp = 0xff;
}
else
{
temp = lenbits | (*p-- << 8);
}
outp = outtbl + (o >> 2);
count = repcount;
do
{
*outp = temp;
outp += repspace;
}
while (--count);
temp = depthbit;
do
{
temp >>= 1;
if (temp & 3) return;
o ^= temp;
}
while (!(o & temp));
}
while (--thisdepth);
}
}
#define EDXMASK ((((1 << (MAX_DEPTH + 1)) - 1) ^ 1) ^ -1)
static int HuffmanDecode(unsigned char *dest, int *source, int *table, int length)
{
unsigned char *start;
int available, reserve, fill, wid;
unsigned int bits=0, resbits;
unsigned char *p;
start = dest;
available = 0;
reserve = 0;
wid = 0;
do
{
available += wid;
fill = 31 - available;
bits <<= fill;
if (fill > reserve)
{
fill -= reserve;
available += reserve;
if (reserve)
{
bits = (bits >> reserve) | (resbits << (32 - reserve));
}
resbits = *source++;
reserve = 32;
}
bits = (bits >> fill) | (resbits << (32 - fill));
resbits >>= fill;
reserve -= fill;
available = 31;
goto lpent;
do
{
bits >>= wid;
*dest++ = p[1];
lpent: p = (unsigned char *)(((short *)table)+(bits & ~EDXMASK));
}
while ((available -= (wid = *p)) >= 0 && (dest-start)!=length);
}
while (available > -32 && (dest-start)!=length);
return dest - start;
}

31
src/win95/huffman.hpp Normal file
View file

@ -0,0 +1,31 @@
#ifndef _huffman_hpp_included
#define _huffman_hpp_included 1
#ifdef __cplusplus
extern "C"
{
#endif
#define MAX_DEPTH 11
typedef struct
{
char Identifier[8];
int CompressedDataSize;
int UncompressedDataSize;
int CodelengthCount[MAX_DEPTH];
unsigned char ByteAssignment[256];
} HuffmanPackage;
/* KJL 17:16:03 17/09/98 - Compression */
extern HuffmanPackage *HuffmanCompression(unsigned char *sourcePtr, int length);
/* KJL 16:53:53 19/09/98 - Decompression */
extern char *HuffmanDecompress(HuffmanPackage *inpackage);
#define COMPRESSED_RIF_IDENTIFIER "REBCRIF1"
#ifdef __cplusplus
};
#endif
#endif

826
src/win95/iff.cpp Normal file
View file

@ -0,0 +1,826 @@
#include "advwin32.h"
#include "iff.hpp"
#include <stdio.h>
#include <tchar.h>
#if defined(_CPPRTTI) && !defined(NDEBUG)
#include <typeinfo>
#endif
#ifndef NDEBUG
#define HT_FAIL(str) (::IFF::DisplayMessage(TEXT("IFF Internal Error"),TEXT(str)),exit(-45))
#endif
#include "hash_tem.hpp"
namespace IFF
{
/*****************************/
/* Original File: iffObj.cpp */
/*****************************/
#ifndef NDEBUG
static bool g_bAllocListActive = false;
class AllocList : public ::HashTable<Unknown *>
{
public:
AllocList()
{
g_bAllocListActive = true;
}
~AllocList()
{
#ifdef _CPPRTTI // this works in MSVC 5.0 - ie. the macro is defined if RTTI is turned on
// but there appears to be no preprocessor way of determining if RTTI is turned on under Watcom
// No, I think it works in Watcom too, actually...
#pragma message("Run-Time Type Identification (RTTI) is enabled")
for (Iterator itLeak(*this) ; !itLeak.Done() ; itLeak.Next())
{
TCHAR buf[256];
::wsprintf(buf,TEXT("Object not deallocated:\nType: %s\nRefCnt: %u"),typeid(*itLeak.Get()).name(),itLeak.Get()->m_nRefCnt);
DisplayMessage(TEXT("Memory Leak!"),buf);
}
#else // ! _CPPRTTI
unsigned nRefs(0);
for (Iterator itLeak(*this) ; !itLeak.Done() ; itLeak.Next())
{
nRefs += itLeak.Get()->m_nRefCnt;
}
if (Size())
{
char buf[256];
::sprintf(buf,"Objects not deallocated:\nNumber of Objects: %u\nNumber of References: %u",Size(),nRefs);
DisplayMessage("Memory Leaks!",buf);
}
#endif // ! _CPPRTTI
g_bAllocListActive = false;
}
};
static AllocList g_listAllocated;
void DbRemember(Unknown * pObj)
{
g_listAllocated.AddAsserted(pObj);
}
void DbForget(Unknown * pObj)
{
if (g_bAllocListActive)
g_listAllocated.RemoveAsserted(pObj);
}
#endif // ! NDEBUG
/******************************/
/* Original File: iffFile.cpp */
/******************************/
bool GenericFile::Load(::MediaMedium * pMedium)
{
ArchvIn ar;
ar.Open(pMedium);
if (!ar.m_bError)
Serialize(&ar);
ar.Close();
return ! ar.m_bError;
}
#ifndef IFF_READ_ONLY
bool GenericFile::Write(::MediaMedium * pMedium)
{
ArchvOut ar;
ar.Open(pMedium);
if (!ar.m_bError)
Serialize(&ar);
ar.Close();
return ! ar.m_bError;
}
#endif // ! IFF_READ_ONLY
#ifdef _IFF_WIN_TARGET
typedef ::MediaWinFileMedium DeviceFileHandle;
#else
typedef ::MediaStdFileMedium DeviceFileHandle;
#endif
bool GenericFile::Load(TCHAR const * pszFileName)
{
#ifndef IFF_READ_ONLY
if (m_pszFileName) delete[] m_pszFileName;
m_pszFileName = new TCHAR [_tcslen(pszFileName)+1];
_tcscpy(m_pszFileName,pszFileName);
#endif // ! IFF_READ_ONLY
#ifdef _IFF_WIN_TARGET
::MediaWinFileMedium * pMedium = new ::MediaWinFileMedium;
pMedium->Open(pszFileName, GENERIC_READ);
#else
::MediaStdFileMedium * pMedium = new ::MediaStdFileMedium;
pMedium->Open(pszFileName, "rb");
#endif
bool bRet = Load(pMedium);
pMedium->Release();
return bRet;
}
#ifndef IFF_READ_ONLY
bool GenericFile::Write(TCHAR const * pszFileName)
{
if (pszFileName)
{
if (m_pszFileName) delete[] m_pszFileName;
m_pszFileName = new TCHAR [_tcslen(pszFileName)+1];
_tcscpy(m_pszFileName,pszFileName);
}
if (!m_pszFileName) return false;
#ifdef _IFF_WIN_TARGET
::MediaWinFileMedium * pMedium = new ::MediaWinFileMedium;
pMedium->Open(pszFileName, GENERIC_WRITE);
#else
::MediaStdFileMedium * pMedium = new ::MediaStdFileMedium;
pMedium->Open(pszFileName, "wb");
#endif
bool bRet = Write(pMedium);
pMedium->Release();
return bRet;
}
#endif // ! IFF_READ_ONLY
void File::Serialize(Archive * pArchv)
{
if (pArchv->m_bIsLoading)
{
if (m_pContents)
{
m_pContents->Release();
m_pContents = NULL;
}
pArchv->Transfer(m_idType);
if (!!m_idType && (m_idType == ID("FORM") || m_idType == ID("LIST") || m_idType == ID("CAT ")))
{
m_pContents = static_cast<Composite *>(Chunk::Load(ID_ANY,pArchv,m_idType));
}
else
{
pArchv->m_bError = true;
}
}
else
{
if (m_pContents)
m_pContents->Chunk::Write(pArchv);
else
pArchv->m_bError = true;
}
}
File::~File()
{
if (m_pContents)
m_pContents->Release();
}
/*******************************/
/* Original File: iffChunk.cpp */
/*******************************/
class RegEntry
{
public:
ID m_idParent;
ID m_idChunk;
Chunk * (* m_pfnCreate) ();
inline bool operator == (RegEntry const & rEntry) const
{
return m_idParent == rEntry.m_idParent && m_idChunk == rEntry.m_idChunk;
}
inline bool operator != (RegEntry const & rEntry) const
{
return ! operator == (rEntry);
}
};
} // namespace IFF
inline unsigned HashFunction(IFF::RegEntry const & rEntry)
{
return HashFunction(rEntry.m_idChunk.m_nID);
}
namespace IFF {
static ::HashTable<RegEntry> * g_pRegister = NULL;
void Chunk::Register(ID idParent, ID idChunk, Chunk * (* pfnCreate) () )
{
static ::HashTable<RegEntry> reg;
g_pRegister = &reg;
RegEntry entry;
entry.m_idParent = idParent;
entry.m_idChunk = idChunk;
entry.m_pfnCreate = pfnCreate;
reg.AddAsserted(entry);
}
Chunk * Chunk::DynCreate(ID idParent, ID idChunk)
{
if (g_pRegister)
{
RegEntry test;
test.m_idParent = idParent;
test.m_idChunk = idChunk;
test.m_pfnCreate = NULL;
RegEntry const * pEntry = g_pRegister->Contains(test);
if (pEntry)
{
return pEntry->m_pfnCreate();
}
}
return new MiscChunk(idChunk);
}
void Chunk::Write(Archive * pArchv)
{
Archive * pSubArchv = pArchv->OpenSubArchive();
Serialize(pSubArchv);
UINT32 nSize = pSubArchv->GetSize();
pArchv->Transfer(m_idCk);
pArchv->Transfer(nSize);
pArchv->CloseSubArchive(pSubArchv);
BYTE z = 0;
if (nSize & 1) pArchv->Transfer(z);
}
Chunk * Chunk::Load(ID idParent, Archive * pArchv, ID idChunk, bool bKnown)
{
if (!idChunk)
pArchv->Transfer(idChunk);
Chunk * pChunk = bKnown ? DynCreate(idParent, idChunk) : new MiscChunk(idChunk);
UINT32 nSize;
pArchv->Transfer(nSize);
Archive * pSubArchv = pArchv->OpenSubArchive(nSize);
pChunk->Serialize(pSubArchv);
pArchv->CloseSubArchive(pSubArchv);
BYTE z = 0;
if (nSize & 1) pArchv->Transfer(z);
return pChunk;
}
Chunk * Chunk::GetProperty(ID idProp) const
{
if (m_pParent && m_pNode)
return m_pParent->GetProperty(m_pNode,idProp);
else
return NULL;
}
/*******************************/
/* Original File: iffBlock.cpp */
/*******************************/
Composite::~Composite()
{
DeleteAllChildren();
}
ChildNode * Composite::GetFirstChild(ID idMatch) const
{
for (ChildNode * pSrchNode = m_pFirst; pSrchNode; pSrchNode = GetNextChild(pSrchNode))
{
if (pSrchNode->GetChunk()->m_idCk == idMatch && !pSrchNode->GetChunk()->IsUnknown()) return pSrchNode;
}
return NULL;
}
ChildNode * Composite::GetLastChild(ID idMatch) const
{
for (ChildNode * pSrchNode = m_pLast; pSrchNode; pSrchNode = GetPrevChild(pSrchNode))
{
if (pSrchNode->GetChunk()->m_idCk == idMatch && !pSrchNode->GetChunk()->IsUnknown()) return pSrchNode;
}
return NULL;
}
ChildNode * Composite::GetNextChild(ChildNode const * pNode, ID idMatch)
{
for (ChildNode * pSrchNode = GetNextChild(pNode); pSrchNode; pSrchNode = GetNextChild(pSrchNode))
{
if (pSrchNode->GetChunk()->m_idCk == idMatch && !pSrchNode->GetChunk()->IsUnknown()) return pSrchNode;
}
return NULL;
}
ChildNode * Composite::GetPrevChild(ChildNode const * pNode, ID idMatch)
{
for (ChildNode * pSrchNode = GetPrevChild(pNode); pSrchNode; pSrchNode = GetPrevChild(pSrchNode))
{
if (pSrchNode->GetChunk()->m_idCk == idMatch && !pSrchNode->GetChunk()->IsUnknown()) return pSrchNode;
}
return NULL;
}
Chunk * Composite::GetProperty(ChildNode const * pNode, ID idProp) const
{
// search backward for ID
ChildNode * pFindNode = GetPrevChild(pNode, idProp);
if (pFindNode) return pFindNode->GetChunk();
// if not found, search parent backwards, for "PROP ...." then get that
// and if not in the parent, search its parent similarly
// provided all these parents are of type LIST ....
for (Composite const * pThis = this; pThis->m_pParent && pThis->m_pParent->m_idCk == ID("LIST"); pThis = pThis->m_pParent)
{
if (pThis->m_pNode)
{
for (ChildNode * pFindProp = pThis->m_pParent->GetPrevChild(pThis->m_pNode,"PROP"); pFindProp; pFindProp = pThis->m_pParent->GetPrevChild(pFindProp,"PROP"))
{
Composite * pProp = static_cast<Composite *>(pFindProp->GetChunk());
if (pProp->m_idData == m_idData)
{
ChildNode * pFindNode = pProp->GetLastChild(idProp);
if (pFindNode) return pFindNode->GetChunk();
}
}
}
}
return NULL;
}
void Composite::DeleteChild(ChildNode * pNode)
{
if (pNode->m_pPrev)
pNode->m_pPrev->m_pNext = pNode->m_pNext;
else
m_pFirst = pNode->m_pNext;
if (pNode->m_pNext)
pNode->m_pNext->m_pPrev = pNode->m_pPrev;
else
m_pLast = pNode->m_pPrev;
pNode->m_pChunk->m_pParent = NULL;
pNode->m_pChunk->m_pNode = NULL;
pNode->m_pChunk->Release();
pNode->Release();
}
void Composite::DeleteAllChildren()
{
while (m_pFirst)
DeleteChild(m_pFirst);
}
ChildNode * Composite::InsertChildFirst(Chunk * pChunk)
{
pChunk->AddRef();
pChunk->m_pParent = this;
ChildNode * pNode = new ChildNode;
pChunk->m_pNode = pNode;
pNode->m_pChunk = pChunk;
pNode->m_pPrev = NULL;
pNode->m_pNext = m_pFirst;
if (m_pFirst)
m_pFirst->m_pPrev = pNode;
m_pFirst = pNode;
if (!m_pLast)
m_pLast = m_pFirst;
return pNode;
}
ChildNode * Composite::InsertChildLast(Chunk * pChunk)
{
pChunk->m_pParent = this;
pChunk->AddRef();
ChildNode * pNode = new ChildNode;
pChunk->m_pNode = pNode;
pNode->m_pChunk = pChunk;
pNode->m_pNext = NULL;
pNode->m_pPrev = m_pLast;
if (m_pLast)
m_pLast->m_pNext = pNode;
m_pLast = pNode;
if (!m_pFirst)
m_pFirst = m_pLast;
return pNode;
}
ChildNode * Composite::InsertChildAfter(ChildNode * pRefNode, Chunk * pChunk)
{
pChunk->m_pParent = this;
pChunk->AddRef();
ChildNode * pNode = new ChildNode;
pChunk->m_pNode = pNode;
pNode->m_pChunk = pChunk;
pNode->m_pNext = pRefNode->m_pNext;
pNode->m_pPrev = pRefNode;
if (pRefNode->m_pNext)
pRefNode->m_pNext->m_pPrev = pNode;
else
m_pLast = pNode;
pRefNode->m_pNext = pNode;
return pNode;
}
ChildNode * Composite::InsertChildBefore(ChildNode * pRefNode, Chunk * pChunk)
{
pChunk->m_pParent = this;
pChunk->AddRef();
ChildNode * pNode = new ChildNode;
pChunk->m_pNode = pNode;
pNode->m_pChunk = pChunk;
pNode->m_pPrev = pRefNode->m_pPrev;
pNode->m_pNext = pRefNode;
if (pRefNode->m_pPrev)
pRefNode->m_pPrev->m_pNext = pNode;
else
m_pFirst = pNode;
pRefNode->m_pPrev = pNode;
return pNode;
}
bool Composite::EnumChildren(ID idData, ID idChunk, bool (* pfnCallback) (Chunk *, void *), void * pData) const
{
if (m_idData != idData) return true;
for (ChildNode * pNode = GetFirstChild(idChunk); pNode; pNode = GetNextChild(pNode,idChunk))
{
if (!pfnCallback(pNode->GetChunk(),pData)) return false;
}
return true;
}
bool Composite::IsValidChildID(ID) const
{
return true;
}
Chunk * Composite::LoadChunk(Archive * pArchv) const
{
ID idChunk;
pArchv->Transfer(idChunk);
return Chunk::Load(m_idData, pArchv, idChunk, IsValidChildID(idChunk));
}
void Composite::Serialize(Archive * pArchv)
{
pArchv->Transfer(m_idData);
if (pArchv->m_bIsLoading)
{
DeleteAllChildren();
while (pArchv->GetSize())
{
Chunk * pChunk = LoadChunk(pArchv);
InsertChildLast(pChunk);
pChunk->Release();
}
}
else
{
for (ChildNode * pNode = m_pFirst; pNode; pNode = GetNextChild(pNode))
{
pNode->GetChunk()->Write(pArchv);
}
}
}
bool Form::IsValidChildID(ID id) const
{
// contents: FORM | LIST | CAT | LocalChunk
return ID("PROP") != id;
}
bool Cat::EnumChildren(ID idData, ID idChunk, bool (* pfnCallback) (Chunk *, void *), void * pData) const
{
for (ChildNode * pNode = GetFirstChild(); pNode; pNode = GetNextChild(pNode))
{
Composite const * pComposite = static_cast<Composite const *>(pNode->GetChunk());
if (pComposite->m_idData == idData && !pComposite->EnumChildren(idData,idChunk,pfnCallback,pData)) return false;
}
return true;
}
bool Cat::IsValidChildID(ID id) const
{
// contentes: FROM | LIST | CAT
return ID("FORM") == id || ID("LIST") == id || ID("CAT ") == id;
}
bool List::EnumChildren(ID idData, ID idChunk, bool (* pfnCallback) (Chunk *, void *), void * pData) const
{
for (ChildNode * pNode = GetFirstChild(); pNode; pNode = GetNextChild(pNode))
{
Composite const * pComposite = static_cast<Composite const *>(pNode->GetChunk());
if (pComposite->m_idData == idData && !pComposite->EnumChildren(idData,idChunk,pfnCallback,pData)) return false;
}
return true;
}
bool List::IsValidChildID(ID id) const
{
// contentes: FROM | LIST | CAT | PROP
return ID("FORM") == id || ID("LIST") == id || ID("CAT ") == id || ID("PROP") == id;
}
bool Prop::IsValidChildID(ID id) const
{
// contentes: LocalChunk
return ID("FORM") != id && ID("LIST") != id && ID("CAT ") != id && ID("PROP") != id;
}
IFF_IMPLEMENT_DYNCREATE(ID_ANY,"FORM",Form)
IFF_IMPLEMENT_DYNCREATE(ID_ANY,"LIST",List)
IFF_IMPLEMENT_DYNCREATE(ID_ANY,"CAT ",Cat)
IFF_IMPLEMENT_DYNCREATE(ID_ANY,"PROP",Prop)
/*******************************/
/* Original File: iffMscCk.cpp */
/*******************************/
#ifdef IFF_READ_ONLY
void MiscChunk::Serialize(Archive * ){}
#else // ! IFF_READ_ONLY
void MiscChunk::Serialize(Archive * pArchv)
{
if (pArchv->m_bIsLoading)
{
if (m_pData)
delete[] m_pData;
m_nSize = pArchv->GetSize();
m_pData = new BYTE [m_nSize];
}
pArchv->TransferBlock(m_pData,m_nSize);
}
MiscChunk::~MiscChunk()
{
if (m_pData)
delete[] m_pData;
}
/*******************************/
/* Original File: iffSData.cpp */
/*******************************/
DataBlock::~DataBlock()
{
delete[] m_pBlock;
}
inline bool DataBlock::WriteToFile(::MediaMedium * pMedium) const
{
pMedium->WriteBlock(m_pBlock,m_nCurSize);
return pMedium->m_fError ? false : true;
}
void DataBlock::Expand(unsigned nMinSize)
{
while (m_nMaxSize < nMinSize)
m_nMaxSize*=2;
UBYTE * pNewBlock = new UBYTE [m_nMaxSize];
memcpy(pNewBlock,m_pBlock,m_nCurSize);
delete[] m_pBlock;
m_pBlock = pNewBlock;
}
DataNode::~DataNode()
{
if (m_pPrev)
m_pPrev->Release();
if (m_pData)
m_pData->Release();
if (m_pNext)
m_pNext->Release();
}
unsigned DataNode::GetDataSize() const
{
return
(m_pPrev ? m_pPrev->GetDataSize() : 0)
+ (m_pData ? m_pData->GetDataSize() : 0)
+ (m_pNext ? m_pNext->GetDataSize() : 0)
;
}
bool DataNode::WriteToFile(::MediaMedium * pMedium) const
{
return
(m_pPrev ? m_pPrev->WriteToFile(pMedium) : true)
&& (m_pData ? m_pData->WriteToFile(pMedium) : true)
&& (m_pNext ? m_pNext->WriteToFile(pMedium) : true)
;
}
SerialData::~SerialData()
{
m_pData->Release();
if (m_pPrev)
m_pPrev->Release();
}
void SerialData::Clear()
{
m_pData->Release();
if (m_pPrev)
m_pPrev->Release();
m_pData = new DataBlock;
m_pPrev = NULL;
}
unsigned SerialData::GetDataSize() const
{
return
(m_pPrev ? m_pPrev->GetDataSize() : 0)
+ m_pData->GetDataSize()
;
}
bool SerialData::WriteToFile(::MediaMedium * pMedium) const
{
return
(m_pPrev ? m_pPrev->WriteToFile(pMedium) : true)
&& m_pData->WriteToFile(pMedium)
;
}
/*******************************/
/* Original File: iffArchO.cpp */
/*******************************/
void ArchvOut::Open(::MediaMedium * pMedium)
{
if (m_pMedium) m_pMedium->Release();
m_pMedium = pMedium;
m_pMedium->AddRef();
if (m_pMedium->m_fError)
{
m_bError = true;
m_pMedium->Release();
m_pMedium = NULL;
}
}
void ArchvOut::Close()
{
if (m_pMedium)
{
if (!WriteToFile(m_pMedium))
m_bError = true;
m_pMedium->Release();
m_pMedium = NULL;
}
}
ArchvOut::~ArchvOut()
{
Close();
}
Archive * ArchvOut::OpenSubArchive(unsigned)
{
return new ArchvOut;
}
void ArchvOut::CloseSubArchive(Archive * pSub)
{
m_bError = m_bError || pSub->m_bError;
Append(static_cast<ArchvOut *>(pSub));
pSub->Release();
}
#endif // IFF_READ_ONLY
/*******************************/
/* Original File: iffArchI.cpp */
/*******************************/
void ArchvIn::Open(::MediaMedium * pMedium)
{
if (m_pMedium) m_pMedium->Release();
m_pMedium = pMedium;
m_pMedium->AddRef();
if (m_pMedium->m_fError)
{
m_bError = true;
m_pMedium->Release();
m_pMedium = NULL;
}
else
{
m_nEndPos = m_pMedium->GetRemainingSize();
m_nBytesRemaining = m_nEndPos;
}
}
void ArchvIn::Close()
{
if (m_pMedium)
{
m_pMedium->SetPos(m_nEndPos);
m_pMedium->Release();
m_pMedium = NULL;
}
}
inline ArchvIn::ArchvIn(ArchvIn * pParent, unsigned nSize)
: _IFF_ARCHI_FLAG(true)
, m_pMedium(pParent->m_pMedium)
, m_nBytesRemaining(nSize)
{
m_nEndPos = pParent->m_pMedium->GetPos();
m_nEndPos += nSize;
pParent->m_nBytesRemaining -= nSize;
m_pMedium->AddRef();
}
ArchvIn::~ArchvIn()
{
Close();
}
Archive * ArchvIn::OpenSubArchive(unsigned nSize)
{
return new ArchvIn(this,nSize);
}
void ArchvIn::CloseSubArchive(Archive * pSub)
{
m_bError = m_bError || pSub->m_bError;
pSub->Release();
}
} // namespace IFF

991
src/win95/iff.hpp Normal file
View file

@ -0,0 +1,991 @@
#ifndef _INCLUDED_IFF_HPP_
#define _INCLUDED_IFF_HPP_
#if defined(_WIN32) || defined(WIN32) || defined(WINDOWS) || defined(_WINDOWS)
#define _IFF_WIN_TARGET
#include <windows.h>
#else // ! WIN32 && ! _WIN32 && ! WINDOWS && ! _WINDOWS
#include <stdio.h>
#include <conio.h>
#endif // ! WIN32 && ! _WIN32 && ! WINDOWS && ! _WINDOWS
#include "media.hpp"
namespace IFF
{
/*************************/
/* Class Hierarchy: */
/* */
/* + Unknown */
/* + SerializableObj */
/* + GenericFile */
/* + File */
/* + Chunk */
/* + Composite */
/* + Form */
/* + Cat */
/* + List */
/* + Prop */
/* + MiscChunk */
/* + <user chunks> */
/* + Arvhive */
/* + ArchvIn */
/* + ArchvOut(*) */
/* + DataBlock */
/* + DataNode */
/* + SerialData */
/* + ArchvOut(*) */
/* + ChildNode */
/* + DeviceHandle */
/*************************/
#ifdef _IFF_WIN_TARGET
inline void DisplayMessage(TCHAR const * pszTitle,TCHAR const * pszText)
{
::MessageBox(NULL,pszText,pszTitle,MB_OK|MB_ICONEXCLAMATION|MB_SETFOREGROUND);
}
#else
inline void DisplayMessage(char const * pszTitle,char const * pszText)
{
::printf("%s\n%s\n",pszTitle,pszText);
while (::kbhit())
::getch();
while (!::kbhit() || '\r' != ::getch())
;
}
#endif
// forward refs
//class Unknown;
//class SerializableObj;
//class GenericFile;
//class File;
//class Chunk;
class Composite;
//class Form;
//class Cat;
//class List;
//class Prop;
//class MiscChunk;
//class Archive;
//class ArchvIn;
//class ArchvOut;
//class DataBlock;
//class DataNode;
//class SerialData;
class ChildNode;
//class DeviceHandle;
/*****************************/
/* Original File: iffObj.hpp */
/*****************************/
class Unknown
{
public:
unsigned AddRef() { return ++m_nRefCnt; }
unsigned Release() { if (0==(--m_nRefCnt)) { delete this; return 0;} else return m_nRefCnt; }
protected:
virtual ~Unknown() {
#ifndef NDEBUG
DbForget(this);
#endif
}
Unknown() : m_nRefCnt(1) {
#ifndef NDEBUG
DbRemember(this);
#endif
}
Unknown(Unknown const &) : m_nRefCnt(1) {
#ifndef NDEBUG
DbRemember(this);
#endif
}
private:
unsigned m_nRefCnt;
#ifndef NDEBUG
friend void DbRemember(Unknown * pObj);
friend void DbForget(Unknown * pObj);
friend class AllocList;
#endif
};
/*******************************/
/* Original File: iffTypes.hpp */
/*******************************/
// deal with any silly bastard who's put #define BYTE ... in a header, etc.
#ifdef BYTE
#undef BYTE
#pragma message("BYTE was defined - undefining")
#endif
typedef signed char BYTE;
typedef unsigned char UBYTE;
typedef signed short INT16;
typedef unsigned short UINT16;
typedef signed INT32;
typedef unsigned UINT32;
typedef signed __int64 INT64;
typedef unsigned __int64 UINT64;
struct RGBTriple
{
UBYTE r;
UBYTE g;
UBYTE b;
};
union ID
{
UINT32 m_nID;
char m_sID[4];
inline ID(){}
inline ID(char const * pszID) { m_nID = *reinterpret_cast<UINT32 const *>(pszID); }
inline ID(UINT32 nID) : m_nID(nID) {}
inline operator UINT32 () const { return m_nID; }
inline operator char const * () const { return &m_sID[0]; }
inline bool operator == (ID const & rId) const { return !m_nID || !rId.m_nID || m_nID == rId.m_nID; }
inline bool operator != (ID const & rId) const { return ! operator == (rId); }
inline bool operator ! () const { return !m_nID; }
};
ID const ID_ANY(0U);
#ifndef IFF_READ_ONLY
/*******************************/
/* Original File: iffSData.hpp */
/*******************************/
class DataBlock : public Unknown
{
public:
virtual ~DataBlock();
DataBlock() : m_pBlock(new UBYTE [128]), m_nMaxSize(128), m_nCurSize(0) {}
unsigned GetDataSize() const;
UBYTE const * GetDataPtr() const;
bool WriteToFile(::MediaMedium * pMedium) const;
void Append(UBYTE byte);
void Append(void const * pData, unsigned nSize);
private:
void Expand(unsigned nMinSize);
UBYTE * m_pBlock;
unsigned m_nMaxSize;
unsigned m_nCurSize;
};
inline unsigned DataBlock::GetDataSize() const
{
return m_nCurSize;
}
inline UBYTE const * DataBlock::GetDataPtr() const
{
return m_pBlock;
}
inline void DataBlock::Append(UBYTE byte)
{
if (m_nCurSize >= m_nMaxSize)
Expand(m_nCurSize+1);
m_pBlock[m_nCurSize++] = byte;
}
inline void DataBlock::Append(void const * pData, unsigned nSize)
{
if (m_nCurSize+nSize > m_nMaxSize)
Expand(m_nCurSize+nSize+32);
memcpy(&m_pBlock[m_nCurSize],pData,nSize);
m_nCurSize += nSize;
}
class DataNode : public Unknown
{
public:
DataNode(DataNode * pNext, DataBlock * pData, DataNode * pPrev)
: m_pNext(pNext)
, m_pData(pData)
, m_pPrev(pPrev)
{
if (pNext) pNext->AddRef();
if (pData) pData->AddRef();
if (pPrev) pPrev->AddRef();
}
virtual ~DataNode();
unsigned GetDataSize() const;
bool WriteToFile(::MediaMedium * pMedium) const;
private:
DataNode * m_pNext;
DataBlock * m_pData;
DataNode * m_pPrev;
};
class SerialData : public Unknown
{
public:
virtual ~SerialData();
SerialData() : m_pPrev(NULL), m_pData(new DataBlock) {};
void Clear();
unsigned GetDataSize() const;
bool WriteToFile(::MediaMedium * pMedium) const;
void Append(UBYTE byte);
void Append(void const * pData, unsigned nSize);
void Append(SerialData * pData);
private:
DataBlock * m_pData;
DataNode * m_pPrev;
};
inline void SerialData::Append(UBYTE byte)
{
m_pData->Append(byte);
}
inline void SerialData::Append(void const * pData, unsigned nSize)
{
m_pData->Append(pData,nSize);
}
inline void SerialData::Append(SerialData * pIns)
{
DataNode * pNewNode = new DataNode(pIns->m_pPrev,m_pData,m_pPrev);
m_pData->Release();
m_pData = pIns->m_pData;
pIns->m_pData->AddRef();
if (m_pPrev)
m_pPrev->Release();
m_pPrev = pNewNode;
}
/*******************************/
/* Original File: iffArchv.hpp */
/*******************************/
class Archive : public Unknown
{
public:
// constructor - construct with true iff the archive is for loading data
Archive(bool bIsLoading) : m_bIsLoading(bIsLoading), m_bError(false) {}
// to determine easily whenever necessary if the archive is loading data
bool const m_bIsLoading;
bool m_bError;
// returns either the size in bytes of the data so far written to a storing archive
// or the number of bytes remaining to be read from a loading archive, could be negative
// if too many bytes were read
virtual signed GetSize() const = 0;
// if the archive is loading, nSize bytes are sectioned off to be read from a sub-archive
// or if the archive is storing, nSize is ignored and data written to the sub-archive
// will be stored when the sub-archive is closed
virtual Archive * OpenSubArchive(unsigned nSize = 0) = 0;
// commits data written temporarily to a sub-archive (if storing)
// and advances the archive to the next byte after the sub-archive's data
virtual void CloseSubArchive(Archive * pSub) = 0;
virtual void Open(::MediaMedium * pMedium) = 0;
virtual void Close() = 0;
virtual void Transfer(RGBTriple &) = 0;
virtual void Transfer(BYTE &) = 0;
virtual void Transfer(UBYTE &) = 0;
virtual void Transfer(INT16 &) = 0;
virtual void Transfer(UINT16 &) = 0;
virtual void Transfer(INT32 &) = 0;
virtual void Transfer(UINT32 &) = 0;
virtual void Transfer(INT64 &) = 0;
virtual void Transfer(UINT64 &) = 0;
virtual void Transfer(ID &) = 0;
virtual void TransferBlock(void * pData,unsigned nSize) = 0;
};
/*******************************/
/* Original File: iffArchO.hpp */
/*******************************/
class ArchvOut : public Archive, public SerialData
{
public:
ArchvOut() : Archive(false), m_pMedium(NULL) {}
~ArchvOut();
signed GetSize() const;
Archive * OpenSubArchive(unsigned nSize = 0);
void CloseSubArchive(Archive * pSub);
void Open(::MediaMedium * pMedium);
void Close();
void Transfer(RGBTriple &);
void Transfer(BYTE &);
void Transfer(UBYTE &);
void Transfer(INT16 &);
void Transfer(UINT16 &);
void Transfer(INT32 &);
void Transfer(UINT32 &);
void Transfer(INT64 &);
void Transfer(UINT64 &);
void Transfer(ID &);
void TransferBlock(void * pData,unsigned nSize);
private:
::MediaMedium * m_pMedium;
};
inline signed ArchvOut::GetSize() const
{
return GetDataSize();
}
inline void ArchvOut::Transfer(RGBTriple & n)
{
Append(n.r);
Append(n.g);
Append(n.b);
}
inline void ArchvOut::Transfer(BYTE & n)
{
Append(n);
}
inline void ArchvOut::Transfer(UBYTE & n)
{
Append(n);
}
inline void ArchvOut::Transfer(INT16 & n)
{
Append(static_cast<BYTE>(n >> 8));
Append(static_cast<BYTE>(n));
}
inline void ArchvOut::Transfer(UINT16 & n)
{
Append(static_cast<UBYTE>(n >> 8));
Append(static_cast<UBYTE>(n));
}
inline void ArchvOut::Transfer(INT32 & n)
{
Append(static_cast<BYTE>(n >> 24));
Append(static_cast<BYTE>(n >> 16));
Append(static_cast<BYTE>(n >> 8));
Append(static_cast<BYTE>(n));
}
inline void ArchvOut::Transfer(UINT32 & n)
{
Append(static_cast<UBYTE>(n >> 24));
Append(static_cast<UBYTE>(n >> 16));
Append(static_cast<UBYTE>(n >> 8));
Append(static_cast<UBYTE>(n));
}
inline void ArchvOut::Transfer(INT64 & n)
{
Append(static_cast<BYTE>(n >> 56));
Append(static_cast<BYTE>(n >> 48));
Append(static_cast<BYTE>(n >> 40));
Append(static_cast<BYTE>(n >> 32));
Append(static_cast<BYTE>(n >> 24));
Append(static_cast<BYTE>(n >> 16));
Append(static_cast<BYTE>(n >> 8));
Append(static_cast<BYTE>(n));
}
inline void ArchvOut::Transfer(UINT64 & n)
{
Append(static_cast<UBYTE>(n >> 56));
Append(static_cast<UBYTE>(n >> 48));
Append(static_cast<UBYTE>(n >> 40));
Append(static_cast<UBYTE>(n >> 32));
Append(static_cast<UBYTE>(n >> 24));
Append(static_cast<UBYTE>(n >> 16));
Append(static_cast<UBYTE>(n >> 8));
Append(static_cast<UBYTE>(n));
}
inline void ArchvOut::Transfer(ID & n)
{
Append(&n,4);
}
inline void ArchvOut::TransferBlock(void * pData,unsigned nSize)
{
Append(pData,nSize);
}
#endif // ! IFF_READ_ONLY
/*******************************/
/* Original File: iffArchI.hpp */
/*******************************/
#ifdef IFF_READ_ONLY
#define _IFF_ARCHI_BASE Unknown
#define _IFF_ARCHI_GENR ArchvIn
#define _IFF_ARCHI_FLAG m_bIsLoading
#define _IFF_ARCHI_INIT ,m_bError(false)
#else // ! IFF_READ_ONLY
#define _IFF_ARCHI_BASE Archive
#define _IFF_ARCHI_GENR Archive
#define _IFF_ARCHI_FLAG Archive
#define _IFF_ARCHI_INIT
#endif // ! IFF_READ_ONLY
class ArchvIn : public _IFF_ARCHI_BASE
{
public:
ArchvIn() : _IFF_ARCHI_FLAG(true), m_pMedium(NULL) _IFF_ARCHI_INIT {}
~ArchvIn();
#ifdef IFF_READ_ONLY
bool const m_bIsLoading;
bool m_bError;
#endif // IFF_READ_ONLY
signed GetSize() const;
_IFF_ARCHI_GENR * OpenSubArchive(unsigned nSize = 0);
void CloseSubArchive(_IFF_ARCHI_GENR * pSub);
void Open(::MediaMedium * pMedium);
void Close();
void Transfer(RGBTriple &);
void Transfer(BYTE &);
void Transfer(UBYTE &);
void Transfer(INT16 &);
void Transfer(UINT16 &);
void Transfer(INT32 &);
void Transfer(UINT32 &);
void Transfer(INT64 &);
void Transfer(UINT64 &);
void Transfer(ID &);
void TransferBlock(void * pData,unsigned nSize);
private:
ArchvIn(ArchvIn * pParent, unsigned nSize);
::MediaMedium * m_pMedium;
signed m_nBytesRemaining;
unsigned m_nEndPos;
};
#ifdef IFF_READ_ONLY
typedef ArchvIn Archive;
#endif // IFF_READ_ONLY
inline signed ArchvIn::GetSize() const
{
return m_nBytesRemaining;
}
inline void ArchvIn::Transfer(RGBTriple & n)
{
m_nBytesRemaining -= 3;
if (m_nBytesRemaining >= 0)
{
::MediaRead(m_pMedium, &n.r);
::MediaRead(m_pMedium, &n.g);
::MediaRead(m_pMedium, &n.b);
if (m_pMedium->m_fError) m_bError = true;
}
else m_bError = true;
}
inline void ArchvIn::Transfer(UBYTE & n)
{
m_nBytesRemaining -= 1;
if (m_nBytesRemaining >= 0)
{
::MediaRead(m_pMedium, &n);
if (m_pMedium->m_fError) m_bError = true;
}
else m_bError = true;
}
inline void ArchvIn::Transfer(BYTE & n)
{
m_nBytesRemaining -= 1;
if (m_nBytesRemaining >= 0)
{
::MediaRead(m_pMedium, &n);
if (m_pMedium->m_fError) m_bError = true;
}
else m_bError = true;
}
inline void ArchvIn::Transfer(UINT16 & n)
{
m_nBytesRemaining -= 2;
if (m_nBytesRemaining >= 0)
{
UBYTE byte;
::MediaRead(m_pMedium, &byte);
n = byte;
::MediaRead(m_pMedium, &byte);
n <<= 8;
n |= byte;
if (m_pMedium->m_fError) m_bError = true;
}
else m_bError = true;
}
inline void ArchvIn::Transfer(INT16 & n)
{
m_nBytesRemaining -= 2;
if (m_nBytesRemaining >= 0)
{
BYTE byte;
::MediaRead(m_pMedium, &byte);
n = byte;
::MediaRead(m_pMedium, &byte);
n <<= 8;
n |= byte;
if (m_pMedium->m_fError) m_bError = true;
}
else m_bError = true;
}
inline void ArchvIn::Transfer(UINT32 & n)
{
m_nBytesRemaining -= 4;
if (m_nBytesRemaining >= 0)
{
UBYTE byte;
::MediaRead(m_pMedium, &byte);
n = byte;
::MediaRead(m_pMedium, &byte);
n <<= 8;
n |= byte;
::MediaRead(m_pMedium, &byte);
n <<= 8;
n |= byte;
::MediaRead(m_pMedium, &byte);
n <<= 8;
n |= byte;
if (m_pMedium->m_fError) m_bError = true;
}
else m_bError = true;
}
inline void ArchvIn::Transfer(INT32 & n)
{
m_nBytesRemaining -= 4;
if (m_nBytesRemaining >= 0)
{
BYTE byte;
::MediaRead(m_pMedium, &byte);
n = byte;
::MediaRead(m_pMedium, &byte);
n <<= 8;
n |= byte;
::MediaRead(m_pMedium, &byte);
n <<= 8;
n |= byte;
::MediaRead(m_pMedium, &byte);
n <<= 8;
n |= byte;
if (m_pMedium->m_fError) m_bError = true;
}
else m_bError = true;
}
inline void ArchvIn::Transfer(UINT64 & n)
{
m_nBytesRemaining -= 8;
if (m_nBytesRemaining >= 0)
{
UBYTE byte;
::MediaRead(m_pMedium, &byte);
n = byte;
::MediaRead(m_pMedium, &byte);
n <<= 8;
n |= byte;
::MediaRead(m_pMedium, &byte);
n <<= 8;
n |= byte;
::MediaRead(m_pMedium, &byte);
n <<= 8;
n |= byte;
::MediaRead(m_pMedium, &byte);
n <<= 8;
n |= byte;
::MediaRead(m_pMedium, &byte);
n <<= 8;
n |= byte;
::MediaRead(m_pMedium, &byte);
n <<= 8;
n |= byte;
::MediaRead(m_pMedium, &byte);
n <<= 8;
n |= byte;
if (m_pMedium->m_fError) m_bError = true;
}
else m_bError = true;
}
inline void ArchvIn::Transfer(INT64 & n)
{
m_nBytesRemaining -= 8;
if (m_nBytesRemaining >= 0)
{
BYTE byte;
::MediaRead(m_pMedium, &byte);
n = byte;
::MediaRead(m_pMedium, &byte);
n <<= 8;
n |= byte;
::MediaRead(m_pMedium, &byte);
n <<= 8;
n |= byte;
::MediaRead(m_pMedium, &byte);
n <<= 8;
n |= byte;
::MediaRead(m_pMedium, &byte);
n <<= 8;
n |= byte;
::MediaRead(m_pMedium, &byte);
n <<= 8;
n |= byte;
::MediaRead(m_pMedium, &byte);
n <<= 8;
n |= byte;
::MediaRead(m_pMedium, &byte);
n <<= 8;
n |= byte;
if (m_pMedium->m_fError) m_bError = true;
}
else m_bError = true;
}
inline void ArchvIn::Transfer(ID & n)
{
m_nBytesRemaining -= 4;
if (m_nBytesRemaining >= 0)
{
// cast pointer to pointer to 4 byte data type to force 4 byte 'fast' read
::MediaRead(m_pMedium, reinterpret_cast<UINT32 *>(&n.m_sID[0]));
if (m_pMedium->m_fError) m_bError = true;
}
else m_bError = true;
}
inline void ArchvIn::TransferBlock(void * pData,unsigned nSize)
{
m_nBytesRemaining -= nSize;
if (m_nBytesRemaining >= 0)
{
m_pMedium->ReadBlock(pData,nSize);
if (m_pMedium->m_fError) m_bError = true;
}
else m_bError = true;
}
/*******************************/
/* Original File: iffSrlOb.hpp */
/*******************************/
class SerializableObj : public Unknown
{
public:
virtual void Serialize(Archive * pArchv) = 0;
};
/*******************************/
/* Original File: iffChunk.hpp */
/*******************************/
class Chunk : public SerializableObj
{
public:
ID m_idCk;
Chunk * GetProperty(ID idProp) const;
virtual bool IsUnknown() const { return false; }
void Write(Archive * pArchv);
static Chunk * Load(ID idParent, Archive * pArchv, ID idChunk = ID_ANY, bool bKnown = true);
static Chunk * DynCreate(ID idParent, ID idChunk);
static void Register(ID idParent, ID idChunk, Chunk * (* pfnCreate) () );
Composite const * GetParent() const { return m_pParent; }
protected:
Chunk() : m_pParent(NULL) {}
private:
Composite const * m_pParent; // mot reference counted
ChildNode const * m_pNode; // not reference counted either
friend class Composite;
};
#define IFF_IMPLEMENT_DYNCREATE(idParent,idChunk,tokenClassName) _IFF_IMPLEMENT_DYNCREATE_LINE_EX(idParent,idChunk,tokenClassName,__LINE__)
#define _IFF_IMPLEMENT_DYNCREATE_LINE_EX(idParent,idChunk,tokenClassName,nLine) _IFF_IMPLEMENT_DYNCREATE_LINE(idParent,idChunk,tokenClassName,nLine)
#define _IFF_IMPLEMENT_DYNCREATE_LINE(idParent,idChunk,tokenClassName,nLine) \
static IFF::Chunk * CreateClassObject ## tokenClassName ##_## nLine () { \
IFF::Chunk * pChunk = new IFF::tokenClassName; \
pChunk->m_idCk = idChunk; \
return pChunk; \
} \
class RegisterChunkClass ## tokenClassName ##_## nLine { \
public: RegisterChunkClass ## tokenClassName ##_## nLine () { \
IFF::Chunk::Register(idParent , idChunk , CreateClassObject ## tokenClassName ##_## nLine); \
} \
} rcc ## tokenClassName ##_## nLine;
/*******************************/
/* Original File: iffBlock.hpp */
/*******************************/
class ChildNode : public Unknown
{
public:
Chunk * GetChunk() const { return m_pChunk; }
private:
ChildNode * m_pNext;
ChildNode * m_pPrev;
Chunk * m_pChunk;
friend class Composite;
};
class Composite : public Chunk
{
public:
ID m_idData;
Composite() : m_pFirst(NULL), m_pLast(NULL) {}
virtual ~Composite();
ChildNode * GetFirstChild() const { return m_pFirst; }
ChildNode * GetFirstChild(ID idMatch) const;
ChildNode * GetLastChild() const { return m_pLast; }
ChildNode * GetLastChild(ID idMatch) const;
static ChildNode * GetNextChild(ChildNode const * pNode) { return pNode->m_pNext; }
static ChildNode * GetNextChild(ChildNode const * pNode, ID idMatch);
static ChildNode * GetPrevChild(ChildNode const * pNode) { return pNode->m_pPrev; }
static ChildNode * GetPrevChild(ChildNode const * pNode, ID idMatch);
Chunk * GetProperty(ChildNode const * pNode, ID idProp) const;
void DeleteChild(ChildNode * pNode);
void DeleteAllChildren();
ChildNode * InsertChildFirst(Chunk * pChunk);
ChildNode * InsertChildLast(Chunk * pChunk);
ChildNode * InsertChildAfter(ChildNode * pNode, Chunk * pChunk);
ChildNode * InsertChildBefore(ChildNode * pNode, Chunk * pChunk);
// pfnCallback should return true to continue the enumeration, false to finish
virtual bool EnumChildren(ID idData, ID idChunk, bool (* pfnCallback) (Chunk *, void *), void * pData) const;
protected:
virtual void Serialize(Archive * pArchv);
virtual Chunk * LoadChunk(Archive * pArchv) const;
virtual bool IsValidChildID(ID id) const;
private:
ChildNode * m_pFirst;
ChildNode * m_pLast;
};
class Form : public Composite
{
public:
Form() { m_idCk = "FORM"; }
protected:
virtual bool IsValidChildID(ID id) const;
};
class Cat : public Composite
{
public:
Cat() { m_idCk = "CAT "; }
virtual bool EnumChildren(ID idData, ID idChunk, bool (* pfnCallback) (Chunk *, void *), void * pData) const;
protected:
virtual bool IsValidChildID(ID id) const;
};
class List : public Composite
{
public:
List() { m_idCk = "LIST"; }
virtual bool EnumChildren(ID idData, ID idChunk, bool (* pfnCallback) (Chunk *, void *), void * pData) const;
protected:
virtual bool IsValidChildID(ID id) const;
};
class Prop : public Composite
{
public:
Prop() { m_idCk = "PROP"; }
protected:
virtual bool IsValidChildID(ID id) const;
};
/*******************************/
/* Original File: iffMscCk.hpp */
/*******************************/
class MiscChunk : public Chunk
{
public:
MiscChunk(ID id)
#ifndef IFF_READ_ONLY
: m_pData(NULL)
#endif // ! IFF_READ_ONLY
{
m_idCk = id;
}
virtual bool IsUnknown() const { return true; }
protected:
virtual void Serialize(Archive * pArchv);
#ifndef IFF_READ_ONLY
virtual ~MiscChunk();
#endif // ! IFF_READ_ONLY
private:
#ifndef IFF_READ_ONLY
BYTE * m_pData;
unsigned m_nSize;
#endif // ! IFF_READ_ONLY
};
/******************************/
/* Original File: iffFile.hpp */
/******************************/
class GenericFile : public SerializableObj
{
public:
#ifndef IFF_READ_ONLY
GenericFile() : m_pszFileName(NULL) {}
virtual ~GenericFile() { if (m_pszFileName) delete[] m_pszFileName; }
#endif
bool Load(TCHAR const * pszFileName);
bool Load(::MediaMedium * pMedium);
#ifndef IFF_READ_ONLY
bool Write(TCHAR const * pszFileName = NULL);
bool Write(::MediaMedium * pMedium);
#endif // ! IFF_READ_ONLY
private:
#ifndef IFF_READ_ONLY
TCHAR * m_pszFileName;
#endif // ! IFF_READ_ONLY
};
class File : public GenericFile
{
public:
virtual ~File();
File() : m_pContents(NULL) {}
Composite * GetContents() const;
void SetContents(Composite * pContents);
protected:
virtual void Serialize(Archive * pArchv);
private:
ID m_idType;
Composite * m_pContents;
};
inline Composite * File::GetContents() const
{
return m_pContents;
}
inline void File::SetContents(Composite * pContents)
{
if (m_pContents) m_pContents->Release();
if (pContents)
{
pContents->AddRef();
m_idType = pContents->m_idCk;
}
m_pContents = pContents;
}
// Have a static object of this in each file:
// It will detect if some files are compiled with
// IFF_READ_ONLY defined differently to each other
static class ConsistencyCheck
{
public: inline ConsistencyCheck()
{
#ifdef IFF_READ_ONLY
static bool bReadOnly = true;
if (!bReadOnly)
#else
static bool bReadOnly = false;
if (bReadOnly)
#endif
{
DisplayMessage
(
#ifdef NDEBUG
TEXT("Error"),
TEXT("IFF_READ_ONLY definition not consistent")
#else
TEXT("IFF Compile Option Error"),
TEXT("Some files which #include \"iff.hpp\"\n")
TEXT("have the macro IFF_READ_ONLY defined\n")
TEXT("and some don't.\n\n")
TEXT("Please ensure this is consistent and recompile.")
#endif
);
exit(-45);
}
}
}
consistencyCheck;
} // namespace IFF
#endif // ! _INCLUDED_IFF_HPP_

327
src/win95/iff_ilbm.cpp Normal file
View file

@ -0,0 +1,327 @@
#include "advwin32.h"
#include "iff_ILBM.hpp"
IFF_IMPLEMENT_DYNCREATE("ILBM","BMHD",IlbmBmhdChunk)
IFF_IMPLEMENT_DYNCREATE("ILBM","CMAP",IlbmCmapChunk)
IFF_IMPLEMENT_DYNCREATE("ILBM","BODY",IlbmBodyChunk)
IFF_IMPLEMENT_DYNCREATE("ILBM","GRAB",IlbmGrabChunk)
namespace IFF
{
void IlbmBmhdChunk::Serialize(Archive * pArchv)
{
pArchv->Transfer(width);
pArchv->Transfer(height);
pArchv->Transfer(xTopLeft);
pArchv->Transfer(yTopLeft);
pArchv->Transfer(nBitPlanes);
pArchv->Transfer(eMasking);
pArchv->Transfer(eCompression);
pArchv->Transfer(flags);
pArchv->Transfer(iTranspCol);
pArchv->Transfer(xAspectRatio);
pArchv->Transfer(yAspectRatio);
pArchv->Transfer(xMax);
pArchv->Transfer(yMax);
}
void IlbmCmapChunk::Serialize(Archive * pArchv)
{
if (pArchv->m_bIsLoading)
{
nEntries = pArchv->GetSize()/3;
if (pTable) delete[] pTable;
pTable = new RGBTriple [nEntries];
}
for (unsigned i=0; i<nEntries; ++i)
pArchv->Transfer(pTable[i]);
}
IlbmCmapChunk::~IlbmCmapChunk()
{
if (pTable) delete[] pTable;
}
void IlbmBodyChunk::Serialize(Archive * pArchv)
{
if (pArchv->m_bIsLoading)
{
nSize = pArchv->GetSize();
if (pData) delete[] pData;
pData = new UBYTE [nSize];
}
pArchv->TransferBlock(pData,nSize);
}
bool IlbmBodyChunk::GetHeaderInfo() const
{
Chunk * pHdr = GetProperty("BMHD");
if (!pHdr)
{
return false;
}
nWidth = static_cast<IlbmBmhdChunk *>(pHdr)->width;
eCompression = static_cast<IlbmBmhdChunk *>(pHdr)->eCompression;
nBitPlanes = static_cast<IlbmBmhdChunk *>(pHdr)->nBitPlanes;
return true;
}
#ifndef IFF_READ_ONLY
bool IlbmBodyChunk::BeginEncode()
{
if (!GetHeaderInfo())
{
return false;
}
pEncodeDst = new DataBlock;
pEncodeSrc = new UBYTE [(nWidth+7)/8];
nSizeNonCprss = 0;
nSizeCprss = 0;
return true;
}
// The uninitialised part of byte is shifted out.
#ifdef _MSC_VER
#pragma warning(disable: 4701)
#endif
bool IlbmBodyChunk::EncodeNextRow(unsigned const * pRow)
{
if (!pEncodeDst) return false;
for (unsigned b=0; b<nBitPlanes; ++b)
{
UBYTE * pBuf = pEncodeSrc;
unsigned byte;
for (unsigned x=0; x<nWidth; ++x)
{
byte <<= 1;
byte |= pRow[x]>>b & 1;
if (7==(x&7)) *pBuf++ = static_cast<UBYTE>(byte);
}
if (nWidth & 7)
{
byte <<= 8-(nWidth & 7);
*pBuf = static_cast<UBYTE>(byte);
}
if (eCompression)
{
nSizeNonCprss += (nWidth+7)/8;
UBYTE const * pBuf = pEncodeSrc;
unsigned i=(nWidth+7)/8;
while (i)
{
if (1==i)
{
pEncodeDst->Append(0);
pEncodeDst->Append(*pBuf);
nSizeCprss += 2;
i=0;
}
else if (i>1)
{
if (pBuf[0]==pBuf[1])
{
unsigned j=2;
while (j<i && j<0x80 && pBuf[j-1]==pBuf[j])
++j;
pEncodeDst->Append(static_cast<UBYTE>(0x101-j));
pEncodeDst->Append(*pBuf);
pBuf += j;
i -= j;
nSizeCprss += 2;
}
else
{
unsigned j=2;
while (j<i && j<0x80 && (pBuf[j]!=pBuf[j-1] || pBuf[j-1]!=pBuf[j-2]))
++j;
if (j<i && pBuf[j]==pBuf[j-1] && pBuf[j-1]==pBuf[j-2])
j-=2;
pEncodeDst->Append(static_cast<UBYTE>(j-1));
pEncodeDst->Append(pBuf,j);
pBuf += j;
i -= j;
nSizeCprss += j+1;
}
}
}
}
else
{
pEncodeDst->Append(pEncodeSrc,(nWidth+7)/8);
}
}
return true;
}
#ifdef _MSC_VER
#pragma warning(default: 4701)
#endif
bool IlbmBodyChunk::EndEncode()
{
if (!pEncodeDst) return false;
if (pData) delete[] pData;
nSize = pEncodeDst->GetDataSize();
pData = new UBYTE[nSize];
memcpy(pData,pEncodeDst->GetDataPtr(),nSize);
delete pEncodeDst;
delete[] pEncodeSrc;
pEncodeDst = NULL;
pEncodeSrc = NULL;
return true;
}
#endif
bool IlbmBodyChunk::BeginDecode() const
{
if (pDecodeDst) delete[] pDecodeDst;
if (!pData || !GetHeaderInfo())
{
pDecodeSrc = NULL;
pDecodeDst = NULL;
return false;
}
pDecodeSrc = pData;
nRemaining = nSize;
pDecodeDst = new unsigned [nWidth];
return pData != NULL;
}
// The uninitialised part of pDecodeDst is shifted out.
#ifdef _MSC_VER
#pragma warning(disable: 4701)
#endif
unsigned const * IlbmBodyChunk::DecodeNextRow() const
{
if (!pDecodeSrc || !pDecodeDst) return NULL;
for (unsigned x=0; x<nWidth; ++x)
pDecodeDst[x]=0;
if (eCompression)
{
unsigned repcnt = 0;
unsigned rawcnt = 0;
for (unsigned b=0; b<nBitPlanes; ++b)
{
unsigned byte;
for (unsigned x=0; x<nWidth; ++x)
{
if (!(x&7))
{
if (!nRemaining) return NULL;
REPEAT_SKIP:
byte = *pDecodeSrc;
if (rawcnt)
{
--rawcnt;
++pDecodeSrc;
--nRemaining;
}
else if (repcnt)
{
--repcnt;
if (!repcnt)
{
++pDecodeSrc;
--nRemaining;
}
}
else // byte is control byte
{
++pDecodeSrc;
--nRemaining;
if (!nRemaining) return NULL;
if (byte<0x80)
{
rawcnt = byte;
byte = *pDecodeSrc++;
--nRemaining;
}
else if (byte>0x80)
{
repcnt = 0x100 - byte;
byte = *pDecodeSrc;
}
else goto REPEAT_SKIP;
}
}
pDecodeDst[x] |= (byte>>7 & 1)<<b;
byte <<= 1;
}
}
}
else
{
for (unsigned b=0; b<nBitPlanes; ++b)
{
unsigned byte;
for (unsigned x=0; x<nWidth; ++x)
{
if (!(x&7))
{
if (!nRemaining) return NULL;
byte = *pDecodeSrc++;
--nRemaining;
}
pDecodeDst[x] |= (byte>>7 & 1)<<b;
byte <<= 1;
}
}
}
return pDecodeDst;
}
#ifdef _MSC_VER
#pragma warning(default: 4701)
#endif
IlbmBodyChunk::~IlbmBodyChunk()
{
if (pData) delete[] pData;
if (pDecodeDst) delete[] pDecodeDst;
#ifndef IFF_READ_ONLY
if (pEncodeDst) delete pEncodeDst;
if (pEncodeSrc) delete[] pEncodeSrc;
#endif
}
void IlbmGrabChunk::Serialize(Archive * pArchv)
{
pArchv->Transfer(xHotSpot);
pArchv->Transfer(yHotSpot);
}
}

164
src/win95/iff_ilbm.hpp Normal file
View file

@ -0,0 +1,164 @@
#ifndef _INCLUDED_IFF_ILBM_HPP_
#define _INCLUDED_IFF_ILBM_HPP_
#include "iff.hpp"
namespace IFF
{
class IlbmBmhdChunk : public Chunk
{
public:
UINT16 width;
UINT16 height;
UINT16 xTopLeft;
UINT16 yTopLeft;
UBYTE nBitPlanes;
enum
{
MASK_NONE = 0,
MASK_HASMASK = 1,
MASK_TRANSPARENTCOL = 2,
MASK_LASSO = 3
};
UBYTE eMasking;
enum
{
COMPRESS_NONE = 0,
COMPRESS_RUNLENGTH = 1,
COMPRESS_S3TC =2 //will have s3tc chunk instead of body chunk
};
UBYTE eCompression;
UBYTE flags;
UINT16 iTranspCol;
UBYTE xAspectRatio;
UBYTE yAspectRatio;
UINT16 xMax;
UINT16 yMax;
IlbmBmhdChunk() { m_idCk = "BMHD"; }
protected:
virtual void Serialize(Archive * pArchv);
};
class IlbmCmapChunk : public Chunk
{
public:
unsigned nEntries;
RGBTriple * pTable;
void CreateNew(unsigned nSize);
IlbmCmapChunk() : pTable(NULL) { m_idCk = "CMAP"; }
virtual ~IlbmCmapChunk();
protected:
virtual void Serialize(Archive * pArchv);
};
inline void IlbmCmapChunk::CreateNew(unsigned nSize)
{
if (pTable) delete[] pTable;
pTable = new RGBTriple [nSize];
nEntries = nSize;
}
class IlbmBodyChunk : public Chunk
{
public:
IlbmBodyChunk() : pData(NULL), pDecodeDst(NULL)
#ifndef IFF_READ_ONLY
, pEncodeDst(NULL), pEncodeSrc(NULL)
#endif
{ m_idCk = "BODY"; }
virtual ~IlbmBodyChunk();
#ifndef IFF_READ_ONLY
bool BeginEncode();
bool EncodeFirstRow(unsigned const * pRow);
bool EncodeNextRow(unsigned const * pRow);
bool EndEncode();
float GetCompressionRatio() const;
#endif
bool BeginDecode() const;
unsigned const * DecodeFirstRow() const;
unsigned const * DecodeNextRow() const;
bool EndDecode() const;
protected:
virtual void Serialize(Archive * pArchv);
virtual bool GetHeaderInfo() const; // fills in these three data members
mutable unsigned nWidth;
mutable unsigned eCompression;
mutable unsigned nBitPlanes;
private:
unsigned nSize;
UBYTE * pData;
mutable UBYTE const * pDecodeSrc;
mutable unsigned nRemaining;
mutable unsigned * pDecodeDst;
#ifndef IFF_READ_ONLY
DataBlock * pEncodeDst;
UBYTE * pEncodeSrc;
unsigned nSizeNonCprss;
unsigned nSizeCprss;
#endif
};
#ifndef IFF_READ_ONLY
inline bool IlbmBodyChunk::EncodeFirstRow(unsigned const * pRow)
{
if (BeginEncode())
return EncodeNextRow(pRow);
else
return false;
}
inline float IlbmBodyChunk::GetCompressionRatio() const
{
if (!nSizeNonCprss) return 0.0F;
return (static_cast<float>(nSizeNonCprss)-static_cast<float>(nSizeCprss))/static_cast<float>(nSizeNonCprss);
}
#endif
inline unsigned const * IlbmBodyChunk::DecodeFirstRow() const
{
if (BeginDecode())
return DecodeNextRow();
else
return NULL;
}
inline bool IlbmBodyChunk::EndDecode() const
{
if (pDecodeDst)
{
delete[] pDecodeDst;
pDecodeDst = NULL;
return true;
}
else return false;
}
class IlbmGrabChunk : public Chunk
{
public:
UINT16 xHotSpot;
UINT16 yHotSpot;
IlbmGrabChunk() { m_idCk = "GRAB"; }
protected:
virtual void Serialize(Archive * pArchv);
};
}
#endif // ! _INCLUDED_IFF_ILBM_HPP_

87
src/win95/ilbm_ext.cpp Normal file
View file

@ -0,0 +1,87 @@
#include "ILBM_ext.hpp"
IFF_IMPLEMENT_DYNCREATE("ILBM","TRAN",IlbmTranChunk)
IFF_IMPLEMENT_DYNCREATE("ILBM","ALPH",IlbmAlphChunk)
IFF_IMPLEMENT_DYNCREATE("MIPM","CONT",MipmContChunk)
IFF_IMPLEMENT_DYNCREATE("ILBM","S3TC",IlbmS3tcChunk)
IFF_IMPLEMENT_DYNCREATE("MIPM","FLAG",MipmFlagChunk)
namespace IFF
{
void IlbmTranChunk::Serialize(Archive * pArchv)
{
pArchv->Transfer(eTransType);
pArchv->Transfer(xPos);
pArchv->Transfer(yPos);
pArchv->Transfer(rgb);
}
void IlbmAlphChunk::Serialize(Archive * pArchv)
{
pArchv->Transfer(width);
pArchv->Transfer(height);
pArchv->Transfer(nBitPlanes);
pArchv->Transfer(eCompression);
IlbmBodyChunk::Serialize(pArchv);
}
bool IlbmAlphChunk::GetHeaderInfo() const
{
IlbmBodyChunk::nWidth = width;
IlbmBodyChunk::eCompression = eCompression;
IlbmBodyChunk::nBitPlanes = nBitPlanes;
return true;
}
void MipmContChunk::Serialize(Archive * pArchv)
{
pArchv->Transfer(nMipMaps);
pArchv->Transfer(eFilter);
}
void MipmFlagChunk::Serialize(Archive * pArchv)
{
pArchv->Transfer(flags);
}
IlbmS3tcChunk::IlbmS3tcChunk()
{
m_idCk = "S3TC";
pData = NULL;
dataSize = 0;
}
IlbmS3tcChunk::~IlbmS3tcChunk()
{
if(pData) delete [] pData;
pData = NULL;
}
void IlbmS3tcChunk::Serialize(Archive * pArchv)
{
pArchv->Transfer(flags);
pArchv->Transfer(fourCC);
pArchv->Transfer(redWeight);
pArchv->Transfer(blueWeight);
pArchv->Transfer(greenWeight);
pArchv->Transfer(width);
pArchv->Transfer(height);
pArchv->Transfer(dataSize);
if (pArchv->m_bIsLoading)
{
if(pData) delete [] pData;
pData = new UBYTE[dataSize];
}
UBYTE *pDataPos = pData;
for(unsigned i=0;i<dataSize;i++)
{
pArchv->Transfer(*pDataPos++);
}
}
}

117
src/win95/ilbm_ext.hpp Normal file
View file

@ -0,0 +1,117 @@
#ifndef _INCLUDED_ILBM_EXT_HPP_
#define _INCLUDED_ILBM_EXT_HPP_
#include "iff.hpp"
#include "iff_ILBM.hpp"
namespace IFF
{
class IlbmTranChunk : public Chunk
{
public:
enum
{
TRANS_NONE = 0,
TRANS_TOPLEFT = 1,
TRANS_BOTTOMLEFT = 2,
TRANS_TOPRIGHT = 3,
TRANS_BOTTOMRIGHT = 4,
TRANS_XY = 5,
TRANS_RGB = 6
};
UBYTE eTransType;
UINT16 xPos;
UINT16 yPos;
RGBTriple rgb;
IlbmTranChunk() { m_idCk = "TRAN"; }
protected:
virtual void Serialize(Archive * pArchv);
};
class IlbmAlphChunk : public IlbmBodyChunk // uses same encoding methodology
{
public:
UINT16 width;
UINT16 height;
UBYTE nBitPlanes;
UBYTE eCompression;
IlbmAlphChunk()
{ m_idCk = "ALPH"; }
protected:
virtual void Serialize(Archive * pArchv);
virtual bool GetHeaderInfo() const;
};
class IlbmS3tcChunk : public Chunk
{
public:
IlbmS3tcChunk();
virtual ~IlbmS3tcChunk();
UINT32 flags; // none at the moment
UINT32 fourCC; //the fourcc code 'DXT1' - 'DXT5'
UINT16 redWeight; //weighting values used in compression
UINT16 blueWeight;
UINT16 greenWeight;
UINT16 width;
UINT16 height;
UINT32 dataSize;
UBYTE* pData; //the compressed texture itself
protected:
virtual void Serialize(Archive * pArchv);
};
class MipmContChunk : public Chunk
{
public:
enum
{
FILTER_DEFAULT = 0,
FILTER_BOX = 1,
FILTER_TRIANGLE = 2,
FILTER_BELL = 3,
FILTER_BSPLINE = 4,
FILTER_LANCZOS3 = 5,
FILTER_MITCHELL = 6
};
UBYTE nMipMaps;
UBYTE eFilter;
MipmContChunk()
{ m_idCk = "CONT"; }
protected:
virtual void Serialize(Archive * pArchv);
};
class MipmFlagChunk : public Chunk
{
public:
enum
{
FLAG_MANUAL_MIPS = 0x00000001,//some of the mip maps have been set by hand
};
UINT32 flags;
MipmFlagChunk()
{ m_idCk = "FLAG"; flags = 0;}
protected:
virtual void Serialize(Archive * pArchv);
};
}
#endif

1246
src/win95/inline.h Normal file

File diff suppressed because it is too large Load diff

1970
src/win95/io.c Normal file

File diff suppressed because it is too large Load diff

306
src/win95/item.c Normal file
View file

@ -0,0 +1,306 @@
#include "3dc.h"
#include "module.h"
#include "inline.h"
#include "krender.h" /* KJL 11:37:53 12/05/96 - new scandraws patch */
/* KJL 15:02:50 05/14/97 - new max lighting intensity */
#define MAX_INTENSITY (65536*4-1)
#if StandardShapeLanguage
#define UseLocalAssert Yes
#include "ourasert.h"
/*
The outputclockwise compile option has been
maintained in case anyone wants to use the existing
triangle array code with counterclockwise ordering.
In the case of Win95, we might want to this if we can ever
persuade the Direct3D rasterisation module to come up
with CULL_CCW set. Note that outputtriangles has now been purged
from the system.
*/
#define outputclockwise Yes
#define use_div_fixed Yes
#define trip_debugger No
#if trip_debugger
int testa = 0;
int testb = 100;
int testc = 0;
#endif
/*
To make scan draws work backwards as
well as forwards, i.e. to cope with
items that would be backface culled
without the no cull flag set, as in racing
game TLOs.
This should now work for all polygon types.
*/
#define ReverseDraws Yes
/*
To optimise scan draws with local variables
explicitly braced to improve compiler
optimisation.
NOTE THIS IS -->ONLY<-- IMPLEMENTED FOR
VIDEOMODETYPE_8, 2DTEXTURE, 3DTEXTURE (LINEAR)
AND 3DTEXTURE (LINEAR_S) AT PRESENT.
AND NOT ALL THE OPTIONS INSIDE THOSE!!!
NOTE ALSO THAT THIS APPEARS TO PRODUCE BAD CODE
WITH WATCOM 10.0 AND -oeitlr, BUT WE HOPE IT WILL
WORK WITH WATCOM 10.6
-->CRASHES, AS IT HAPPENS!!!<--
*/
/*
Prototypes
*/
/*
externs for commonly used global variables and arrays
*/
extern int VideoModeType;
extern int VideoModeTypeScreen;
extern int ScanDrawMode;
extern int **ShadingTableArray;
extern unsigned char **PaletteShadingTableArray;
extern VIEWDESCRIPTORBLOCK *Global_VDB_Ptr;
extern unsigned char *ScreenBuffer;
extern IMAGEHEADER *ImageHeaderPtrs[MaxImages];
extern SCREENDESCRIPTORBLOCK ScreenDescriptorBlock;
extern long BackBufferPitch;
/* For multiple execute buffers */
extern int NumVertices;
#endif /* for support3dtextures */
/*
Global Variables
*/
// int *ItemPointers[maxpolyptrs];
// int ItemData[maxpolys * avgpolysize];
int **NextFreeItemPtr;
int *NextFreeItemData;
int NumFreeItemPtrs;
int NumFreeItemData;
int ItemCount; /* Instead of a Terminator */
POLYHEADER *global_pheader;
int MIP_Index;
/*
Global Variables For Scan Convertors
*/
int ScanData[maxpolys*maxscansize];
int *NextFreeScanData;
int NumFreeScanData;
int NumScans;
int NumPolyPts;
/*
Item Data Structures.
Buffer Initialisation and Allocation Functions.
*/
/*
John and Neal's code
Note this is only experimental, for the interface engine,
and therefore does not go through the standard scan draw
function array!!! Also, it only works in VideoModeType_8!!!
USE AT YOUR PERIL!!!!
*/
void Draw_Line_VMType_8(VECTOR2D* LineStart, VECTOR2D* LineEnd, int LineColour)
{
int gosa, tame, hani, dire;
int w, x, y;
int x1, y1, x2, y2;
unsigned char *sbufferptr;
unsigned char colour = LineColour;
x1 = LineStart->vx;
y1 = LineStart->vy;
x2 = LineEnd->vx;
y2 = LineEnd->vy;
x1=max(x1,Global_VDB_Ptr->VDB_ClipLeft);
x1=min(x1,Global_VDB_Ptr->VDB_ClipRight-1);
x2=max(x2,Global_VDB_Ptr->VDB_ClipLeft);
x2=min(x2,Global_VDB_Ptr->VDB_ClipRight-1);
y1=max(y1,Global_VDB_Ptr->VDB_ClipUp);
y1=min(y1,Global_VDB_Ptr->VDB_ClipDown-1);
y2=max(y2,Global_VDB_Ptr->VDB_ClipUp);
y2=min(y2,Global_VDB_Ptr->VDB_ClipDown-1);
if( abs( x2 - x1 ) < abs( y2 - y1 ) ) {
if( y2 < y1 ) {
w = y1;
y1 = y2;
y2 = w;
w = x1;
x1 = x2;
x2 = w;
}
dire = x1 < x2 ? 1 : -1;
gosa = abs( x2 - x1 );
hani = y2 - y1;
tame = hani / 2;
x = x1;
for( y = y1; y <= y2; y++ ) {
sbufferptr =
ScreenBuffer +
(y * BackBufferPitch) + x;
*sbufferptr = colour;
tame += gosa;
if( tame > hani ) {
x += dire;
tame -= hani;
}
}
} else {
if( x2 < x1 ) {
w = x1;
x1 = x2;
x2 = w;
w = y1;
y1 = y2;
y2 = w;
}
dire = y1 < y2 ? 1 : -1;
gosa = abs( y2 - y1 );
hani = x2 - x1;
tame = hani / 2;
y = y1;
for( x = x1; x <= x2; x++ ) {
sbufferptr =
ScreenBuffer +
(y * BackBufferPitch) + x;
*sbufferptr = colour;
tame += gosa;
if( tame > hani ) {
y += dire;
tame -= hani;
}
}
}
}
/*
Scan Convert and Draw I_GouraudPolygon
*/
void Draw_Item_GouraudPolygon(int *itemptr)
{
if (ScanDrawMode == ScanDrawDirectDraw)
{
KDraw_Item_GouraudPolygon(itemptr);
}
}
void Draw_Item_2dTexturePolygon(int *itemptr)
{
if (ScanDrawMode == ScanDrawDirectDraw)
{
KDraw_Item_2dTexturePolygon(itemptr);
}
}
void Draw_Item_Gouraud2dTexturePolygon(int *itemptr)
{
if (ScanDrawMode == ScanDrawDirectDraw)
{
KDraw_Item_Gouraud2dTexturePolygon(itemptr);
}
}
void Draw_Item_Gouraud3dTexturePolygon(int *itemptr)
{
if (ScanDrawMode == ScanDrawDirectDraw)
{
KDraw_Item_Gouraud3dTexturePolygon(itemptr);
}
}
void Draw_Item_ZB_Gouraud3dTexturePolygon(int *itemptr)
{
}
void Draw_Item_ZB_GouraudPolygon(int *itemptr)
{
}
void Draw_Item_ZB_2dTexturePolygon(int *itemptr)
{
}
void Draw_Item_ZB_Gouraud2dTexturePolygon(int *itemptr)
{
}
void Draw_Item_ZB_3dTexturedPolygon(int *itemptr)
{
}

2830
src/win95/krender.c Normal file

File diff suppressed because it is too large Load diff

55
src/win95/krender.h Normal file
View file

@ -0,0 +1,55 @@
/* If this define is set to a non-zero value then the new scandraws will be used */
#define KRENDER_ON 1
/* prototypes of the replacement scandraw functions */
extern void KR_ScanDraw_Item_2dTexturePolygon_VideoModeType_8(int *itemptr);
extern void KR_ScanDraw_Item_Gouraud2dTexturePolygon_VideoModeType_8(int *itemptr);
extern void KR_ScanDraw_Item_Gouraud3dTexturePolygon_Linear_S_VideoModeType_8(int *itemptr);
extern void MotionTrackerRotateBlit(void);
extern void MotionTrackerRotateBlit8(void);
/*KJL*****************************************************
* Palette fading; a value of 65536 corresponds to normal *
* palette, 0 is completely other (eg. all white). *
*****************************************************KJL*/
extern void SetPaletteFadeLevel(int fadeLevel);
extern void FadeBetweenPalettes(unsigned char *palPtr, int fadeLevel);
extern void FadePaletteToWhite(unsigned char *palPtr,int fadeLevel);
/*KJL*********************************************
* Fill the screen with black & flip then repeat. *
*********************************************KJL*/
extern void BlankScreen(void);
/* KJL 16:06:24 04/04/97 - To choose between laced and full screen modes */
extern int KRenderDrawMode;
extern void KDraw_Item_GouraudPolygon(int *itemptr);
extern void KDraw_Item_2dTexturePolygon(int *itemptr);
extern void KDraw_Item_Gouraud2dTexturePolygon(int *itemptr);
extern void KDraw_Item_Gouraud3dTexturePolygon(int *itemptr);
extern void MakeViewingWindowSmaller(void);
extern void MakeViewingWindowLarger(void);
/* routines to draw a star filled sky */
extern void CreateStarArray(void);
extern void DrawStarfilledSky(void);

28
src/win95/list_tem.cpp Normal file
View file

@ -0,0 +1,28 @@
#ifdef NDEBUG
;
#else
char const * list_fail_get_data_from_sentinel = "%s: Tried to get data from sentinel\n";
char const * list_fail_add_entry_after = "%s: Tried to add after a nonexistent List entry\n";
char const * list_fail_add_entry_before = "%s: Tried to add before a nonexistent List entry\n";
char const * list_fail_delete_entry = "%s: Tried to delete a nonexistent List entry\n";
char const * list_fail_delete_entry_by_pointer = "%s: Tried to delete-by-pointer the sentinel of a list.\n";
char const * list_fail_alter_entry = "%s: Tried to alter a nonexistent List entry\n";
char const * list_fail_next_entry_nonexist = "%s: Tried to get entry after nonexistent entry.";
char const * list_fail_next_entry_sentinel = "%s: Tried to get next entry, which is sentinel.";
char const * list_fail_prev_entry_nonexist = "%s: Tried to get entry before nonexistent entry";
char const * list_fail_prev_entry_sentinel = "%s: Tried to get previous entry, which is sentinel.";
char const * list_fail_last_entry = "%s: Tried to get last entry from a 0-length list.\n.";
char const * list_fail_first_entry = "%s: Tried to get first entry from a 0-length list.\n.";
char const * list_fail_similar_entry = "%s: Tried to get entry similar to nonexistent entry";
char const * list_fail_delete_last_entry = "%s: Tried to delete last element from an empty List.\n";
char const * list_fail_delete_first_entry = "%s: Tried to delete first element from an empty List.\n";
char const * list_fail_operator = "%s: Tried to get entry %d from %d-entry list.\n";
char const * lit_fail_next = "%s: Tried to take an Iterator past the sentinel of a List.\n";
char const * lit_fail_operator = "%s: Tried to take contents of sentinel of List\n";
char const * lit_fail_delete_current = "%s: Tried to delete sentinel of List\n";
char const * lit_fail_change_current = "%s: Tried to change contents of sentinel of List\n";
#endif

871
src/win95/list_tem.hpp Normal file
View file

@ -0,0 +1,871 @@
// Doubly linked list class.
//
// Inserts new entries at the *end* of the list -- so add_entry()
// followed by delete_last_entry() will do nothing.
//
//
// Usage:
//
// List<Thing> l; creates an empty list.
// Thing a; List<Thing> l(a); creates a list containing a.
//
// void l.add_entry(Thing a); adds an entry.
// void l.delete_entry(Thing a); removes `a' from the list if it's there,
// aborts if it's not.
// void l.delete_{first,last}_entry deletes the first/last entry.
// Thing l.{first,last}_entry returns the first/last entry.
// bool l.contains(Thing a) is a in the list?
#ifndef list_template_hpp
#define list_template_hpp
#pragma once
#include <stdio.h>
#ifdef _CPPRTTI // run time type information available
#include <typeinfo.h>
#define LIST_TEM_TYPEID_THIS typeid(*this).name()
#else
#define LIST_TEM_TYPEID_THIS "?"
#endif
#if defined(engine)
// Not all preprocessors do lazy evaluation. DW
#if engine
#include "mem3dc.h"
#endif
#endif
#ifdef NDEBUG
#define fail if (0)
#define list_fail_get_data_from_sentinel NULL
#define list_fail_add_entry_after NULL
#define list_fail_add_entry_before NULL
#define list_fail_delete_entry NULL
#define list_fail_delete_entry_by_pointer NULL
#define list_fail_alter_entry NULL
#define list_fail_next_entry_nonexist NULL
#define list_fail_next_entry_sentinel NULL
#define list_fail_prev_entry_nonexist NULL
#define list_fail_prev_entry_sentinel NULL
#define list_fail_last_entry NULL
#define list_fail_first_entry NULL
#define list_fail_similar_entry NULL
#define list_fail_delete_last_entry NULL
#define list_fail_delete_first_entry NULL
#define list_fail_operator NULL
#define lit_fail_next NULL
#define lit_fail_operator NULL
#define lit_fail_delete_current NULL
#define lit_fail_change_current NULL
#else
#include "fail.h"
extern char const * list_fail_get_data_from_sentinel;
extern char const * list_fail_add_entry_after;
extern char const * list_fail_add_entry_before;
extern char const * list_fail_delete_entry;
extern char const * list_fail_delete_entry_by_pointer;
extern char const * list_fail_alter_entry;
extern char const * list_fail_next_entry_nonexist;
extern char const * list_fail_next_entry_sentinel;
extern char const * list_fail_prev_entry_nonexist;
extern char const * list_fail_prev_entry_sentinel;
extern char const * list_fail_last_entry;
extern char const * list_fail_first_entry;
extern char const * list_fail_similar_entry;
extern char const * list_fail_delete_last_entry;
extern char const * list_fail_delete_first_entry;
extern char const * list_fail_operator;
extern char const * lit_fail_next;
extern char const * lit_fail_operator;
extern char const * lit_fail_delete_current;
extern char const * lit_fail_change_current;
#endif
// The first declaration of these class templates was previously as friends
// of List. However, Visual C++ 5 can't parse them unless we give a
// forward declaration first - I think this is a compiler bug - Garry.
template<class T>
class List_Iterator_Forward;
template<class T>
class ConstList_Iterator_Forward;
template<class T>
class List_Iterator_Backward;
template<class T>
class ConstList_Iterator_Backward;
template<class T>
class List_Iterator_Loop;
template<class T>
struct List_Member;
template<class T>
struct List_Member_Base
{
union
{
List_Member_Base<T> *prev;
#ifndef __WATCOMC__
List_Member<T> *prev_debug; // encourage the debugger to display the list members data
#endif // hopefully casting from base to derived class would not
// cause the actual value of the ptr to change, so the debugger
// will display the information correctly, and this union
// won't cause any kind of performance hit
//watcom doesn't appear to like this, unfortunately.
};
union
{
List_Member_Base<T> *next;
#ifndef __WATCOMC__
List_Member<T> *next_debug;
#endif
};
virtual ~List_Member_Base() {}
};
template<class T>
struct List_Member : public List_Member_Base<T>
{
T data;
List_Member<T>(const T& n) : data(n) {}
};
template<class T>
class List {
private:
List_Member_Base<T> *sentinel;
int n_entries;
mutable T **entry_pointers;
mutable bool calculated_indices;
T& data(List_Member_Base<T>* e) const
{
if (e == sentinel)
fail(list_fail_get_data_from_sentinel,LIST_TEM_TYPEID_THIS);
return ((List_Member<T>*)e)->data;
}
public:
List() {
sentinel = new List_Member_Base<T>;
sentinel->next = sentinel;
sentinel->prev = sentinel;
n_entries = 0;
entry_pointers = 0;
calculated_indices = false;
}
List(const T& n) {
sentinel = new List_Member_Base<T>;
sentinel->next = sentinel;
sentinel->prev = sentinel;
n_entries = 0;
entry_pointers = 0;
calculated_indices = false;
add_entry(n);
}
List(const List<T>& l) {
sentinel = new List_Member_Base<T>;
sentinel->next = sentinel;
sentinel->prev = sentinel;
n_entries = 0;
entry_pointers = 0;
calculated_indices = false;
List_Member_Base<T>* m = l.sentinel->next;
while (m != l.sentinel) {
add_entry(data(m));
m = m->next;
}
}
List<T>& operator= (const List<T>& l) {
while(n_entries != 0) delete_last_entry();
if (entry_pointers != 0)
delete[] entry_pointers;
List_Member_Base<T>* m = l.sentinel->next;
while (m != l.sentinel) {
add_entry(data(m));
m = m->next;
}
calculated_indices = false;
entry_pointers = 0;
return *this;
}
~List() {
while (n_entries != 0) delete_last_entry();
delete sentinel;
delete[] entry_pointers;
}
void add_entry(const T& n) {
add_entry_end(n);
}
void add_entry_end(const T& n) {
List_Member<T> *e = new List_Member<T>(n);
e->next = sentinel;
e->prev = sentinel->prev;
sentinel->prev->next = e;
sentinel->prev = e;
n_entries++;
cleanup();
}
void add_entry_start(const T& n) {
List_Member<T> *e = new List_Member<T>(n);
e->prev = sentinel;
e->next = sentinel->next;
sentinel->next->prev = e;
sentinel->next = e;
n_entries++;
cleanup();
}
void add_entry_after(const T& n, const T& d) {
List_Member_Base<T> *f = sentinel->next;
while (f != sentinel && data(f) != d) {
f = f->next;
}
if (f == sentinel) {
fail(list_fail_add_entry_after,LIST_TEM_TYPEID_THIS);
} else {
List_Member<T> *e = new List_Member<T>(n);
e->next = f->next;
e->prev = f;
e->next->prev = e;
f->next = e;
n_entries++;
}
cleanup();
}
void add_entry_before(const T& n, const T& d) {
List_Member_Base<T> *f = sentinel->next;
while (f != sentinel && data(f) != d) {
f = f->next;
}
if (f == sentinel) {
fail(list_fail_add_entry_before,LIST_TEM_TYPEID_THIS);
} else {
List_Member<T> *e = new List_Member<T>(n);
e->prev = f->prev;
e->next = f;
e->prev->next = e;
f->prev = e;
n_entries++;
}
cleanup();
}
void delete_entry(const T& d) {
List_Member_Base<T> *e = sentinel->next;
while (e != sentinel && data(e) != d && e != sentinel) {
e = e->next;
}
if (e == sentinel) {
fail(list_fail_delete_entry,LIST_TEM_TYPEID_THIS);
} else {
e->prev->next = e->next;
e->next->prev = e->prev;
delete e;
}
n_entries--;
cleanup();
}
void delete_entry_backward(const T& d) {
List_Member_Base<T> *e = sentinel->prev;
while (e != sentinel && data(e) != d && e != sentinel) {
e = e->prev;
}
if (e == sentinel) {
fail(list_fail_delete_entry,LIST_TEM_TYPEID_THIS);
} else {
e->prev->next = e->next;
e->next->prev = e->prev;
delete e;
}
n_entries--;
cleanup();
}
void delete_entry_by_pointer(List_Member_Base<T>* l) {
if (l == sentinel)
fail(list_fail_delete_entry_by_pointer,LIST_TEM_TYPEID_THIS);
l->next->prev = l->prev;
l->prev->next = l->next;
delete l;
l = 0; // so we get a seg if we try and reuse it
n_entries--;
cleanup();
}
void alter_entry(const T& od, const T& nd) {
List_Member_Base<T> *e = sentinel->next;
while (e != sentinel && data(e) != od) {
e = e->next;
}
if (e == sentinel) {
fail(list_fail_alter_entry,LIST_TEM_TYPEID_THIS);
} else {
// Remove this entry, and put a new one in it's place. We can't
// just do e->data = nd, because that's assignment, and we don't
// want to require an assignment operator to be defined for
// every thing that we put on a list.
List_Member<T> * n = new List_Member<T>(nd);
e->prev->next = n;
e->next->prev = n;
n->next = e->next;
n->prev = e->prev;
delete e;
}
cleanup();
}
T next_entry(const T& d) const {
List_Member_Base<T> *e = sentinel->next;
while (e != sentinel && data(e) != d && e != sentinel) {
e = e->next;
}
if (e == sentinel) {
fail(list_fail_next_entry_nonexist,LIST_TEM_TYPEID_THIS);
} else {
if (e->next == sentinel)
fail(list_fail_next_entry_sentinel,LIST_TEM_TYPEID_THIS);
return data(e->next);
}
return data(e->next);
}
T prev_entry(const T& d) const {
List_Member_Base<T> *e = sentinel->next;
while (e!= sentinel && data(e) != d) {
e = e->next;
}
if (e == sentinel) {
fail(list_fail_prev_entry_nonexist,LIST_TEM_TYPEID_THIS);
} else {
if (e->prev == sentinel)
fail(list_fail_prev_entry_sentinel,LIST_TEM_TYPEID_THIS);
return data(e->prev);
}
return data(e->prev);
}
T const & similar_entry(T const& d) const
{
List_Member_Base<T> *e = sentinel->next;
while (e != sentinel)
{
if (data(e) == d)
break;
e = e->next;
}
if (e == sentinel)
{
fail(list_fail_similar_entry,LIST_TEM_TYPEID_THIS);
}
return data(e);
}
bool contains(const T& d) {
List_Member_Base<T> *e = sentinel->next;
while (e != sentinel && data(e) != d) {
e = e->next;
}
if (e == sentinel) return false;
else return true;
}
void delete_last_entry() {
if (sentinel->prev == sentinel) {
fail(list_fail_delete_last_entry,LIST_TEM_TYPEID_THIS);
} else {
// aiee. These lines work, but are a bit hairy.
sentinel->prev = sentinel->prev->prev;
delete sentinel->prev->next;
sentinel->prev->next = sentinel;
n_entries--;
}
cleanup();
}
void delete_first_entry() {
if (sentinel->next == sentinel) {
fail(list_fail_delete_last_entry,LIST_TEM_TYPEID_THIS);
} else {
sentinel->next = sentinel->next->next;
delete sentinel->next->prev;
sentinel->next->prev = sentinel;
n_entries--;
}
cleanup();
}
T const & operator[](int i) const {
if (i < 0 || i >= n_entries)
fail(list_fail_operator,LIST_TEM_TYPEID_THIS, i+1, n_entries);
if (!calculated_indices) {
if (entry_pointers != 0)
delete[] entry_pointers;
entry_pointers = new T*[n_entries+1];
List_Member_Base<T>*e = sentinel->next;
int j = 0;
while (e != sentinel) {
entry_pointers[j] = &data(e);
e = e->next;
j++;
}
calculated_indices = true;
}
return *entry_pointers[i];
}
T & last_entry()
{
if (n_entries == 0)
fail(list_fail_last_entry,LIST_TEM_TYPEID_THIS);
return data(sentinel->prev);
}
T const & last_entry() const
{
if (n_entries == 0)
fail(list_fail_last_entry,LIST_TEM_TYPEID_THIS);
return data(sentinel->prev);
}
T & first_entry()
{
if (n_entries == 0)
fail(list_fail_first_entry,LIST_TEM_TYPEID_THIS);
return data(sentinel->next);
}
T const & first_entry() const
{
if (n_entries == 0)
fail(list_fail_first_entry,LIST_TEM_TYPEID_THIS);
return data(sentinel->next);
}
int size() const { return n_entries; }
void cleanup() { calculated_indices = false; if (entry_pointers != 0) delete[] entry_pointers; entry_pointers = 0;}
bool operator==(const List <T> &l1) const
{
if (n_entries != l1.n_entries) return false;
for (List_Member_Base<T> * e = sentinel->next, *e1 = l1.sentinel->next; e != sentinel; e = e->next, e1 = e1->next)
{
if (((List_Member<T> *)e)->data != ((List_Member<T> *)e1)->data) return false;
}
return true;
}
bool operator!=(const List <T> &l1) const
{
if (n_entries != l1.n_entries) return true;
for (List_Member_Base<T> * e = sentinel->next, *e1 = l1.sentinel->next; e != sentinel; e = e->next, e1 = e1->next)
{
if (((List_Member<T> *)e)->data != ((List_Member<T> *)e1)->data) return true;
}
return false;
}
friend class List_Iterator_Forward<T>;
friend class ConstList_Iterator_Forward<T>;
friend class List_Iterator_Backward<T>;
friend class ConstList_Iterator_Backward<T>;
friend class List_Iterator_Loop<T>;
};
// Use List_Iterator_{Forward,Backward} as follows:
//
// for(List_Iterator_Forward<T*> oi(&(List_of_T*)); // a _pointer_
// // to the list.
// !oi.done();
// oi.next() ) {
// do_something( oi() ) ;
// }
//
// First entry is the one past the sentinel, and next() and
// operator() fail if you try and iterate too far; check if it's
// done() before doing anything else, basically.
//
// As it's a doubly-linked list, we can go backwards and
// forwards. next() takes us to the entry that the type of iterator
// suggests; un_next() takes us in the other direction. un_next() is
// an ugly name, but next() and prev() are too suggestive of a
// particular direction.
template<class T>
class List_Iterator_Forward
{
private:
union
{
List_Member_Base<T> *m;
List_Member<T> *m_debug; // encourage the debugger to display the list members data
// hopefully casting from base to derived class would not
// cause the actual value of the ptr to change, so the debugger
// will display the information correctly, and this union
// won't cause any kind of performance hit
};
List<T> *l;
public:
List_Iterator_Forward() {}
List_Iterator_Forward(List<T> *list) { l = list; m = l->sentinel->next; }
void next() {
if (m != l->sentinel) {
m = m->next;
} else
fail(lit_fail_next,LIST_TEM_TYPEID_THIS);
}
void un_next() {
if (m != l->sentinel) {
m = m->prev;
} else
fail(lit_fail_next,LIST_TEM_TYPEID_THIS);
}
T & operator() () const {
if (m == l->sentinel)
fail(lit_fail_operator,LIST_TEM_TYPEID_THIS);
return l->data(m);
}
void delete_current() {
if (m != l->sentinel) {
m = m->next;
l->delete_entry_by_pointer(m->prev);
} else
fail(lit_fail_delete_current,LIST_TEM_TYPEID_THIS);
}
void change_current(T const &new_val) const {
if (m != l->sentinel) {
// Delete the current member out of the list, put a new one in.
List_Member<T> * n = new List_Member<T>(new_val);
m->prev->next = n;
m->next->prev = n;
n->next = m->next;
n->prev = m->prev;
delete m;
*(List_Member_Base<T> **)&m =n; // or we're pointing at the thing we just deleted.
l->cleanup(); // because it's changed, but the List doesn't know that.
} else
fail(lit_fail_change_current,LIST_TEM_TYPEID_THIS);
}
bool done() { if (m == l->sentinel) return true; else return false; }
void restart() { m = l->sentinel->next; }
// Go to the end of the list.
void end() { m = l->sentinel->prev; }
};
#define LIF List_Iterator_Forward
template<class T>
class ConstList_Iterator_Forward
{
private:
union
{
List_Member_Base<T> *m;
List_Member<T> *m_debug; // encourage the debugger to display the list members data
};
List<T> const *l;
public:
ConstList_Iterator_Forward(List<T> const *list) { l = list; m = l->sentinel->next; }
ConstList_Iterator_Forward(){}
void next() {
if (m == l->sentinel) {
fail(lit_fail_next,LIST_TEM_TYPEID_THIS);
}
m = m->next;
}
void un_next() {
if (m == l->sentinel) {
fail(lit_fail_next,LIST_TEM_TYPEID_THIS);
}
m = m->prev;
}
T const & operator() () const {
if (m == l->sentinel)
fail(lit_fail_operator,LIST_TEM_TYPEID_THIS);
return l->data(m);
}
#if 0 // shouldn't really be available on a const list
void change_current(T const & new_val) const {
if (m != l->sentinel) {
m->data = new_val;
} else
fail(lit_fail_change_current,LIST_TEM_TYPEID_THIS);
}
#endif
bool done() const { if (m == l->sentinel) return true; else return false; }
void restart() { m = l->sentinel->next; }
// Go to the end of the list.
void end() { m = l->sentinel->prev; }
};
#define CLIF ConstList_Iterator_Forward
template<class T>
class List_Iterator_Backward
{
private:
union
{
List_Member_Base<T> *m;
List_Member<T> *m_debug; // encourage the debugger to display the list members data
};
List<T> *l;
public:
List_Iterator_Backward() {}
List_Iterator_Backward(List<T> *list) { l = list; m = l->sentinel->prev; }
void next() {
if (m != l->sentinel) {
m = m->prev;
} else
fail(lit_fail_next,LIST_TEM_TYPEID_THIS);
}
void un_next() {
if (m != l->sentinel) {
m = m->next;
} else
fail(lit_fail_next,LIST_TEM_TYPEID_THIS);
}
T & operator() () const {
if (m == l->sentinel)
fail(lit_fail_operator,LIST_TEM_TYPEID_THIS);
return l->data(m);
}
void delete_current() {
if (m != l->sentinel) {
m = m->prev;
l->delete_entry_by_pointer(m->next);
} else
fail(lit_fail_delete_current,LIST_TEM_TYPEID_THIS);
}
void change_current(T const & new_val) {
if (m != l->sentinel) {
// Delete the current member out of the list, put a new one in.
List_Member<T> * n = new List_Member<T>(new_val);
m->prev->next = n;
m->next->prev = n;
n->next = m->next;
n->prev = m->prev;
delete m;
m = n; // or we're pointing at the thing we just deleted.
l->cleanup(); // because it's changed, but the List doesn't know that.
} else
fail(lit_fail_change_current,LIST_TEM_TYPEID_THIS);
}
bool done() { if (m == l->sentinel) return true; else return false; }
void restart() { m = l->sentinel->prev; }
// Go to the end of the list.
void end() { m = l->sentinel->prev; }
};
#define LIB List_Iterator_Backward
template<class T>
class ConstList_Iterator_Backward
{
private:
union
{
List_Member_Base<T> *m;
List_Member<T> *m_debug; // encourage the debugger to display the list members data
};
List<T> const *l;
public:
ConstList_Iterator_Backward(List<T> const *list) { l = list; m = l->sentinel->prev; }
ConstList_Iterator_Backward(){}
void next() {
if (m == l->sentinel) {
fail(lit_fail_next,LIST_TEM_TYPEID_THIS);
}
m = m->prev;
}
void un_next() {
if (m == l->sentinel) {
fail(lit_fail_next,LIST_TEM_TYPEID_THIS);
}
m = m->next;
}
T const & operator() () const {
if (m == l->sentinel)
fail(lit_fail_operator,LIST_TEM_TYPEID_THIS);
return l->data(m);
}
#if 0 // shouldn't really be available on a const list
void change_current(T const & new_val) const {
if (m != l->sentinel) {
m->data = new_val;
} else
fail(lit_fail_change_current,LIST_TEM_TYPEID_THIS);
}
#endif
bool done() const { if (m == l->sentinel) return true; else return false; }
void restart() { m = l->sentinel->prev; }
// Go to the end of the list.
void end() { m = l->sentinel->prev; }
};
#define CLIB ConstList_Iterator_Backward
/*
A looping list iterator class :
next from the last member will go to the first
previous from the first member will go to the last
*/
template<class T>
class List_Iterator_Loop
{
private:
union
{
List_Member_Base<T> *m;
List_Member<T> *m_debug; // encourage the debugger to display the list members data
};
List<T> *l;
public:
List_Iterator_Loop(List<T> *list) { l = list; m = l->sentinel->next; }
void next() {
m=m->next;
if (m == l->sentinel) {
m = m->next;
}
}
void previous() {
m=m->prev;
if (m == l->sentinel) {
m = m->prev;
}
}
T const & operator() () {
if (m == l->sentinel)
{
m=m->next;//needed in case iterator was created before anything was added to the list
if (m == l->sentinel)
{
fail(lit_fail_operator,LIST_TEM_TYPEID_THIS);
}
}
return l->data(m);
}
void delete_current() {
if (m == l->sentinel)
{
m=m->next;//needed in case iterator was created before anything was added to the list
if (m == l->sentinel)
{
fail(lit_fail_delete_current,LIST_TEM_TYPEID_THIS);
}
}
m = m->next;
l->delete_entry_by_pointer(m->prev);
}
void change_current(T const & new_val)
{
if (m == l->sentinel)
m=m->next;//needed in case iterator was created before anything was added to the list
if (m != l->sentinel)
{
// Delete the current member out of the list, put a new one in.
List_Member<T> * n = new List_Member<T>(new_val);
m->prev->next = n;
m->next->prev = n;
n->next = m->next;
n->prev = m->prev;
delete m;
m = n; // or we're pointing at the thing we just deleted.
l->cleanup(); // because it's changed, but the List doesn't know that.
}
else
fail(lit_fail_change_current,LIST_TEM_TYPEID_THIS);
}
// Go to the start of the list.
void restart() { m = l->sentinel->next; }
// Go to the end of the list.
void end() { m = l->sentinel->prev; }
// Is it on the last entry.
bool at_last() const { if (m == l->sentinel->prev) return true; else return false; }
// Get the next entry but done move the pointer.
T const & get_next() {
if (m->next == l->sentinel)
{
if (m->next->next == l->sentinel)
{
fail(lit_fail_operator,LIST_TEM_TYPEID_THIS);
}
return l->data(m->next->next);
}
return l->data(m->next);
}
};
#define LIL List_Iterator_Loop
#ifdef NDEBUG
#undef fail // allow other code to have local variables called or differently scoped 'fail'
#endif
#endif

489
src/win95/ltchunk.cpp Normal file
View file

@ -0,0 +1,489 @@
#include "chunk.hpp"
#include "ltchunk.hpp"
#ifdef cencon
#define new my_new
#endif
//macro for helping to force inclusion of chunks when using libraries
FORCE_CHUNK_INCLUDE_IMPLEMENT(ltchunk)
////////////////////////////////////////////////////////////////////////////////////
//Class Light_Set_Chunk
RIF_IMPLEMENT_DYNCREATE("LIGHTSET",Light_Set_Chunk)
CHUNK_WITH_CHILDREN_LOADER("LIGHTSET",Light_Set_Chunk)
/*
Children for Light_Set_Chunk :
"LTSETHDR" Light_Set_Header_Chunk
"STDLIGHT" Light_Chunk
"AMBIENCE" Lighting_Ambience_Chunk
"LITSCALE" Light_Scale_Chunk
"AVPSTRAT" AVP_Strategy_Chunk
*/
Light_Set_Chunk::Light_Set_Chunk (Chunk_With_Children * parent, char * light_set_name)
: Chunk_With_Children (parent, "LIGHTSET")
{
new Light_Set_Header_Chunk (this, light_set_name);
}
////////////////////////////////////////////////////////////////////////////////////
RIF_IMPLEMENT_DYNCREATE("LTSETHDR",Light_Set_Header_Chunk)
Light_Set_Header_Chunk::Light_Set_Header_Chunk (Light_Set_Chunk * parent, char l_set_name[8])
: Chunk (parent, "LTSETHDR"), pad (0)
{
strncpy (light_set_name, l_set_name, 8);
}
void Light_Set_Header_Chunk::fill_data_block ( char * data_start)
{
strncpy (data_start, identifier, 8);
data_start += 8;
*((int *) data_start) = chunk_size;
data_start += 4;
strncpy (data_start, light_set_name, 8);
data_start += 8;
*((int *) data_start) = pad;
}
Light_Set_Header_Chunk::Light_Set_Header_Chunk (Chunk_With_Children * parent, const char * data, size_t const /*size*/)
: Chunk (parent, "LTSETHDR")
{
strncpy (light_set_name, data, 8);
data += 8;
pad = *((int *) data);
}
////////////////////////////////////////////////////////////////////////////////////
RIF_IMPLEMENT_DYNCREATE("STDLIGHT",Light_Chunk)
void Light_Chunk::fill_data_block ( char * data_start)
{
strncpy (data_start, identifier, 8);
data_start += 8;
*((int *) data_start) = chunk_size;
data_start += 4;
*((int *) data_start) = light.light_number;
data_start += 4;
*((ChunkVectorInt *) data_start) = light.location;
data_start += sizeof(ChunkVectorInt);
*((ChunkMatrix *) data_start) = light.orientation;
data_start += sizeof(ChunkMatrix);
*((int *) data_start) = light.brightness;
data_start += 4;
*((int *) data_start) = light.spread;
data_start += 4;
*((int *) data_start) = light.range;
data_start += 4;
*((int *) data_start) = light.colour;
data_start += 4;
*((int *) data_start) = light.engine_light_flags;
data_start += 4;
*((int *) data_start) = light.local_light_flags;
data_start += 4;
*((int *) data_start) = light.pad1;
data_start += 4;
*((int *) data_start) = light.pad2;
}
#if UseOldChunkLoader
Light_Chunk::Light_Chunk(Light_Set_Chunk * parent, const char * data, size_t const /*size*/)
: Chunk (parent, "STDLIGHT")
{
light.light_number = *((int *) data);
data += 4;
light.location = *((ChunkVector *) data);
data += sizeof(ChunkVector);
light.orientation.mat11 = (int) *((double *) data);
data += 8;
light.orientation.mat12 = (int) *((double *) data);
data += 8;
light.orientation.mat13 = (int) *((double *) data);
data += 8;
light.orientation.mat21 = (int) *((double *) data);
data += 8;
light.orientation.mat22 = (int) *((double *) data);
data += 8;
light.orientation.mat23 = (int) *((double *) data);
data += 8;
light.orientation.mat31 = (int) *((double *) data);
data += 8;
light.orientation.mat32 = (int) *((double *) data);
data += 8;
light.orientation.mat33 = (int) *((double *) data);
data += 8;
light.brightness = *((int *) data);
data += 4;
light.spread = *((int *) data);
data += 4;
light.range = *((int *) data);
data += 4;
light.colour = *((int *) data);
data += 4;
light.engine_light_flags = *((int *) data);
data += 4;
light.local_light_flags = *((int *) data);
data += 4;
light.pad1 = *((int *) data);
data += 4;
light.pad2 = *((int *) data);
#if engine || cencon
light_added_to_module = FALSE;
#endif
}
#else
Light_Chunk::Light_Chunk(Chunk_With_Children * parent, const char * data, size_t const /*size*/)
: Chunk (parent, "STDLIGHT")
{
light.light_number = *((int *) data);
data += 4;
light.location = *((ChunkVectorInt *) data);
data += sizeof(ChunkVectorInt);
light.orientation = *((ChunkMatrix *) data);
data += sizeof(ChunkMatrix);
light.brightness = *((int *) data);
data += 4;
light.spread = *((int *) data);
data += 4;
light.range = *((int *) data);
data += 4;
light.colour = *((int *) data);
data += 4;
light.engine_light_flags = *((int *) data);
data += 4;
light.local_light_flags = *((int *) data);
data += 4;
light.pad1 = *((int *) data);
data += 4;
light.pad2 = *((int *) data);
#if engine || cencon
light_added_to_module = FALSE;
#endif
}
#endif
#if InterfaceEngine
AVP_Strategy_Chunk* Light_Chunk::GetStrategyChunk()
{
List<Chunk*> chlist;
parent->lookup_child("AVPSTRAT",chlist);
for(LIF<Chunk*> chlif(&chlist);!chlif.done();chlif.next())
{
AVP_Strategy_Chunk* asc=(AVP_Strategy_Chunk*)chlif();
if(asc->index==light.light_number) return asc;
}
return 0;
}
AVP_Strategy_Chunk* Light_Chunk::CreateStrategyChunk()
{
AVP_Strategy_Chunk* asc=GetStrategyChunk();
if(asc) return asc;
asc=new AVP_Strategy_Chunk(parent);
asc->index=light.light_number;
return asc;
}
#endif
////////////////////////////////////////////////////////////////////////////////////
RIF_IMPLEMENT_DYNCREATE("SHPVTINT",Shape_Vertex_Intensities_Chunk)
Shape_Vertex_Intensities_Chunk::Shape_Vertex_Intensities_Chunk
(Chunk_With_Children *parent, char *lsn, int num_v, int * i_array)
: Chunk (parent, "SHPVTINT"), num_vertices(num_v), pad (0)
{
strncpy (light_set_name, lsn, 8);
intensity_array = new int [num_v];
for (int i=0; i<num_v; i++)
{
intensity_array[i] = i_array[i];
}
}
void Shape_Vertex_Intensities_Chunk::fill_data_block ( char * data_start)
{
strncpy (data_start, identifier, 8);
data_start += 8;
*((int *) data_start) = chunk_size;
data_start += 4;
strncpy (data_start, light_set_name,8);
data_start += 8;
*((int *) data_start) = pad;
data_start += 4;
*((int *) data_start) = num_vertices;
data_start += 4;
int * cia = (int *)data_start, * ia = intensity_array;
for (int i = num_vertices; i; i--)
{
*cia++ = *ia++;
}
}
Shape_Vertex_Intensities_Chunk::Shape_Vertex_Intensities_Chunk(Chunk_With_Children * parent, const char * data, size_t const /*size*/)
: Chunk (parent, "SHPVTINT")
{
strncpy (light_set_name, data, 8);
data += 8;
pad = *((int *)data);
data += 4;
num_vertices = *((int *)data);
data += 4;
intensity_array = new int [num_vertices];
int * cia = (int *)data, * ia = intensity_array;
for (int i = num_vertices; i; i--)
{
*ia++ = *cia++;
}
}
Shape_Vertex_Intensities_Chunk::~Shape_Vertex_Intensities_Chunk()
{
if (intensity_array)
delete [] intensity_array;
}
///////////////////////////////////////////////////////////////////////////
RIF_IMPLEMENT_DYNCREATE("AMBIENCE",Lighting_Ambience_Chunk)
void Lighting_Ambience_Chunk::fill_data_block ( char * data_start)
{
strncpy (data_start, identifier, 8);
data_start += 8;
*((int *) data_start) = chunk_size;
data_start += 4;
*((int *) data_start) = ambience;
data_start += 4;
}
///////////////////////////////////////////////////////////////////////////
RIF_IMPLEMENT_DYNCREATE("LITSCALE",Light_Scale_Chunk)
Light_Scale_Chunk::Light_Scale_Chunk(Light_Set_Chunk* parent,int mode)
:Chunk(parent,"LITSCALE")
{
LightMode=mode;
prelight_multiply=runtime_multiply=1;
prelight_multiply_above=runtime_multiply_above=0;
prelight_add=runtime_add=0;
spare1=spare2=spare3=0;
}
Light_Scale_Chunk::Light_Scale_Chunk(Chunk_With_Children* parent,const char* data,size_t)
:Chunk(parent,"LITSCALE")
{
LightMode=*(int*)data;
data+=4;
prelight_multiply=*(float*)data;
data+=4;
prelight_multiply_above= (int) *(float*)data;
data+=4;
prelight_add= (int) *(float*)data;
data+=4;
runtime_multiply=*(float*)data;
data+=4;
runtime_multiply_above= (int) *(float*)data;
data+=4;
runtime_add= (int) *(float*)data;
data+=4;
spare1=*(int*)data;
data+=4;
spare2=*(int*)data;
data+=4;
spare3=*(int*)data;
data+=4;
}
void Light_Scale_Chunk::fill_data_block(char* data_start)
{
strncpy(data_start,identifier,8);
data_start+=8;
*((int *) data_start) = chunk_size;
data_start += 4;
*(int*)data_start=LightMode;
data_start+=4;
*(float*)data_start=prelight_multiply;
data_start+=4;
*(float*)data_start= (float) prelight_multiply_above;
data_start+=4;
*(float*)data_start= (float) prelight_add;
data_start+=4;
*(float*)data_start=runtime_multiply;
data_start+=4;
*(float*)data_start= (float) runtime_multiply_above;
data_start+=4;
*(float*)data_start= (float) runtime_add;
data_start+=4;
*(int*)data_start=spare1;
data_start+=4;
*(int*)data_start=spare2;
data_start+=4;
*(int*)data_start=spare3;
data_start+=4;
}
int Light_Scale_Chunk::ApplyPrelightScale(int l)
{
if(l<prelight_multiply_above)return l;
l+=(prelight_add-prelight_multiply_above);
l= (int)(l*prelight_multiply);
l+=prelight_multiply_above;
l=min(l,255);
return max(l,prelight_multiply_above);
}
int Light_Scale_Chunk::ApplyRuntimeScale(int l)
{
if(l<runtime_multiply_above)return l;
l+=(runtime_add-runtime_multiply_above);
l=(int)( l*runtime_multiply);
l+=runtime_multiply_above;
l=min(l,255);
return max(l,runtime_multiply_above);
}
////////////////////////////////////////////////////////////////////////////////////
RIF_IMPLEMENT_DYNCREATE("PLOBJLIT",Placed_Object_Light_Chunk)
Placed_Object_Light_Chunk::Placed_Object_Light_Chunk(Chunk_With_Children * parent, const char * data, size_t const /*size*/)
: Chunk (parent, "PLOBJLIT")
{
light=*(Placed_Object_Light_Data*) data;
data+=sizeof(Placed_Object_Light_Data);
num_extra_data=*(int*)data;
data+=4;
if(num_extra_data)
{
extra_data=new int[num_extra_data];
for(int i=0;i<num_extra_data;i++)
{
extra_data[i]=*(int*)data;
data+=4;
}
}
else
{
extra_data=0;
}
}
Placed_Object_Light_Chunk::~Placed_Object_Light_Chunk()
{
if(extra_data)
{
delete [] extra_data;
}
}
void Placed_Object_Light_Chunk::fill_data_block(char* data)
{
strncpy (data, identifier, 8);
data += 8;
*((int *) data) = chunk_size;
data += 4;
*(Placed_Object_Light_Data*)data=light;
data+=sizeof(Placed_Object_Light_Data);
*(int*)data=num_extra_data;
data+=4;
for(int i=0;i<num_extra_data;i++)
{
*(int*)data=extra_data[i];
data+=4;
}
}
////////////////////////////////////////////////////////////////////////////////////

273
src/win95/ltchunk.hpp Normal file
View file

@ -0,0 +1,273 @@
#ifndef _ltchunk_hpp
#define _ltchunk_hpp 1
#include "chunk.hpp"
#include "chnktype.hpp"
#if InterfaceEngine
#include "strachnk.hpp"
#endif
#define LOFlag_On 0x00000001
#define LOFlag_ShadowData 0x00000002
#define LOFlag_Changed 0x00000004
#define LOFlag_Calc_Data 0x00000008
#define LOFlag_Runtime 0x00000010
#define LOFlag_Invisible 0x00000020
#define LOFlag_NoPreLight 0x00000040
class Environment_Data_Chunk;
class Light_Data
{
public:
int light_number;
ChunkVectorInt location;
ChunkMatrix orientation;
int brightness;
int spread;
int range;
int colour;
int engine_light_flags;
int local_light_flags;
int pad1;
int pad2;
};
#define PlacedLightType_Standard 0
#define PlacedLightType_Strobe 1
#define PlacedLightType_Flicker 2
#define PlacedLightOnOff_Standard 0
#define PlacedLightOnOff_Fade 1
#define PlacedLightOnOff_Flicker 2
#define PlacedLightFlag_On 0x00000001
#define PlacedLightFlag_SwapColourBright 0x00000002
#define PlacedLightFlag_NoSpecular 0x00000004
class Placed_Object_Light_Data
{
public:
int brightness;
int spread;
int range;
int up_colour;
int down_colour;
int engine_light_flags;
int local_light_flags;
int fade_up_time;
int fade_down_time;
int up_time;
int down_time;
int start_time;
int light_type;
int on_off_type;
int flags;
};
class Light_Set_Chunk : public Chunk_With_Children
{
public:
// for user
Light_Set_Chunk (Chunk_With_Children * parent, char * light_set_name);
Light_Set_Chunk (Chunk_With_Children * const parent,const char *, size_t const);
private:
friend class Environment_Data_Chunk;
};
class Light_Set_Header_Chunk : public Chunk
{
public:
Light_Set_Header_Chunk (Light_Set_Chunk * parent, char l_set_name[8]);
Light_Set_Header_Chunk (Chunk_With_Children * parent, const char *, size_t const);
char light_set_name[8];
int pad;
size_t size_chunk()
{
return (chunk_size = 12 + 8 + 4);
}
void fill_data_block ( char * data_start);
private:
friend class Light_Set_Chunk;
};
class Light_Chunk : public Chunk
{
public:
Light_Chunk (Light_Set_Chunk * parent, Light_Data & new_light)
: Chunk (parent, "STDLIGHT"), light (new_light) {}
Light_Chunk (Chunk_With_Children * parent, const char *, size_t const);
Light_Data light;
BOOL light_added_to_module;
size_t size_chunk()
{
return (chunk_size = 12 + 9 * 4 + 3 * 4 + 9 * 4);
}
void fill_data_block ( char * data_start);
#if InterfaceEngine
AVP_Strategy_Chunk* GetStrategyChunk();
AVP_Strategy_Chunk* CreateStrategyChunk();
#endif
private:
friend class Light_Set_Chunk;
};
//should be a child of an object_chunk
class Placed_Object_Light_Chunk : public Chunk
{
public :
Placed_Object_Light_Chunk (Chunk_With_Children * parent, Placed_Object_Light_Data & new_light)
: Chunk (parent, "PLOBJLIT"), light (new_light),num_extra_data(0),extra_data(0) {}
Placed_Object_Light_Chunk (Chunk_With_Children * parent, const char *, size_t const);
~Placed_Object_Light_Chunk();
Placed_Object_Light_Data light;
int* extra_data;
int num_extra_data;
size_t size_chunk()
{
return (chunk_size = 12 +sizeof(Placed_Object_Light_Data) +4 +4*num_extra_data);
}
void fill_data_block ( char * data_start);
};
class Shape_Vertex_Intensities_Chunk : public Chunk
{
public:
Shape_Vertex_Intensities_Chunk(Chunk_With_Children *, char *, int, int *);
Shape_Vertex_Intensities_Chunk(Chunk_With_Children *, const char *, size_t const);
~Shape_Vertex_Intensities_Chunk();
char light_set_name[8];
int pad;
int num_vertices;
int * intensity_array;
size_t size_chunk()
{
return (chunk_size = 12 + 8 + 4 + 4 + 4 * num_vertices);
}
void fill_data_block ( char * data_start);
private:
friend class Object_Chunk;
};
class Lighting_Ambience_Chunk : public Chunk
{
public:
Lighting_Ambience_Chunk (Light_Set_Chunk * parent, int _ambience)
: Chunk (parent, "AMBIENCE"), ambience (_ambience)
{}
Lighting_Ambience_Chunk (Chunk_With_Children * parent, const char * data, size_t const /*size*/)
: Chunk (parent, "AMBIENCE"), ambience (*((int *)data))
{}
int ambience;
size_t size_chunk()
{
return (chunk_size = 12 + 4);
}
void fill_data_block ( char * data_start);
private:
friend class Light_Set_Chunk;
};
#define PSXLightMode 0
//details of how light data should be altered for different platforms.
//currently just playstation
class Light_Scale_Chunk : public Chunk
{
public :
Light_Scale_Chunk(Light_Set_Chunk * parent,int mode);
Light_Scale_Chunk(Chunk_With_Children* parent,const char* data,size_t);
void fill_data_block ( char * data_start);
size_t size_chunk()
{
return (chunk_size = 12 + 44);
}
int LightMode;
float prelight_multiply;
int prelight_multiply_above;
int prelight_add;
float runtime_multiply;
int runtime_multiply_above;
int runtime_add;
int ApplyPrelightScale(int l);
int ApplyRuntimeScale(int l);
int spare1,spare2,spare3,spare4;
};
#endif

556
src/win95/media.cpp Normal file
View file

@ -0,0 +1,556 @@
#include "advwin32.h"
#include "media.hpp"
void * MediaMedium::GetWriteBuffer(unsigned * pSize, unsigned /*nDesiredSize*/)
{
*pSize = 0;
m_fError |= MME_UNAVAIL;
return NULL;
}
void const * MediaMedium::GetReadBuffer(unsigned * pSize, unsigned /*nDesiredSize*/)
{
*pSize = 0;
m_fError |= MME_UNAVAIL;
return NULL;
}
void MediaMedium::CloseWriteBuffer(unsigned /*nPosOffset*/)
{
m_fError |= MME_UNAVAIL;
}
void MediaMedium::CloseReadBuffer(unsigned /*nPosOffset*/)
{
m_fError |= MME_UNAVAIL;
}
void MediaMedium::DoWriteBlock(void const * /*pData*/, unsigned /*nSize*/)
{
m_fError |= MME_UNAVAIL;
}
void MediaMedium::DoReadBlock(void * /*pData*/, unsigned /*nSize*/)
{
m_fError |= MME_UNAVAIL;
}
unsigned MediaMedium::GetRemainingSize()
{
return UINT_MAX;
}
// MediaWinFileMedium
#ifdef _MEDIA_WIN_TARGET
unsigned MediaWinFileMedium::GetRemainingSize()
{
if (INVALID_HANDLE_VALUE == m_hFile)
{
m_fError |= MME_UNAVAIL;
return 0;
}
unsigned nSize = GetFileSize(m_hFile,NULL);
if (0xffffffff == nSize)
{
m_fError |= MME_UNAVAIL;
return 0;
}
return nSize - GetPos();
}
void * MediaWinFileMedium::GetWriteBuffer(unsigned * pSize, unsigned nDesiredSize)
{
m_pBuffer = new char [nDesiredSize];
*pSize = nDesiredSize;
return m_pBuffer;
}
void const * MediaWinFileMedium::GetReadBuffer(unsigned * pSize, unsigned nDesiredSize)
{
if (INVALID_HANDLE_VALUE == m_hFile)
// the base/default implementation raises an error
return MediaMedium::GetReadBuffer(pSize,nDesiredSize);
m_pBuffer = new char [nDesiredSize];
DWORD nBytesRead = 0;
if (!ReadFile(m_hFile, m_pBuffer, nDesiredSize, &nBytesRead, NULL))
m_fError |= MME_IOERROR;
else if (!nBytesRead)
m_fError |= MME_EOFMET;
*pSize = m_nReadBufLen = nBytesRead;
return m_pBuffer;
}
void MediaWinFileMedium::CloseWriteBuffer(unsigned nPosOffset)
{
if (INVALID_HANDLE_VALUE == m_hFile)
{
// the base/default implementation raises an error
MediaMedium::CloseWriteBuffer(nPosOffset);
return;
}
DWORD nBytesWritten = 0;
if (!WriteFile(m_hFile, m_pBuffer, nPosOffset, &nBytesWritten, NULL))
m_fError |= MME_IOERROR;
else if (nBytesWritten < nPosOffset)
m_fError |= MME_EOFMET;
delete [] m_pBuffer;
}
void MediaWinFileMedium::CloseReadBuffer(unsigned nPosOffset)
{
if (INVALID_HANDLE_VALUE == m_hFile)
{
// the base/default implementation raises an error
MediaMedium::CloseReadBuffer(nPosOffset);
return;
}
if (nPosOffset != m_nReadBufLen && 0xffffffff == SetFilePointer(m_hFile,nPosOffset - m_nReadBufLen,NULL,FILE_CURRENT))
m_fError |= MME_UNAVAIL;
m_nReadBufLen = 0;
delete [] m_pBuffer;
}
void MediaWinFileMedium::DoWriteBlock(void const * pData, unsigned nSize)
{
if (INVALID_HANDLE_VALUE == m_hFile)
{
MediaMedium::DoWriteBlock(pData,nSize);
return;
}
DWORD nBytesWritten = 0;
if (!WriteFile(m_hFile, pData, nSize, &nBytesWritten, NULL))
m_fError |= MME_IOERROR;
else if (nBytesWritten < nSize)
m_fError |= MME_EOFMET;
}
void MediaWinFileMedium::DoReadBlock(void * pData, unsigned nSize)
{
if (INVALID_HANDLE_VALUE == m_hFile)
{
MediaMedium::DoReadBlock(pData,nSize);
return;
}
DWORD nBytesRead = 0;
if (!ReadFile(m_hFile, pData, nSize, &nBytesRead, NULL))
m_fError |= MME_IOERROR;
else if (nBytesRead < nSize)
m_fError |= MME_EOFMET;
}
unsigned MediaWinFileMedium::DoGetPos()
{
unsigned nFilePos = SetFilePointer(m_hFile,0,NULL,FILE_CURRENT);
if (0xffffffff == nFilePos)
{
m_fError |= MME_UNAVAIL;
return 0;
}
return nFilePos - m_nReadBufLen;
}
void MediaWinFileMedium::DoSetPos(unsigned nPos)
{
if (0xffffffff == SetFilePointer(m_hFile,nPos,NULL,FILE_BEGIN))
m_fError |= MME_UNAVAIL;
}
#endif // _MEDIA_WIN_TARGET
// MediaStdFileMedium
unsigned MediaStdFileMedium::GetRemainingSize()
{
if (!m_pFile)
{
m_fError |= MME_UNAVAIL;
return 0;
}
long nPos = ftell(m_pFile);
if (-1L == nPos || fseek(m_pFile,0,SEEK_END))
{
m_fError |= MME_UNAVAIL;
return 0;
}
long nSize = ftell(m_pFile);
fseek(m_pFile,nPos,SEEK_SET);
if (-1L == nSize)
{
m_fError |= MME_UNAVAIL;
return 0;
}
return nSize - GetPos();
}
void * MediaStdFileMedium::GetWriteBuffer(unsigned * pSize, unsigned nDesiredSize)
{
m_pBuffer = new char [nDesiredSize];
*pSize = nDesiredSize;
return m_pBuffer;
}
void const * MediaStdFileMedium::GetReadBuffer(unsigned * pSize, unsigned nDesiredSize)
{
if (!m_pFile)
// the base/default implementation raises an error
return MediaMedium::GetReadBuffer(pSize,nDesiredSize);
m_pBuffer = new char [nDesiredSize];
*pSize = m_nReadBufLen = fread(m_pBuffer, 1, nDesiredSize, m_pFile);
if (!m_nReadBufLen)
{
if (feof(m_pFile))
m_fError |= MME_EOFMET;
else
m_fError |= MME_IOERROR;
}
return m_pBuffer;
}
void MediaStdFileMedium::CloseWriteBuffer(unsigned nPosOffset)
{
if (!m_pFile)
{
// the base/default implementation raises an error
MediaMedium::CloseWriteBuffer(nPosOffset);
return;
}
if (fwrite(m_pBuffer, 1, nPosOffset, m_pFile) < nPosOffset)
{
if (feof(m_pFile))
m_fError |= MME_EOFMET;
else
m_fError |= MME_IOERROR;
}
delete [] m_pBuffer;
}
void MediaStdFileMedium::CloseReadBuffer(unsigned nPosOffset)
{
if (!m_pFile)
{
// the base/default implementation raises an error
MediaMedium::CloseReadBuffer(nPosOffset);
return;
}
if (nPosOffset != m_nReadBufLen && fseek(m_pFile,nPosOffset - m_nReadBufLen,SEEK_CUR))
m_fError |= MME_UNAVAIL;
m_nReadBufLen = 0;
delete [] m_pBuffer;
}
void MediaStdFileMedium::DoWriteBlock(void const * pData, unsigned nSize)
{
if (!m_pFile)
{
MediaMedium::DoWriteBlock(pData,nSize);
return;
}
if (fwrite(pData, 1, nSize, m_pFile) < nSize)
{
if (feof(m_pFile))
m_fError |= MME_EOFMET;
else
m_fError |= MME_IOERROR;
}
}
void MediaStdFileMedium::DoReadBlock(void * pData, unsigned nSize)
{
if (!m_pFile)
{
MediaMedium::DoReadBlock(pData,nSize);
return;
}
if (fread(pData, 1, nSize, m_pFile) < nSize)
{
if (feof(m_pFile))
m_fError |= MME_EOFMET;
else
m_fError |= MME_IOERROR;
}
}
unsigned MediaStdFileMedium::DoGetPos()
{
long nFilePos = ftell(m_pFile);
if (-1L == nFilePos)
{
m_fError |= MME_UNAVAIL;
return 0;
}
return nFilePos - m_nReadBufLen;
}
void MediaStdFileMedium::DoSetPos(unsigned nPos)
{
if (fseek(m_pFile,nPos,SEEK_SET))
m_fError |= MME_UNAVAIL;
}
// MediaMemoryReadMedium
void const * MediaMemoryReadMedium::GetReadBuffer(unsigned * pSize, unsigned nDesiredSize)
{
if (!m_pMem)
// the base/default implementation raises an error
return MediaMedium::GetReadBuffer(pSize,nDesiredSize);
*pSize = nDesiredSize;
return static_cast<char const *>(m_pMem)+m_nOffset/sizeof(char);
}
void MediaMemoryReadMedium::CloseReadBuffer(unsigned nPosOffset)
{
if (!m_pMem)
{
// the base/default implementation raises an error
MediaMedium::CloseReadBuffer(nPosOffset);
return;
}
m_nOffset += nPosOffset;
}
void MediaMemoryReadMedium::DoReadBlock(void * pData, unsigned nSize)
{
if (!m_pMem)
{
MediaMedium::DoReadBlock(pData,nSize);
return;
}
memcpy(pData,static_cast<char const *>(m_pMem)+m_nOffset/sizeof(char),nSize);
m_nOffset += nSize;
}
unsigned MediaMemoryReadMedium::DoGetPos()
{
return m_nOffset;
}
void MediaMemoryReadMedium::DoSetPos(unsigned nPos)
{
m_nOffset = nPos;
}
// MediaMemoryMedium
void * MediaMemoryMedium::GetWriteBuffer(unsigned * pSize, unsigned nDesiredSize)
{
if (!m_pMem)
// the base/default implementation raises an error
return MediaMedium::GetWriteBuffer(pSize,nDesiredSize);
*pSize = nDesiredSize;
return static_cast<char *>(m_pMem)+m_nOffset/sizeof(char);
}
void MediaMemoryMedium::CloseWriteBuffer(unsigned nPosOffset)
{
if (!m_pMem)
{
// the base/default implementation raises an error
MediaMedium::CloseWriteBuffer(nPosOffset);
return;
}
m_nOffset += nPosOffset;
}
void MediaMemoryMedium::DoWriteBlock(void const * pData, unsigned nSize)
{
if (!m_pMem)
{
MediaMedium::DoWriteBlock(pData,nSize);
return;
}
memcpy(static_cast<char *>(m_pMem)+m_nOffset/sizeof(char),pData,nSize);
m_nOffset += nSize;
}
// MediaSection
unsigned MediaSection::GetRemainingSize()
{
if (!m_pMedium)
{
m_fError |= MME_UNAVAIL;
return 0;
}
unsigned nSectionSize = m_nMaxSize - GetPos();
unsigned nMediaSize = m_pMedium->GetRemainingSize();
m_fError |= m_pMedium->m_fError;
return nSectionSize < nMediaSize ? nSectionSize : nMediaSize;
}
void * MediaSection::GetWriteBuffer(unsigned * pSize, unsigned nDesiredSize)
{
if (!m_pMedium)
return MediaMedium::GetWriteBuffer(pSize,nDesiredSize);
if (m_nPos + nDesiredSize > m_nMaxSize)
{
nDesiredSize = m_nMaxSize - m_nPos;
}
void * p = m_pMedium->GetWriteBuffer(pSize,nDesiredSize);
m_fError |= m_pMedium->m_fError;
return p;
}
void const * MediaSection::GetReadBuffer(unsigned * pSize, unsigned nDesiredSize)
{
if (!m_pMedium)
return MediaMedium::GetReadBuffer(pSize,nDesiredSize);
if (m_nPos + nDesiredSize > m_nMaxSize)
{
nDesiredSize = m_nMaxSize - m_nPos;
}
void const * p = m_pMedium->GetReadBuffer(pSize,nDesiredSize);
m_fError |= m_pMedium->m_fError;
return p;
}
void MediaSection::CloseWriteBuffer(unsigned nPosOffset)
{
if (!m_pMedium)
{
MediaMedium::CloseWriteBuffer(nPosOffset);
return;
}
m_nPos += nPosOffset;
m_pMedium->CloseWriteBuffer(nPosOffset);
m_fError |= m_pMedium->m_fError;
}
void MediaSection::CloseReadBuffer(unsigned nPosOffset)
{
if (!m_pMedium)
{
MediaMedium::CloseReadBuffer(nPosOffset);
return;
}
m_nPos += nPosOffset;
m_pMedium->CloseReadBuffer(nPosOffset);
m_fError |= m_pMedium->m_fError;
}
void MediaSection::DoWriteBlock(void const * pData, unsigned nSize)
{
if (!m_pMedium)
{
MediaMedium::DoWriteBlock(pData,nSize);
return;
}
if (m_nPos + nSize > m_nMaxSize)
{
m_fError |= MME_VEOFMET;
return;
}
m_nPos += nSize;
m_pMedium->DoWriteBlock(pData,nSize);
m_fError |= m_pMedium->m_fError;
}
void MediaSection::DoReadBlock(void * pData, unsigned nSize)
{
if (!m_pMedium)
{
MediaMedium::DoReadBlock(pData,nSize);
return;
}
if (m_nPos + nSize > m_nMaxSize)
{
m_fError |= MME_VEOFMET;
return;
}
m_nPos += nSize;
m_pMedium->DoReadBlock(pData,nSize);
m_fError |= m_pMedium->m_fError;
}
unsigned MediaSection::DoGetPos()
{
return m_nPos;
}
void MediaSection::DoSetPos(unsigned nPos)
{
if (!m_pMedium)
{
m_fError |= MME_UNAVAIL;
return;
}
if (nPos > m_nMaxSize)
{
m_fError |= MME_VEOFMET;
return;
}
m_pMedium->DoSetPos(m_pMedium->DoGetPos()+nPos-m_nPos);
if (m_nPos > m_nUsedPos) m_nUsedPos = m_nPos;
m_nPos = nPos;
m_fError |= m_pMedium->m_fError;
}

681
src/win95/media.hpp Normal file
View file

@ -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

1999
src/win95/mishchnk.cpp Normal file

File diff suppressed because it is too large Load diff

250
src/win95/mishchnk.hpp Normal file
View file

@ -0,0 +1,250 @@
#ifndef _miscchunk_hpp
#define _miscchunk_hpp 1
#include <time.h>
#include "chunk.hpp"
#include "chnktype.hpp"
#if engine
#define UseLocalAssert No
#include "ourasert.h"
#define assert(x) GLOBALASSERT(x)
#else
#if cencon
#include "ccassert.h"
#else
#include <assert.h>
#endif
#endif
#if cencon
#include "output.hpp"
#else
#define twprintf printf
extern char * users_name;
#endif
class File_Chunk;
class Lockable_Chunk_With_Children : public Chunk_With_Children
{
public:
Lockable_Chunk_With_Children (Chunk_With_Children * parent, const char * identifier)
: Chunk_With_Children (parent, identifier),
updated (FALSE),updated_outside (FALSE),local_lock (FALSE),external_lock(FALSE),
output_chunk_for_process (FALSE), deleted (FALSE)
{}
// derived classes from this class must have the
// following functions (or it won't compile)!!
virtual BOOL file_equals(HANDLE &) = 0;
// the file equals function knows to look in
// the file from the start of the current chunk
// to see if the current chunk is the same one
virtual const char * get_head_id() = 0;
virtual void set_lock_user(char *) = 0;
// this function will lock the chunk if it can -
// will return true on success or if the chunk has
// already been locked locally.
BOOL lock_chunk(File_Chunk &);
// The unlock_chunk will unlock the chunk
// if the updateyn flag is set, the updated flag will be set
// internally and the chunk may be updated on the next file update
// If there is no update, the chunk will be unlocked in the file
BOOL unlock_chunk (File_Chunk &, BOOL updateyn);
BOOL update_chunk_in_file(HANDLE &rif_file);
// Selective output functions,
// These will output on condition of the flag, the flag will be set
// to FALSE
BOOL output_chunk_for_process;
virtual size_t size_chunk_for_process();
virtual void fill_data_block_for_process(char * data_start);
BOOL updated;
BOOL updated_outside;
BOOL local_lock;
BOOL external_lock;
BOOL deleted;
};
///////////////////////////////////////////////
class Object_Chunk;
class Shape_Chunk;
class Dummy_Object_Chunk;
class Environment_Data_Chunk;
class File_Chunk : public Chunk_With_Children
{
public:
//constructor
File_Chunk (const char * filename);
File_Chunk ();
//destructor
~File_Chunk ();
// file handling
BOOL update_file ();
BOOL write_file (const char *);
BOOL check_file();
BOOL update_chunks_from_file();
// the file_chunk must link all of its shapes & objects together
// in post_input_processing
virtual void post_input_processing();
// copy string when constructed
// to this variable
char * filename;
// some easy access functions
void list_objects(List<Object_Chunk *> * pList);
void list_shapes(List<Shape_Chunk *> * pList);
void list_dummy_objects(List<Dummy_Object_Chunk *> * pList);
Environment_Data_Chunk * get_env_data();
Object_Chunk* get_object_by_index(int index);
void assign_index_to_object(Object_Chunk* object);
private:
friend class Shape_Chunk;
friend class Object_Chunk;
friend class Lockable_Chunk_With_Children;
int flags;
int object_array_size;
Object_Chunk** object_array;
void build_object_array();
};
///////////////////////////////////////////////
class RIF_Version_Num_Chunk : public Chunk
{
public:
RIF_Version_Num_Chunk (Chunk_With_Children * parent, const char *data, size_t /*size*/)
: Chunk (parent,"RIFVERIN"), file_version_no (*((int *) data))
{}
int file_version_no;
// output_chunk updates the above
virtual void fill_data_block (char * data_start);
virtual size_t size_chunk ()
{
chunk_size = 16;
return 16;
}
private:
friend class File_Chunk;
friend class GodFather_Chunk;
friend class RIF_File_Chunk;
RIF_Version_Num_Chunk (Chunk_With_Children * parent)
: Chunk (parent,"RIFVERIN"), file_version_no (0)
{}
};
///////////////////////////////////////////////
class RIF_File_Chunk : public Chunk_With_Children
{
public:
// This is a special chunk which does not output itself
RIF_File_Chunk (Chunk_With_Children * parent, const char * fname);
size_t size_chunk()
{
return chunk_size = 0;
}
virtual void post_input_processing();
BOOL output_chunk (HANDLE & /*h*/){return TRUE;};
void fill_data_block (char * /*c*/){};
void list_objects(List<Object_Chunk *> * pList);
void list_shapes(List<Shape_Chunk *> * pList);
Environment_Data_Chunk * get_env_data();
};
///////////////////////////////////////////////
class RIF_Name_Chunk : public Chunk
{
public:
RIF_Name_Chunk (Chunk_With_Children * parent, const char * rname);
~RIF_Name_Chunk();
// constructor from buffer
RIF_Name_Chunk (Chunk_With_Children * parent, const char * sdata, size_t ssize);
char * rif_name;
virtual size_t size_chunk ()
{
return (chunk_size = 12 + strlen (rif_name) + 4 - strlen (rif_name)%4);
}
virtual void fill_data_block (char * data_start);
private:
friend class Environment_Data_Chunk;
friend class Environment_Game_Mode_Chunk;
friend class Shape_External_File_Chunk;
friend class Sprite_Header_Chunk;
};
#endif

1272
src/win95/mmx_math.asm Normal file

File diff suppressed because it is too large Load diff

469
src/win95/mmx_math.h Normal file
View file

@ -0,0 +1,469 @@
#ifndef _included_mmx_math_h_
#define _included_mmx_math_h_
#if SUPPORT_MMX
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/*
Calling-convention independent
definitions of inline MMX assembler
functions and declarations for non-
inline MMX assembler functions
*/
/* SPECIFICATION */
/*
Dot Product and Vector Transform functions take
arguments referencing matrices or vectors whose
elements are 32 bit signed integers and arranged as
follows. All integers (including the results) are
in 16.16 fixed point form - ie. The 64-bit results
are shifted down 16 bits (divided by 65536) before
being written back as 32-bit values. Results are
rounded down (towards negative infinity).
the matrix structure looks like this (not ideal!)
[ +00 +0c +18 ]
[ +04 +10 +1c ]
[ +08 +14 +20 ]
and the vector structure looks like this
[ +00 ]
[ +04 ]
[ +08 ]
*/
/* TYPICAL CHARACTERISTICS */
/*
Accuracy
Internal rounding errors may be propogated, and
the results may not be exact. For the Dot Product
result and the Vector Transform results (x,y and z
independently), the error distributions are all
the same, as follows:
Exact: 25%
-1: 50%
-2: 25%
Better accuracy can be obtained by adding 1 to each integer result,
but this will produce poor results in the case of nice simple round
numbers, eg Dot({1.0,0.0,0.0},{0.0,1.0,0.0}) gives 1 not 0!
Speed
The DotProduct Takes 33 cycles (not including call instruction)
The inline DotProduct takes 30+1 cycles (the last instruction is pairable)
All Vector transforms take 63 cycles. These figures assume no
stalls due to cache misses or misaligned data. A matrix multiply
or cross product could be supplied if it is thought they would
be necessary
For optimal performance, it is recommended that vector and
matrix structures should be aligned to EIGHT byte boundaries.
To ensure this in arrays of vectors/matrices, the structure
should contain a dummy padding 32-bit value (recommended).
*/
/* storage class specifier for assembler calls */
#ifdef __WATCOMC__
#define _asmcall
#define _asminline
#elif defined(_MSC_VER)
#define _asmcall static __inline
#define _asminline static __inline
#else
#error "Unknown compiler"
#endif
/* forward reference declared in global scope */
struct vectorch;
struct matrixch;
/***********************/
/* F-U-N-C-T-I-O-N */
/* P-R-O-T-O-T-Y-P-E-S */
/* F-O-R A-L-L */
/* P-U-B-L-I-C */
/* F-U-N-C-T-I-O-N-S */
/***********************/
/* overwrites the input vector with the new vector */
_asmcall void MMX_VectorTransform(struct vectorch * vector, struct matrixch const * matrix);
/* fills a new vector with the result of the input vector transformed by the matrix */
_asmcall void MMX_VectorTransformed(struct vectorch * v_result, struct vectorch const * v_parm, struct matrixch const * matrix);
/* overwrites the input vector with the new vector, then adds another vector */
_asmcall void MMX_VectorTransformAndAdd(struct vectorch * vector, struct matrixch const * matrix, struct vectorch const * v_add);
/* fills a new vector with the result of the input vector transformed by the matrix then added to another vector */
_asmcall void MMX_VectorTransformedAndAdd(struct vectorch * v_result, struct vectorch const * v_parm, struct matrixch const * matrix, struct vectorch const * v_add);
/* compute dot product */
_asmcall signed MMX_VectorDot(struct vectorch const * v1, struct vectorch const * v2);
/* this one assumes all the input vector elements are in the range [-32768,32767] */
_asmcall signed MMX_VectorDot16(struct vectorch const * v1, struct vectorch const * v2);
/* inline versions */
_asminline signed MMXInline_VectorDot(struct vectorch const * v1, struct vectorch const * v2);
_asminline signed MMXInline_VectorDot16(struct vectorch const * v1, struct vectorch const * v2);
/*****************/
/* PRIVATE PARTS */
/*****************/
/* Assembler labels */
extern void MMXAsm_VectorTransform(void);
extern void MMXAsm_VectorTransformed(void);
extern void MMXAsm_VectorTransformAndAdd(void);
extern void MMXAsm_VectorTransformedAndAdd(void);
extern void MMXAsm_VectorDot(void);
extern void MMXAsm_VectorDot16(void);
/* inline calls to MMX functions with correct parameters set */
#ifdef __WATCOMC__
#pragma aux MMX_VectorTransform = "call MMXAsm_VectorTransform" parm [eax] [edx];
#pragma aux MMX_VectorTransformed = "call MMXAsm_VectorTransformed" parm [eax] [edx] [ecx];
#pragma aux MMX_VectorTransformAndAdd = "call MMXAsm_VectorTransformAndAdd" parm [eax] [edx] [ecx];
#pragma aux MMX_VectorTransformedAndAdd = "call MMXAsm_VectorTransformedAndAdd" parm [eax] [edx] [ecx] [ebx];
#pragma aux MMX_VectorDot = "call MMXAsm_VectorDot" parm [eax] [edx] value [eax];
#pragma aux MMX_VectorDot16 = "call MMXAsm_VectorDot16" parm [eax] [edx] value [eax];
#elif defined(_MSC_VER)
_asmcall void MMX_VectorTransform(struct vectorch * vector, struct matrixch const * matrix)
{
_asm
{
mov eax,vector
mov edx,matrix
call MMXAsm_VectorTransform
}
}
_asmcall void MMX_VectorTransformed(struct vectorch * v_result, struct vectorch const * v_parm, struct matrixch const * matrix)
{
_asm
{
mov eax,v_result
mov edx,v_parm
mov ecx,matrix
call MMXAsm_VectorTransformed
}
}
_asmcall void MMX_VectorTransformAndAdd(struct vectorch * vector, struct matrixch const * matrix, struct vectorch const * v_add)
{
_asm
{
mov eax,vector
mov edx,matrix
mov ecx,v_add
call MMXAsm_VectorTransformAndAdd
}
}
_asmcall void MMX_VectorTransformedAndAdd(struct vectorch * v_result, struct vectorch const * v_parm, struct matrixch const * matrix, struct vectorch const * v_add)
{
_asm
{
mov eax,v_result
mov edx,v_parm
mov ecx,matrix
mov ebx,v_add
call MMXAsm_VectorTransformedAndAdd
}
}
_asmcall signed MMX_VectorDot(struct vectorch const * v1, struct vectorch const * v2)
{
signed retval;
_asm
{
mov eax,v1
mov edx,v2
call MMXAsm_VectorDot
mov retval,eax
}
return retval;
}
_asmcall signed MMX_VectorDot16(struct vectorch const * v1, struct vectorch const * v2)
{
signed retval;
_asm
{
mov eax,v1
mov edx,v2
call MMXAsm_VectorDot16
mov retval,eax
}
return retval;
}
#else
#error "Unknown compiler"
#endif
/* Cross product? Mod? MatrixMultiply? */
/* globals */
extern int use_mmx_math;
/* inline functions - no call */
extern __int64 const mmx_sign_mask;
extern __int64 const mmx_one_fixed_h;
#ifdef __WATCOMC__
#pragma aux MMXInline_VectorDot = \
\
" movq mm0,[edx]" \
\
" movd mm2,[edx+08h]" \
" movq mm4,mm0" \
\
" pand mm4,mmx_sign_mask" \
" movq mm6,mm2" \
\
" movq mm1,[eax]" \
" paddd mm4,mm4" \
\
" movd mm3,[eax+08h]" \
" movq mm5,mm1" \
\
" pand mm6,mmx_sign_mask" \
" movq mm7,mm3" \
\
" pand mm5,mmx_sign_mask" \
" paddd mm6,mm6" \
\
" pand mm7,mmx_sign_mask" \
" paddd mm5,mm5" \
\
" paddd mm0,mm4" \
" paddd mm2,mm6" \
\
" paddd mm7,mm7" \
" movq mm4,mm2" \
\
" punpcklwd mm4,mm0" \
" paddd mm1,mm5" \
\
" punpckhwd mm2,mm0" \
" paddd mm3,mm7" \
\
" movq mm5,mm3" \
" punpckhwd mm3,mm1" \
\
" punpcklwd mm5,mm1" \
" movq mm0,mm2" \
\
" movq mm1,mm4" \
" pmaddwd mm0,mm3" \
\
" movq mm6,mm3" \
" psrlq mm3,32" \
\
" movq mm7,mm5" \
" punpckldq mm3,mm6" \
\
" pmaddwd mm1,mm5" \
" psrlq mm5,32" \
\
" punpckldq mm5,mm7" \
" pmaddwd mm2,mm3" \
\
" pmaddwd mm4,mm5" \
" movq mm3,mm0" \
\
" punpckldq mm0,mm1" \
\
" psubd mm0,mmx_one_fixed_h" \
" punpckhdq mm1,mm3" \
\
" psrad mm0,16" \
" paddd mm2,mm4" \
\
" pslld mm1,16" \
" paddd mm2,mm0" \
\
" paddd mm2,mm1" \
\
" movq mm1,mm2" \
" psrlq mm2,32" \
\
" paddd mm1,mm2" \
\
" movd eax,mm1" \
\
" emms" \
\
" inc eax" \
\
parm [eax] [edx] value [eax];
#pragma aux MMXInline_VectorDot16 = \
\
" movd mm0,[edx+08h]" \
\
" packssdw mm0,[edx]" \
\
" movd mm1,[eax+08h]" \
\
" packssdw mm1,[eax]" \
\
" pmaddwd mm0,mm1" \
\
" movq mm1,mm0" \
" psrlq mm0,32" \
\
" paddd mm0,mm1" \
\
" movd eax,mm0" \
\
" emms" \
\
parm [eax] [edx] value [eax];
#elif defined(_MSC_VER)
_asminline signed MMXInline_VectorDot(struct vectorch const * v1, struct vectorch const * v2)
{
signed retval;
_asm
{
mov edx,v1
mov eax,v2
movq mm0,[edx]
movd mm2,[edx+08h]
movq mm4,mm0
pand mm4,mmx_sign_mask
movq mm6,mm2
movq mm1,[eax]
paddd mm4,mm4
movd mm3,[eax+08h]
movq mm5,mm1
pand mm6,mmx_sign_mask
movq mm7,mm3
pand mm5,mmx_sign_mask
paddd mm6,mm6
pand mm7,mmx_sign_mask
paddd mm5,mm5
paddd mm0,mm4
paddd mm2,mm6
paddd mm7,mm7
movq mm4,mm2
punpcklwd mm4,mm0
paddd mm1,mm5
punpckhwd mm2,mm0
paddd mm3,mm7
movq mm5,mm3
punpckhwd mm3,mm1
punpcklwd mm5,mm1
movq mm0,mm2
movq mm1,mm4
pmaddwd mm0,mm3
movq mm6,mm3
psrlq mm3,32
movq mm7,mm5
punpckldq mm3,mm6
pmaddwd mm1,mm5
psrlq mm5,32
punpckldq mm5,mm7
pmaddwd mm2,mm3
pmaddwd mm4,mm5
movq mm3,mm0
punpckldq mm0,mm1
psubd mm0,mmx_one_fixed_h
punpckhdq mm1,mm3
psrad mm0,16
paddd mm2,mm4
pslld mm1,16
paddd mm2,mm0
paddd mm2,mm1
movq mm1,mm2
psrlq mm2,32
paddd mm1,mm2
movd retval,mm1
emms
}
return retval+1;
}
_asminline signed MMXInline_VectorDot16(struct vectorch const * v1, struct vectorch const * v2)
{
signed retval;
_asm
{
mov eax,v1
mov edx,v2
movd mm0,[edx+08h]
packssdw mm0,[edx]
movd mm1,[eax+08h]
packssdw mm1,[eax]
pmaddwd mm0,mm1
movq mm1,mm0
psrlq mm0,32
paddd mm0,mm1
movd retval,mm0
emms
}
return retval;
}
#else
#error "Unknown compiler"
#endif
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* SUPPORT_MMX */
#endif /* ! _included_mmx_math_h_ */

1434
src/win95/obchunk.cpp Normal file

File diff suppressed because it is too large Load diff

503
src/win95/obchunk.hpp Normal file
View file

@ -0,0 +1,503 @@
#ifndef _obchunk_hpp
#define _obchunk_hpp 1
#include "chunk.hpp"
#include "chnktype.hpp"
#include "mishchnk.hpp"
// object flags
#define OBJECT_FLAG_BASE_OBJECT 0x0000100
#define OBJECT_FLAG_MODULE_OBJECT 0x0000200
#define OBJECT_FLAG_PLACED_OBJECT 0x0000400
// Note these flags have to correspond with the ones used by ed_ob_type
// and AVP generator flags
#define OBJECT_FLAG_AVPGAMEMODEMARINE 0x00000800
#define OBJECT_FLAG_AVPGAMEMODEALIEN 0x00001000
#define OBJECT_FLAG_AVPGAMEMODEPREDATOR 0x00002000
#define OBJECT_FLAG_PLATFORMLOADSET 0x00004000
#define OBJECT_FLAG_PCLOAD 0x00008000
#define OBJECT_FLAG_PSXLOAD 0x00010000
#define OBJECT_FLAG_SATURNLOAD 0x00020000
#define OBJECT_FLAG_NOTDIFFICULTY1 0x00100000
#define OBJECT_FLAG_NOTDIFFICULTY2 0x00200000
#define OBJECT_FLAG_NOTDIFFICULTY3 0x00400000
class Shape_Chunk;
class Shape_Header_Chunk;
class Object_Header_Chunk;
// flags structure
struct object_flags
{
unsigned int locked : 1;
// add more flags here as they are needed
};
class VModule_Array_Chunk;
class Object_Chunk : public Lockable_Chunk_With_Children
{
public:
// constructor from buffer
Object_Chunk (Chunk_With_Children * parent,const char *, size_t);
// constructor from data
Object_Chunk (Chunk_With_Children * parent, ChunkObject &obj);
// destructor
virtual ~Object_Chunk();
const ChunkObject object_data;
Shape_Chunk * get_assoc_shape();
BOOL assoc_with_shape (Shape_Chunk *);
BOOL deassoc_with_shape (Shape_Chunk *);
Object_Header_Chunk * get_header();
BOOL inc_v_no();
BOOL same_and_updated(Object_Chunk &);
BOOL assoc_with_shape_no(File_Chunk *);
void update_my_chunkobject (ChunkObject &);
// functions for the locking functionality
BOOL file_equals (HANDLE &);
const char * get_head_id();
void set_lock_user(char *);
virtual void post_input_processing();
VModule_Array_Chunk * get_vmod_chunk();
// destroy object needs to go through all the other
// objects and delete itself from the VMAC
void destroy(File_Chunk *);
ObjectID CalculateID();
//program_object_index can be set by the program using the chunks , so you can find where
//the object has been put.
//I need it so that I can find out which module each object has been put into.
int program_object_index;
private:
friend class File_Chunk;
friend class Object_Header_Chunk;
ChunkObject * object_data_store;
};
///////////////////////////////////////////////
class Object_Header_Chunk : public Chunk
{
public:
// constructor from buffer
Object_Header_Chunk (Chunk_With_Children * parent, const char * pdata, size_t psize);
virtual size_t size_chunk ();
virtual BOOL output_chunk (HANDLE &);
virtual void fill_data_block (char * data_start);
const ChunkObject * const object_data;
virtual void prepare_for_output();
const char * get_lockuser()
{
return lock_user;
}
int flags;
private:
friend class Object_Chunk;
friend class Shape_Header_Chunk;
friend class RIF_File_Chunk;
friend class File_Chunk;
friend class Environment;
char lock_user[17];
int version_no;
int shape_id_no;
Shape_Chunk * associated_shape;
// constructor from data
Object_Header_Chunk (Object_Chunk * parent);
};
///////////////////////////////////////////////
// automatically constructed when Object_Chunks are constructed from
// data
class Object_Interface_Data_Chunk : public Chunk_With_Children
{
public:
// constructor from buffer
Object_Interface_Data_Chunk (Chunk_With_Children * parent,const char *, size_t);
private:
friend class Object_Chunk;
// constructor from Object_Chunks
Object_Interface_Data_Chunk (Object_Chunk * parent);
};
///////////////////////////////////////////////
class Object_Notes_Chunk : public Chunk
{
public:
Object_Notes_Chunk (Chunk_With_Children * parent,
const char * _data, size_t _data_size);
virtual ~Object_Notes_Chunk ();
virtual size_t size_chunk ()
{
chunk_size = (data_size + 12);
chunk_size += (4-chunk_size%4)%4;
return chunk_size;
}
virtual BOOL output_chunk (HANDLE &);
virtual void fill_data_block (char * data_start);
const size_t data_size;
const char * const data;
private:
char * data_store;
};
///////////////////////////////////////////////
class Object_Module_Data_Chunk : public Chunk_With_Children
{
public:
// constructor from Object_Chunks
Object_Module_Data_Chunk (Object_Chunk * parent)
: Chunk_With_Children (parent, "MODULEDT")
{}
// constructor from buffer
Object_Module_Data_Chunk (Chunk_With_Children * parent,const char *, size_t);
private:
friend class Object_Chunk;
friend class AI_Module_Master_Chunk;
friend class AI_Module_Slave_Chunk;
// constructor from buffer
Object_Module_Data_Chunk (Object_Chunk * parent,const char *, size_t);
};
///////////////////////////////////////////////
class VModule_Array_Chunk : public Chunk
{
public:
VModule_Array_Chunk (Object_Module_Data_Chunk * parent, VMod_Arr_Item * vma, int num_in_vma);
VModule_Array_Chunk (Chunk_With_Children* parent, const char * vmdata, size_t vmsize);
~VModule_Array_Chunk ();
int num_array_items;
VMod_Arr_Item * vmod_array;
virtual void fill_data_block (char *);
virtual size_t size_chunk ();
private:
friend class Object_Module_Data_Chunk;
};
///////////////////////////////////////////////
#if 0
class Adjacent_Modules_Chunk : public Chunk
{
public:
Adjacent_Modules_Chunk(Object_Module_Data_Chunk * parent, List<Adjacent_Module> aml)
: Chunk (parent, "ADJMDLST"), adjacent_modules_list (aml)
{}
List<Adjacent_Module> adjacent_modules_list;
virtual void fill_data_block (char *);
virtual size_t size_chunk ();
private:
friend class Object_Module_Data_Chunk;
Adjacent_Modules_Chunk(Object_Module_Data_Chunk * parent, const char * data, size_t size);
};
#endif
//a replacement for adjacent_modules_chunk
#define AdjacentModuleFlag_EntryPointSetByHand 0x00000001
#define AdjacentModuleFlag_InsideAdjacentModule 0x00000002
#define AdjacentModuleFlag_AdjacentModuleInsideMe 0x00000004
#define AdjacentModuleFlag_Vertical 0x00000008
class Adjacent_Module_Entry_Points_Chunk : public Chunk
{
public:
Adjacent_Module_Entry_Points_Chunk(Object_Module_Data_Chunk * parent, List<Adjacent_Module> aml)
: Chunk (parent, "ADJMDLEP"), adjacent_modules_list (aml)
{}
Adjacent_Module_Entry_Points_Chunk(Chunk_With_Children * parent, const char * data, size_t size);
List<Adjacent_Module> adjacent_modules_list;
virtual void fill_data_block (char *);
virtual size_t size_chunk ();
private:
friend class Object_Module_Data_Chunk;
};
///////////////////////////////////////////////
class Module_Flag_Chunk : public Chunk
{
public:
Module_Flag_Chunk(Object_Module_Data_Chunk * parent);
Module_Flag_Chunk(Chunk_With_Children* parent, const char * data, size_t );
virtual void fill_data_block(char*);
virtual size_t size_chunk()
{return chunk_size=20;}
int Flags;
int spare;
private:
friend class Object_Module_Data_Chunk;
};
///////////////////////////////////////////////
class Module_Zone_Chunk : public Chunk
{
public:
Module_Zone_Chunk(Object_Module_Data_Chunk * parent);
Module_Zone_Chunk(Chunk_With_Children* parent, const char * data, size_t );
virtual void fill_data_block(char*);
virtual size_t size_chunk()
{return chunk_size=20;}
int Zone;
int spare;
private:
friend class Object_Module_Data_Chunk;
};
///////////////////////////////////////////////
class Module_Acoustics_Chunk : public Chunk
{
public:
Module_Acoustics_Chunk(Object_Module_Data_Chunk * parent);
Module_Acoustics_Chunk(Chunk_With_Children* parent, const char * data, size_t );
virtual void fill_data_block(char*);
virtual size_t size_chunk()
{return chunk_size=24;}
int env_index;
float reverb;
int spare;
private:
friend class Object_Module_Data_Chunk;
};
///////////////////////////////////////////////
class Object_Project_Data_Chunk : public Chunk_With_Children
{
public:
// constructor from Object_Chunks
Object_Project_Data_Chunk (Object_Chunk * parent)
: Chunk_With_Children (parent, "OBJPRJDT")
{}
// constructor from buffer
Object_Project_Data_Chunk (Chunk_With_Children * const parent,const char *,const size_t);
private:
friend class Object_Chunk;
};
///////////////////////////////////////////////
struct ChunkTrackSection
{
ChunkQuat quat_start;
ChunkQuat quat_end;
ChunkVectorInt pivot_start;
ChunkVectorInt pivot_end;
ChunkVectorInt object_offset;
int time_for_section;
int spare;
};
#define TrackFlag_Loop 0x00000001
#define TrackFlag_PlayingAtStart 0x00000002
#define TrackFlag_LoopBackAndForth 0x00000004
#define TrackFlag_UseTrackSmoothing 0x00000008
#define TrackFlag_QuatProblemSorted 0x80000000
class Object_Track_Chunk2 : public Chunk
{
public:
Object_Track_Chunk2 (Object_Chunk * parent);
Object_Track_Chunk2 (Chunk_With_Children * parent,const char *, size_t);
~Object_Track_Chunk2();
int num_sections;
ChunkTrackSection * sections;
int flags;
int timer_start;
virtual void fill_data_block (char *);
virtual size_t size_chunk ();
private:
friend class Object_Chunk;
};
#define TrackSoundFlag_Loop 0x00000001
class Object_Track_Sound_Chunk : public Chunk
{
public :
Object_Track_Sound_Chunk(Chunk_With_Children* parent);
Object_Track_Sound_Chunk (Chunk_With_Children * const parent,const char *, size_t const);
~Object_Track_Sound_Chunk();
size_t size_chunk ();
void fill_data_block (char * data_start);
char* wav_name;
unsigned long inner_range;
unsigned long outer_range;
int max_volume;
int pitch;
int flags;
int index;
};
///////////////////////////////////////////////
struct AltObjectLocation
{
ChunkVectorInt position;
ChunkQuat orientation;
int spare1,spare2;
};
//chunk for storing list of possible alternate locations for an object
//use for placed objects and generators and possibly sounds
class Object_Alternate_Locations_Chunk : public Chunk
{
public :
Object_Alternate_Locations_Chunk(Chunk_With_Children* parent,const char* data, size_t);
Object_Alternate_Locations_Chunk(Chunk_With_Children* parent);
~Object_Alternate_Locations_Chunk();
void fill_data_block(char* data);
size_t size_chunk();
int num_locations;
AltObjectLocation* locations;
int group; //objects with the same group (other than 0) share the same die roll
int spare2;
};
#endif

84
src/win95/objedit.h Normal file
View file

@ -0,0 +1,84 @@
#include "Chunk.hpp"
#define VECTOR VECTORCH
struct ChunkMapBlock
{
char TemplateName[20];
char TemplateNotes[100];
int MapType;
int MapShape;
int MapFlags;
int MapFlags2;
int MapFlags3;
int MapCType;
int MapCGameType;
int MapCStrategyS;
int MapCStrategyL;
int MapInteriorType;
int MapLightType;
int MapMass;
VECTOR MapNewtonV;
VECTOR MapOrigin;
int MapViewType;
int MapVDBData;
int SimShapeList;
};
class Map_Block_Chunk : public Chunk
{
public:
virtual size_t size_chunk()
{
return (chunk_size=216);
}
virtual BOOL output_chunk (HANDLE &);
virtual void fill_data_block (char * data_start);
ChunkMapBlock map_data;
friend class Object_Project_Data_Chunk;
Map_Block_Chunk (Object_Project_Data_Chunk * parent)
:Chunk(parent,"MAPBLOCK")
{}
private:
//constructor from buffer
Map_Block_Chunk (Object_Project_Data_Chunk * parent,const char* data);
};
struct ChunkStrategy
{
char StrategyName[20];
char StrategyNotes[100];
int Strategy;
};
class Strategy_Chunk : public Chunk
{
public :
virtual size_t size_chunk()
{
return (chunk_size=136);
}
virtual BOOL output_chunk (HANDLE &);
virtual void fill_data_block (char * data_start);
ChunkStrategy strategy_data;
friend class Object_Project_Data_Chunk;
Strategy_Chunk(Object_Project_Data_Chunk *parent)
:Chunk(parent,"STRATEGY")
{}
private:
//constructor from buffer
Strategy_Chunk (Object_Project_Data_Chunk * parent,const char* data);
};

167
src/win95/oechunk.cpp Normal file
View file

@ -0,0 +1,167 @@
#if objedit
#include "Template.hpp"
#endif
#include "OEChunk.h"
#include "Chunk.hpp"
#ifdef cencon
#define new my_new
#endif
//macro for helping to force inclusion of chunks when using libraries
FORCE_CHUNK_INCLUDE_IMPLEMENT(oechunk)
extern Chunk *Parent_File;
RIF_IMPLEMENT_DYNCREATE("MAPBLOCK",Map_Block_Chunk)
Map_Block_Chunk::Map_Block_Chunk(Chunk_With_Children * parent,const char* data,size_t)
:Chunk(parent,"MAPBLOCK")
{
strncpy(map_data.TemplateName,data,20);
strncpy(map_data.TemplateNotes,data+20,100);
map_data.MapType=*((int*)(data+120));
map_data.MapShape=*((int*)(data+124));
map_data.MapFlags=*((int*)(data+128));
map_data.MapFlags2=*((int*)(data+132));
map_data.MapFlags3=*((int*)(data+136));
map_data.MapCType=*((int*)(data+140));
map_data.MapCGameType=*((int*)(data+144));
map_data.MapCStrategyS=*((int*)(data+148));
map_data.MapCStrategyL=*((int*)(data+152));
map_data.MapInteriorType=*((int*)(data+126));
map_data.MapLightType=*((int*)(data+160));
map_data.MapMass=*((int*)(data+164));
map_data.MapNewtonV.vx=*((int*)(data+168));
map_data.MapNewtonV.vy=*((int*)(data+172));
map_data.MapNewtonV.vz=*((int*)(data+176));
map_data.MapOrigin.vx=*((int*)(data+180));
map_data.MapOrigin.vy=*((int*)(data+184));
map_data.MapOrigin.vz=*((int*)(data+188));
map_data.MapViewType=*((int*)(data+192));
map_data.MapVDBData=*((int*)(data+196));
map_data.SimShapeList=*((int*)(data+200));
}
RIF_IMPLEMENT_DYNCREATE("STRATEGY",Strategy_Chunk)
Strategy_Chunk::Strategy_Chunk(Chunk_With_Children * parent,const char * data,size_t)
:Chunk(parent,"STRATEGY")
{
strncpy(strategy_data.StrategyName,data,20);
strncpy(strategy_data.StrategyNotes,data+20,100);
strategy_data.Strategy=*((int*)(data+120));
}
void Map_Block_Chunk::fill_data_block (char* data_start)
{
strncpy (data_start, identifier, 8);
data_start += 8;
*((int *) data_start) = chunk_size;
data_start += 4;
strncpy (data_start,map_data.TemplateName,20);
data_start+=20;
strncpy (data_start,map_data.TemplateNotes,100);
data_start+=100;
*((int*)data_start)=map_data.MapType;
data_start += 4;
*((int*)data_start)=map_data.MapShape;
data_start += 4;
*((int*)data_start)=map_data.MapFlags;
data_start += 4;
*((int*)data_start)=map_data.MapFlags2;
data_start += 4;
*((int*)data_start)=map_data.MapFlags3;
data_start += 4;
*((int*)data_start)=map_data.MapCType;
data_start += 4;
*((int*)data_start)=map_data.MapCGameType;
data_start += 4;
*((int*)data_start)=map_data.MapCStrategyS;
data_start+=4;
*((int*)data_start)=map_data.MapCStrategyL;;
data_start+=4;
*((int*)data_start)=map_data.MapInteriorType;
data_start+=4;
*((int*)data_start)=map_data.MapLightType;
data_start+=4;
*((int*)data_start)=map_data.MapMass;
data_start+=4;
*((int*)data_start)=map_data.MapNewtonV.vx;
data_start+=4;
*((int*)data_start)=map_data.MapNewtonV.vy;
data_start+=4;
*((int*)data_start)=map_data.MapNewtonV.vz;
data_start+=4;
*((int*)data_start)=map_data.MapOrigin.vx;
data_start+=4;
*((int*)data_start)=map_data.MapOrigin.vy;
data_start+=4;
*((int*)data_start)=map_data.MapOrigin.vz;
data_start+=4;
*((int*)data_start)=map_data.MapViewType;
data_start+=4;
*((int*)data_start)=map_data.MapVDBData;
data_start+=4;
*((int*)data_start)=map_data.SimShapeList;
}
void Strategy_Chunk::fill_data_block(char* data_start)
{
strncpy (data_start, identifier, 8);
data_start += 8;
*((int *) data_start) = chunk_size;
data_start += 4;
strncpy (data_start,strategy_data.StrategyName,20);
data_start+=20;
strncpy (data_start,strategy_data.StrategyNotes,100);
data_start+=100;
*((int*)data_start)=strategy_data.Strategy;
}
BOOL Map_Block_Chunk::output_chunk(HANDLE &hand)
{
unsigned long junk;
BOOL ok;
char * data_block;
data_block = this->make_data_block_from_chunk();
ok = WriteFile (hand, (long *) data_block, (unsigned long) chunk_size, &junk, 0);
delete [] data_block;
if (!ok) return FALSE;
return TRUE;
}
BOOL Strategy_Chunk::output_chunk(HANDLE &hand)
{
unsigned long junk;
BOOL ok;
char * data_block;
data_block = this->make_data_block_from_chunk();
ok = WriteFile (hand, (long *) data_block, (unsigned long) chunk_size, &junk, 0);
delete [] data_block;
if (!ok) return FALSE;
return TRUE;
}

99
src/win95/oechunk.h Normal file
View file

@ -0,0 +1,99 @@
#ifndef _oechunk_h_
#define _oechunk_h_ 1
#include "Chunk.hpp"
#include "obchunk.hpp"
#if objedit
#include "Template.hpp"
#endif
//#if engine
//#define VECTOR VECTORCH
//#endif
#if engine
#else
struct VECTORCH
{
int vx, vy, vz;
};
#endif
struct ChunkMapBlock
{
char TemplateName[20];
char TemplateNotes[100];
int MapType;
int MapShape;
int MapFlags;
int MapFlags2;
int MapFlags3;
int MapCType;
int MapCGameType;
int MapCStrategyS;
int MapCStrategyL;
int MapInteriorType;
int MapLightType;
int MapMass;
VECTORCH MapNewtonV;
VECTORCH MapOrigin;
int MapViewType;
int MapVDBData;
int SimShapeList;
};
class Map_Block_Chunk : public Chunk
{
public:
virtual size_t size_chunk()
{
return (chunk_size=216);
}
virtual BOOL output_chunk (HANDLE &);
virtual void fill_data_block (char * data_start);
ChunkMapBlock map_data;
friend class Object_Project_Data_Chunk;
Map_Block_Chunk (Object_Project_Data_Chunk * parent)
:Chunk(parent,"MAPBLOCK")
{}
//constructor from buffer
Map_Block_Chunk (Chunk_With_Children * parent,const char* data,size_t);
};
struct ChunkStrategy
{
char StrategyName[20];
char StrategyNotes[100];
int Strategy;
};
class Strategy_Chunk : public Chunk
{
public :
virtual size_t size_chunk()
{
return (chunk_size=136);
}
virtual BOOL output_chunk (HANDLE &);
virtual void fill_data_block (char * data_start);
ChunkStrategy strategy_data;
friend class Object_Project_Data_Chunk;
Strategy_Chunk(Object_Project_Data_Chunk *parent)
:Chunk(parent,"STRATEGY")
{}
//constructor from buffer
Strategy_Chunk (Chunk_With_Children * parent,const char* data,size_t);
};
#endif

54
src/win95/our_mem.c Normal file
View file

@ -0,0 +1,54 @@
#include "3dc.h"
#include <malloc.h>
#define UseLocalAssert No
#include "ourasert.h"
#if debug
int alloc_cnt = 0;
int deall_cnt = 0;
#endif
void *AllocMem(size_t __size);
void DeallocMem(void *__ptr);
/* Note: Never use AllocMem directly ! */
/* Instead use AllocateMem() which is a */
/* macro defined in mem3dc.h that allows */
/* for debugging info. */
void *AllocMem(size_t __size)
{
GLOBALASSERT(__size>0);
#if debug
alloc_cnt++;
#endif
return malloc(__size);
};
/* Note: Never use DeallocMem directly ! */
/* Instead use DeallocateMem() which is a */
/* macro defined in mem3dc.h that allows */
/* for debugging info. */
void DeallocMem(void *__ptr)
{
#if debug
deall_cnt++;
#endif
if(__ptr) free(__ptr);
#if debug
else {
textprint("ERROR - freeing null ptr\n");
WaitForReturn();
}
#endif
};

138
src/win95/ourasert.h Normal file
View file

@ -0,0 +1,138 @@
/*
This is our assert file for the Win95
platform, with Dave's global/local assert
distinctions.
*/
/*
Note that WaitForReturn now calls FlushTextprintBuffer
and FlipBuffers implicitly.
*/
/*
Modified 10th December 1996 by Dave Malcolm. Now can be set so that
functions are supplied by the project/platform to fire when an assertion
fires.
Also is set so that the compiler will generate an error message if you manage to
include the file more than once (with confusing definitons of UseLocalAssert);
this can be disabled.
*/
#ifdef _OURASERT
#if StopCompilationOnMultipleInclusions
#error OURASERT.H included more than once
#endif
#else
#define _OURASERT 1
#endif
#ifdef AVP_DEBUG_VERSION
#define ASSERT_SYSTEM_ON 1
#else
#define ASSERT_SYSTEM_ON 0
#endif
#if UseProjPlatAssert
/* New assertions system */
#ifdef __cplusplus
extern "C" {
#endif
int GlobalAssertFired(char* Filename, int LineNum, char* Condition);
int LocalAssertFired(char* Filename, int LineNum, char* Condition);
void ExitFired(char* Filename, int LineNum, int ExitCode);
#ifdef __cplusplus
};
#endif
#if ASSERT_SYSTEM_ON
#define GLOBALASSERT(x) \
(void)( (x) ? 1 : \
( \
GlobalAssertFired \
( \
__FILE__, \
__LINE__, \
#x \
) \
) \
)
#if UseLocalAssert
#define LOCALASSERT(x) \
(void)( (x) ? 1 : \
( \
LocalAssertFired \
( \
__FILE__, \
__LINE__, \
#x \
) \
) \
)
#else
#define LOCALASSERT(ignore)
#endif
#define exit(x) ExitFired(__FILE__,__LINE__,x)
#else
#define GLOBALASSERT(ignore) ((void)0)
#define LOCALASSERT(ignore) ((void)0)
#endif
#else
/* Old assertions system */
#define GlobalAssertCode 0xffff
#define LocalAssertCode 0xfffe
#if 0//debug
#define GLOBALASSERT(x) \
(void)((x) ? 1 : \
(textprint("\nGAF " #x "\nLINE %d\nFILE'%s'\n", \
__LINE__, __FILE__), WaitForReturn(), \
ExitSystem(), exit(GlobalAssertCode), \
0))
#if UseLocalAssert
#define LOCALASSERT(x) \
(void)((x) ? 1 : \
(textprint("\nLAF " #x "LINE %d\nFILE'%s'\n", \
__LINE__, __FILE__), WaitForReturn(), \
ExitSystem(), exit(LocalAssertCode), \
0))
#else
#define LOCALASSERT(ignore)
#endif
#else
#define GLOBALASSERT(ignore)
#define LOCALASSERT(ignore)
#endif
#endif

64
src/win95/pentime.h Normal file
View file

@ -0,0 +1,64 @@
/* pentime.h */
extern unsigned long int rdtsc_lo(void);
extern unsigned long int rdtsc_hi(void);
extern unsigned long int rdtsc_mid(void);
#define ProfileStart() \
{ \
int time = rdtsc_lo();
#define ProfileStop(x) \
textprint("%s %d\n",x,rdtsc_lo()-time); \
}
#pragma aux rdtsc_lo = \
"db 0fh, 31h" \
value [eax] \
modify [edx];
#pragma aux rdtsc_hi = \
"db 0fh, 31h" \
value [edx] \
modify [eax];
#pragma aux rdtsc_mid = \
"db 0fh, 31h" \
"shr eax, 10h" \
"shl edx, 10h" \
"add eax, edx" \
value [eax] \
modify [edx];
/* Test to see if we have a Pentium or not. Note that this test is reliable
* enough for a tools project (where we can put in an overide switch) but not
* for a released product.
*/
extern unsigned char Pentium(void);
#pragma aux Pentium = \
"pushfd" \
"pop eax" \
"or eax, 00200000h" \
"push eax" \
"popfd" \
"pushfd" \
"pop eax" \
"mov ecx, eax" \
"and eax, 00200000h" \
"cmp eax, 0" \
"je not_Pentium" \
"mov eax, ecx" \
"and eax, 0ffdfffffh" \
"push eax" \
"popfd" \
"pushfd" \
"pop eax" \
"and eax, 00200000h" \
"cmp eax, 0" \
"jne not_Pentium" \
"is_Pentium: mov al, 1" \
"jmp finish" \
"not_Pentium: mov al, 0" \
"finish: nop" \
value [al] \
modify [eax ecx]

369
src/win95/plat_shp.c Normal file
View file

@ -0,0 +1,369 @@
/*RWH moved to a seperate file*/
#include "3dc.h"
#include "module.h"
#include "inline.h"
#include "gameplat.h"
#include "gamedef.h"
#include "dynblock.h"
#include "dynamics.h"
#define UseLocalAssert No
#include "ourasert.h"
/* *
*
*
* * *
* * *
***
*
*/
/*KJL***********************************************
* Polygon Access Functions V1.0, 18:12:27 11/07/96 *
***********************************************KJL*/
int SetupPolygonAccess(DISPLAYBLOCK *objectPtr);
void AccessNextPolygon(void);
void GetPolygonVertices(struct ColPolyTag *polyPtr);
void GetPolygonNormal(struct ColPolyTag *polyPtr);
int SetupPolygonAccessFromShapeIndex(int shapeIndex);
/* the following are needed for morphing support */
#if SupportMorphing
extern MORPHDISPLAY MorphDisplay;
extern VECTORCH MorphedPts[];
#endif
VECTORCH *ShapePointsPtr;
int *ShapeNormalsPtr;
int *Shape2NormalsPtr;
char ShapeIsMorphed;
int **ItemArrayPtr;
POLYHEADER *PolyheaderPtr;
int SetupPolygonAccess(DISPLAYBLOCK *objectPtr)
{
SHAPEHEADER *shape1Ptr;
#if SupportMorphing
if (objectPtr->ObMorphCtrl) /* morphable object? */
{
VECTORCH *shape1PointsPtr;
VECTORCH *shape2PointsPtr;
/* Set up the morph data */
GetMorphDisplay(&MorphDisplay, objectPtr);
shape1Ptr = MorphDisplay.md_sptr1;
if(MorphDisplay.md_lerp == 0x0000)
{
ShapePointsPtr = (VECTORCH *)*shape1Ptr->points;
ShapeNormalsPtr = (int *) *(shape1Ptr->sh_normals);
ShapeIsMorphed=0;
}
else if(MorphDisplay.md_lerp == 0xffff)
{
SHAPEHEADER *shape2Ptr;
shape2Ptr = MorphDisplay.md_sptr2;
ShapePointsPtr = (VECTORCH *)*shape2Ptr->points;
ShapeNormalsPtr = (int *) *(shape2Ptr->sh_normals);
ShapeIsMorphed=0;
}
else
{
SHAPEHEADER *shape2Ptr;
shape2Ptr = MorphDisplay.md_sptr2;
shape1PointsPtr = (VECTORCH *)(*shape1Ptr->points);
shape2PointsPtr = (VECTORCH *)(*shape2Ptr->points);
/* you're going to need all the points so you might as well morph them all at once now */
{
int numberOfPoints = shape1Ptr->numpoints;
VECTORCH *morphedPointsPtr = (VECTORCH *) MorphedPts;
while(numberOfPoints--)
{
VECTORCH vertex1 = *shape1PointsPtr;
VECTORCH vertex2 = *shape2PointsPtr;
if( (vertex1.vx == vertex2.vx && vertex1.vy == vertex2.vy && vertex1.vz == vertex2.vz) )
{
*morphedPointsPtr = vertex1;
}
else
{
/* KJL 15:27:20 05/22/97 - I've changed this to speed things up, If a vertex
component has a magnitude greater than 32768 things will go wrong. */
morphedPointsPtr->vx = vertex1.vx + (((vertex2.vx-vertex1.vx)*MorphDisplay.md_lerp)>>16);
morphedPointsPtr->vy = vertex1.vy + (((vertex2.vy-vertex1.vy)*MorphDisplay.md_lerp)>>16);
morphedPointsPtr->vz = vertex1.vz + (((vertex2.vz-vertex1.vz)*MorphDisplay.md_lerp)>>16);
}
shape1PointsPtr++;
shape2PointsPtr++;
morphedPointsPtr++;
}
}
ShapePointsPtr = (VECTORCH *)MorphedPts;
ShapeNormalsPtr = (int *) *(shape1Ptr->sh_normals);
Shape2NormalsPtr = (int *) *(shape2Ptr->sh_normals);
ShapeIsMorphed=1;
}
ItemArrayPtr = (int **)shape1Ptr->items;
}
else /* not a morphing object */
#endif
{
shape1Ptr = GetShapeData(objectPtr->ObShape);
ShapePointsPtr = (VECTORCH *)(*shape1Ptr->points);
ShapeNormalsPtr = (int *)(*shape1Ptr->sh_normals);
ItemArrayPtr = (int **)shape1Ptr->items;
ShapeIsMorphed=0;
}
{
int *itemPtr = *ItemArrayPtr;
PolyheaderPtr = (POLYHEADER *) itemPtr;
}
return shape1Ptr->numitems;
}
void AccessNextPolygon(void)
{
int *itemPtr = *(ItemArrayPtr++);
PolyheaderPtr = (POLYHEADER *) itemPtr;
return;
}
void GetPolygonVertices(struct ColPolyTag *polyPtr)
{
int *vertexNumberPtr = &PolyheaderPtr->Poly1stPt;
polyPtr->PolyPoint[0] = *(ShapePointsPtr + *vertexNumberPtr++);
polyPtr->PolyPoint[1] = *(ShapePointsPtr + *vertexNumberPtr++);
polyPtr->PolyPoint[2] = *(ShapePointsPtr + *vertexNumberPtr++);
if (*vertexNumberPtr != Term)
{
polyPtr->PolyPoint[3] = *(ShapePointsPtr + *vertexNumberPtr);
polyPtr->NumberOfVertices=4;
}
else
{
polyPtr->NumberOfVertices=3;
}
return;
}
void GetPolygonNormal(struct ColPolyTag *polyPtr)
{
if (ShapeIsMorphed)
{
VECTORCH n1Ptr = *(VECTORCH*)(ShapeNormalsPtr + PolyheaderPtr->PolyNormalIndex);
VECTORCH n2Ptr = *(VECTORCH*)(Shape2NormalsPtr + PolyheaderPtr->PolyNormalIndex);
if( ((n1Ptr.vx == n2Ptr.vx)
&& (n1Ptr.vy == n2Ptr.vy)
&& (n1Ptr.vz == n2Ptr.vz))
|| (MorphDisplay.md_lerp == 0) )
{
polyPtr->PolyNormal = n1Ptr;
}
else if(MorphDisplay.md_lerp == 0xffff)
{
polyPtr->PolyNormal = n2Ptr;
}
else
{
VECTORCH *pointPtr[3];
int *vertexNumPtr = &PolyheaderPtr->Poly1stPt;
pointPtr[0] = (ShapePointsPtr + *vertexNumPtr++);
pointPtr[1] = (ShapePointsPtr + *vertexNumPtr++);
pointPtr[2] = (ShapePointsPtr + *vertexNumPtr);
MakeNormal
(
pointPtr[0],
pointPtr[1],
pointPtr[2],
&polyPtr->PolyNormal
);
}
}
else /* not morphed */
{
polyPtr->PolyNormal = *(VECTORCH*)(ShapeNormalsPtr + PolyheaderPtr->PolyNormalIndex);
/* KJL 20:55:36 05/14/97 - turned off for alpha */
#if 0
if( (polyPtr->PolyNormal.vx==0)
&&(polyPtr->PolyNormal.vy==0)
&&(polyPtr->PolyNormal.vz==0) )
{
textprint("shape data has zero normal\n");
}
#endif
}
return;
}
/*-----------------------Patrick 1/12/96--------------------------
I have added this function to initialise polygon access for a
module based on the shape index specified in its mapblock....
Specifically, this is for setting up location data for modules
during game initialisation, and so doesn't support morphing.
----------------------------------------------------------------*/
int SetupPolygonAccessFromShapeIndex(int shapeIndex)
{
SHAPEHEADER *shape1Ptr;
shape1Ptr = GetShapeData(shapeIndex);
ShapePointsPtr = (VECTORCH *)(*shape1Ptr->points);
ShapeNormalsPtr = (int *)(*shape1Ptr->sh_normals);
ItemArrayPtr = (int **)shape1Ptr->items;
ShapeIsMorphed=0;
{
int *itemPtr = *ItemArrayPtr;
PolyheaderPtr = (POLYHEADER *) itemPtr;
}
return shape1Ptr->numitems;
}
/*--------------------Patrick 17/12/96----------------------------
I have added some more shape data access functions......
PSX versions are required.
----------------------------------------------------------------*/
static VECTORCH patPointData;
static int patPolyVertexIndices[4];
static VECTORCH *patShapePointsPtr;
int SetupPointAccessFromShapeIndex(int shapeIndex)
{
SHAPEHEADER *shapePtr;
shapePtr = GetShapeData(shapeIndex);
patShapePointsPtr = (VECTORCH *)(*shapePtr->points);
return shapePtr->numpoints;
}
VECTORCH* AccessNextPoint(void)
{
patPointData = *patShapePointsPtr++;
return &patPointData;
}
VECTORCH* AccessPointFromIndex(int index)
{
patPointData = patShapePointsPtr[index];
return &patPointData;
}
/* KJL 18:51:08 21/11/98 - similiar function for polys */
POLYHEADER *AccessPolyFromIndex(int index)
{
int *itemPtr = *(ItemArrayPtr+index);
PolyheaderPtr = (POLYHEADER *) itemPtr;
return PolyheaderPtr;
}
void DestroyPolygon(int shapeIndex,int polyIndex)
{
SHAPEHEADER *shapePtr = GetShapeData(shapeIndex);
shapePtr->numitems--;
*(ItemArrayPtr+polyIndex) = *(ItemArrayPtr+shapePtr->numitems);
}
void ReplaceVertexInPolygon(int polyIndex, int oldVertex, int newVertex)
{
int *vertexNumberPtr;
int *itemPtr = *(ItemArrayPtr+polyIndex);
PolyheaderPtr = (POLYHEADER *) itemPtr;
vertexNumberPtr = &PolyheaderPtr->Poly1stPt;
while(*vertexNumberPtr != Term)
{
if (*vertexNumberPtr == oldVertex)
{
*vertexNumberPtr = newVertex;
}
vertexNumberPtr++;
}
{
VECTORCH newNormal;
VECTORCH *pointPtr[3];
int *vertexNumPtr = &PolyheaderPtr->Poly1stPt;
pointPtr[0] = (ShapePointsPtr + *vertexNumPtr++);
pointPtr[1] = (ShapePointsPtr + *vertexNumPtr++);
pointPtr[2] = (ShapePointsPtr + *vertexNumPtr);
MakeNormal
(
pointPtr[0],
pointPtr[1],
pointPtr[2],
&newNormal
);
*(VECTORCH*)(ShapeNormalsPtr + PolyheaderPtr->PolyNormalIndex)=newNormal;
}
}
VECTORCH *GetPolygonNormalFromIndex(void)
{
return (VECTORCH*)(ShapeNormalsPtr + PolyheaderPtr->PolyNormalIndex);
}
int *GetPolygonVertexIndices(void)
{
int *vertexNumberPtr = &PolyheaderPtr->Poly1stPt;
int numberOfVertices=0;
patPolyVertexIndices[3] = -1;
while(*vertexNumberPtr != Term)
{
patPolyVertexIndices[numberOfVertices++] = (*vertexNumberPtr);
vertexNumberPtr++;
}
return &patPolyVertexIndices[0];
}
/*--------------------Roxby 3/7/97----------------------------
I have added some more shape data access functions......
taken from PSX versions
----------------------------------------------------------------*/
void SetupPolygonFlagAccessForShape(SHAPEHEADER *shape)
{
}
int Request_PolyFlags(void *polygon)
{
POLYHEADER *poly = (POLYHEADER*)polygon;
return poly->PolyFlags;
}

11
src/win95/plat_shp.h Normal file
View file

@ -0,0 +1,11 @@
/* Plat_Shp.h */
extern void SetupPolygonFlagAccessForShape(SHAPEHEADER *shape);
extern int Request_PolyFlags(void *polygon);
extern int SetupPolygonAccess(DISPLAYBLOCK *objectPtr);
extern void AccessNextPolygon(void);
extern void GetPolygonVertices(struct ColPolyTag *polyPtr);
extern void GetPolygonNormal(struct ColPolyTag *polyPtr);
extern int SetupPolygonAccessFromShapeIndex(int shapeIndex);

939
src/win95/platform.h Normal file
View file

@ -0,0 +1,939 @@
#ifndef PLATFORM_INCLUDED
/*
Platform Specific Header Include
*/
#ifdef __cplusplus
extern "C" {
#endif
/*
Minimise header files to
speed compiles...
*/
#define WIN32_LEAN_AND_MEAN
/*
Standard windows functionality
*/
#include <windows.h>
#include <windowsx.h>
#include <winuser.h>
#include <mmsystem.h>
#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
/*
DirectX functionality
*/
#include "ddraw.h"
#include "d3d.h"
#include "dsound.h"
#include "dplay.h"
#include "dinput.h"
#include "dplobby.h"
//#include "fastfile.h"
#define platform_pc Yes
#define Saturn No
#define Hardware2dTextureClipping No
/*
Types
*/
typedef RECT RECT_AVP;
/* Watcom C 64-bit values */
typedef struct LONGLONGCH {
unsigned int lo32;
int hi32;
} LONGLONGCH;
/*
Sine and Cosine
*/
#define GetSin(a) sine[a]
#define GetCos(a) cosine[a]
/*
Available processor types
*/
typedef enum {
PType_OffBottomOfScale,
PType_486,
PType_Pentium,
PType_P6,
PType_PentiumMMX,
PType_Klamath,
PType_OffTopOfScale
} PROCESSORTYPES;
/*
VGA Palette Entry
*/
typedef struct vgapaletteentry {
unsigned char vga_r;
unsigned char vga_g;
unsigned char vga_b;
} VGAPALETTEENTRY;
extern void LoadAndChangeToPalette(char*);
/*
Video mode decsription (to be filled
in by DirectDraw callback).
*/
typedef struct videomodeinfo {
int Width; /* in pixels */
int Height; /* in pixels */
int ColourDepth; /* in bits per pixel */
} VIDEOMODEINFO;
/*
Maximum number of display modes
that could be detected on unknown
hardware.
*/
#define MaxAvailableVideoModes 100
/*
#defines, structures etc for
textprint system
*/
#define MaxMsgChars 100
#define MaxMessages 20
/* Font description */
#define CharWidth 8 /* In PIXELS, not bytes */
#define CharHeight 10 /* In PIXELS, not bytes */
#define CharVertSep (CharHeight + 0) /* In PIXELS, not bytes */
#define FontStart 33 // random squiggle in standard ASCII
#define FontEnd 127 // different random squiggle in standard ASCII
#define FontInvisValue 0x00 // value to be colour keyed out of font blit
typedef struct printqueueitem {
char text[MaxMsgChars];
int text_length;
int x;
int y;
} PRINTQUEUEITEM;
/* KJL 12:30:05 9/9/97 - new keyboard, mouse etc. enum */
enum KEY_ID
{
KEY_ESCAPE,
KEY_0,
KEY_1,
KEY_2,
KEY_3,
KEY_4,
KEY_5,
KEY_6,
KEY_7,
KEY_8,
KEY_9,
KEY_A,
KEY_B,
KEY_C,
KEY_D,
KEY_E,
KEY_F,
KEY_G,
KEY_H,
KEY_I,
KEY_J,
KEY_K,
KEY_L,
KEY_M,
KEY_N,
KEY_O,
KEY_P,
KEY_Q,
KEY_R,
KEY_S,
KEY_T,
KEY_U,
KEY_V,
KEY_W,
KEY_X,
KEY_Y,
KEY_Z,
KEY_LEFT,
KEY_RIGHT,
KEY_UP,
KEY_DOWN,
KEY_CR,
KEY_TAB,
KEY_INS,
KEY_DEL,
KEY_END,
KEY_HOME,
KEY_PAGEUP,
KEY_PAGEDOWN,
KEY_BACKSPACE,
KEY_COMMA,
KEY_FSTOP,
KEY_SPACE,
KEY_LEFTSHIFT,
KEY_RIGHTSHIFT,
KEY_LEFTALT,
KEY_RIGHTALT,
KEY_LEFTCTRL,
KEY_RIGHTCTRL,
KEY_CAPS,
KEY_NUMLOCK,
KEY_SCROLLOK,
KEY_NUMPAD0,
KEY_NUMPAD1,
KEY_NUMPAD2,
KEY_NUMPAD3,
KEY_NUMPAD4,
KEY_NUMPAD5,
KEY_NUMPAD6,
KEY_NUMPAD7,
KEY_NUMPAD8,
KEY_NUMPAD9,
KEY_NUMPADSUB,
KEY_NUMPADADD,
KEY_NUMPADDEL,
KEY_NUMPADENTER,
KEY_NUMPADDIVIDE,
KEY_NUMPADMULTIPLY,
KEY_LBRACKET,
KEY_RBRACKET,
KEY_SEMICOLON,
KEY_APOSTROPHE,
KEY_GRAVE,
KEY_BACKSLASH,
KEY_SLASH,
KEY_CAPITAL,
KEY_MINUS,
KEY_EQUALS,
KEY_LWIN,
KEY_RWIN,
KEY_APPS,
KEY_F1,
KEY_F2,
KEY_F3,
KEY_F4,
KEY_F5,
KEY_F6,
KEY_F7,
KEY_F8,
KEY_F9,
KEY_F10,
KEY_F11,
KEY_F12,
KEY_JOYSTICK_BUTTON_1,
KEY_JOYSTICK_BUTTON_2,
KEY_JOYSTICK_BUTTON_3,
KEY_JOYSTICK_BUTTON_4,
KEY_JOYSTICK_BUTTON_5,
KEY_JOYSTICK_BUTTON_6,
KEY_JOYSTICK_BUTTON_7,
KEY_JOYSTICK_BUTTON_8,
KEY_JOYSTICK_BUTTON_9,
KEY_JOYSTICK_BUTTON_10,
KEY_JOYSTICK_BUTTON_11,
KEY_JOYSTICK_BUTTON_12,
KEY_JOYSTICK_BUTTON_13,
KEY_JOYSTICK_BUTTON_14,
KEY_JOYSTICK_BUTTON_15,
KEY_JOYSTICK_BUTTON_16,
KEY_LMOUSE,
KEY_MMOUSE,
KEY_RMOUSE,
KEY_MOUSEBUTTON4,
KEY_MOUSEWHEELUP,
KEY_MOUSEWHEELDOWN,
// Dutch
KEY_ORDINAL,
KEY_LESSTHAN,
KEY_PLUS,
// French
KEY_RIGHTBRACKET,
KEY_ASTERISK,
KEY_DOLLAR,
KEY_U_GRAVE,
KEY_EXCLAMATION,
KEY_COLON,
// German
KEY_BETA,
KEY_A_UMLAUT,
KEY_O_UMLAUT,
KEY_U_UMLAUT,
KEY_HASH,
// Spanish
KEY_UPSIDEDOWNEXCLAMATION,
KEY_C_CEDILLA,
KEY_N_TILDE,
// accents & diacritics
KEY_DIACRITIC_GRAVE,
KEY_DIACRITIC_ACUTE,
KEY_DIACRITIC_CARET,
KEY_DIACRITIC_UMLAUT,
KEY_VOID=255, // used to indicate a blank spot in the key config
MAX_NUMBER_OF_INPUT_KEYS,
};
/*
Mouse handler modes (velocity mode is for
interfacing to input functions that need
to read the mouse velocity, e.g. WeRequest
functions, while poistion mode is for menus
and similar problems).
The initial mode is defined as a compiled in
global in game.c
*/
typedef enum {
MouseVelocityMode,
MousePositionMode
} MOUSEMODES;
/* Defines for the purpose of familiarity of name only */
#define LeftButton 0x0001
#define RightButton 0x0002
#define MiddleButton 0x0004
/*
Video Modes
*/
typedef enum {
VideoMode_DX_320x200x8,
VideoMode_DX_320x200x8T,
VideoMode_DX_320x200x15,
VideoMode_DX_320x240x8,
VideoMode_DX_640x480x8,
VideoMode_DX_640x480x8T,
VideoMode_DX_640x480x15,
VideoMode_DX_640x480x24,
VideoMode_DX_800x600x8,
VideoMode_DX_800x600x8T,
VideoMode_DX_800x600x15,
VideoMode_DX_800x600x24,
VideoMode_DX_1024x768x8,
VideoMode_DX_1024x768x8T,
VideoMode_DX_1024x768x15,
VideoMode_DX_1024x768x24,
VideoMode_DX_1280x1024x8,
VideoMode_DX_1280x1024x8T,
VideoMode_DX_1280x1024x15,
VideoMode_DX_1280x1024x24,
VideoMode_DX_1600x1200x8,
VideoMode_DX_1600x1200x8T,
VideoMode_DX_1600x1200x15,
VideoMode_DX_1600x1200x24,
MaxVideoModes
} VIDEOMODES;
#define MaxScreenWidth 1600 /* Don't get this wrong! */
/*
Max no of palettes -- at present there is NO
code for palette switching and ALL palette
calls within the DirectDraw interface system
run on palette 0
*/
#define MaxPalettes 4
/*
Video Mode Types
*/
typedef enum {
VideoModeType_8,
VideoModeType_15,
VideoModeType_24,
VideoModeType_8T
} VIDEOMODETYPES;
/*
Windows modes
*/
typedef enum {
WindowModeFullScreen,
WindowModeSubWindow
} WINDOWMODES;
typedef struct WinScaleXY {
float x;
float y;
} WINSCALEXY;
/*
Dubious hack for dubious
aspects of DirectDraw initialisation
*/
typedef enum {
/* Default */
NoRestartRequired,
/*
Characteristic of driver which
will not support changing to a different
bit depth without rebooting
*/
RestartDisplayModeNotAvailable,
/*
Characteristic of ModeX emulation leading
to no video memory being available because
of the need to cooperate with a large existing
GDI surface which cannot be reduced without a
reboot
*/
RestartOutOfVidMemForPrimary
} VIDEORESTARTMODES;
/*
Load modes for putting an image
in a DirectDraw surface --- either
do or do not deallocate the
system memory image, but always
keep the DirectDraw one
*/
typedef enum {
LoadModeDirectDrawOnly,
LoadModeFull
} IMAGELOADMODES;
/*
Direct3D driver modes
*/
typedef enum {
D3DSoftwareRGBDriver,
D3DSoftwareRampDriver,
D3DHardwareRGBDriver
} D3DMODES;
/*
Software scan draw request modes
*/
typedef enum {
RequestScanDrawDirectDraw,
RequestScanDrawSoftwareRGB,
RequestScanDrawRamp,
RequestScanDrawDefault
} SOFTWARESCANDRAWREQUESTMODES;
/*
Rasterisation request modes
*/
typedef enum {
RequestSoftwareRasterisation,
RequestDefaultRasterisation
} RASTERREQUESTMODES;
/*
Actual scan draw mode
*/
typedef enum {
ScanDrawDirectDraw,
ScanDrawD3DRamp,
ScanDrawD3DSoftwareRGB,
ScanDrawD3DHardwareRGB
} SCANDRAWMODES;
/*
Z buffering request modes
*/
typedef enum {
RequestZBufferNever,
RequestZBufferAlways,
RequestZBufferDefault
} ZBUFFERREQUESTMODES;
/*
Z buffering modes
*/
typedef enum {
ZBufferOn,
ZBufferWriteOnly,
ZBufferOff
} ZBUFFERMODES;
/*
Request modes for DirectX
memory usage
*/
typedef enum {
RequestSystemMemoryAlways,
RequestDefaultMemoryAllocation
} DXMEMORYREQUESTMODES;
/*
DirectX memory usage modes
*/
typedef enum {
SystemMemoryPreferred,
VideoMemoryPreferred
} DXMEMORYMODES;
/*
.BMP File header
*/
/*
Pack the header to 1 byte alignment so that the
loader works (John's code, still under test).
*/
#ifdef __WATCOMC__
#pragma pack (1)
#endif
typedef struct bmpheader {
unsigned short BMP_ID; /* Contains 'BM' */
int BMP_Size;
short BMP_Null1;
short BMP_Null2;
int BMP_Image; /* Byte offset of image start relative to offset 14 */
int BMP_HeadSize; /* Size of header (40 for Windows, 12 for OS/2) */
int BMP_Width; /* Width of image in pixels */
int BMP_Height; /* Height of image in pixels */
short BMP_Planes; /* Number of image planes (must be 1) */
short BMP_Bits; /* Number of bits per pixel (1,4,8 or 24) */
int BMP_Comp; /* Compression type */
int BMP_CSize; /* Size in bytes of compressed image */
int BMP_Hres; /* Horizontal resolution in pixels/meter */
int BMP_Vres; /* Vertical resolution in pixels/meter */
int BMP_Colours; /* Number of colours used, below (N) */
int BMP_ImpCols; /* Number of important colours */
} BMPHEADER;
#ifdef __WATCOMC__
#pragma pack (4)
#endif
/*
Types of texture files that can be
requested from the main D3D texture
loader.
*/
typedef enum {
TextureTypePGM,
TextureTypePPM
} TEXTUREFILETYPE;
/*
Windows initialisation modes.
See InitialiseWindowsSystem
in the default win_proj.cpp
for a full description.
*/
typedef enum {
WinInitFull,
WinInitChange
} WININITMODES;
/*
Triangle Array Limits etc.
*/
#define maxarrtriangles 7 /* Could be 6 if all shape data in triangles */
#define trianglesize (1 + 1 + 1 + 1 + (6 * 3) + 1) /* largest, could be 5*3 if no 3d texturing */
#define pta_max 9 /* Could be 8 if all shape data in triangles */
/* header + xy + terminator */
#define item_polygon_trianglesize (1 + 1 + 1 + 1 + (2 * 3) + 1)
/* header + xyi + terminator */
#define item_gouraudpolygon_trianglesize (1 + 1 + 1 + 1 + (3 * 3) + 1)
/* header + xyuv + terminator */
#define item_2dtexturedpolygon_trianglesize (1 + 1 + 1 + 1 + (4 * 3) + 1)
/* header + xyuvi + terminator */
#define item_gouraud2dtexturedpolygon_trianglesize (1 + 1 + 1 + 1 + (5 * 3) + 1)
/* header + xyuvw + terminator */
#define item_3dtexturedpolygon_trianglesize (1 + 1 + 1 + 1 + (5 * 3) + 1)
/* header + xyuvwi + terminator */
#define item_gouraud3dtexturedpolygon_trianglesize (1 + 1 + 1 + 1 + (6 * 3) + 1)
/*
Vertex sizes
For copying vertices from item list polygons to triangles
e.g.
Vertex 2 (x component) of the quad would be (for Item_Polygon)
q[2 * i_poly_vsize + i_vstart + ix]
WARNING: If the item format changes these MUST be updated
*/
#define vstart 4
#define poly_vsize 2
#define gpoly_vsize 3
#define t2poly_vsize 4
#define gt2poly_vsize 5
#define t3poly_vsize 5
#define gt3poly_vsize 6
/*
Triangle Array Structure
*/
typedef struct trianglearray {
int TA_NumTriangles;
int *TA_ItemPtr;
int *TA_TriangleArray[maxarrtriangles];
} TRIANGLEARRAY;
/*
Function prototypes
*/
/*
Windows functionality. Note current
DirectInput functions are also here since
they are really part of the Win32 multimedia
library.
*/
long GetWindowsTickCount(void);
void CheckForWindowsMessages(void);
BOOL ExitWindowsSystem(void);
BOOL InitialiseWindowsSystem(HANDLE hInstance, int nCmdShow, int WinInitMode);
void KeyboardHandlerKeyDown(WPARAM wParam);
void KeyboardHandlerKeyUp(WPARAM wParam);
void MouseVelocityHandler(UINT message, LPARAM lParam);
void MousePositionHandler(UINT message, LPARAM lParam);
int ReadJoystick(void);
int CheckForJoystick(void);
BOOL SpawnRasterThread();
BOOL WaitForRasterThread();
/* DirectDraw */
void finiObjects(void);
void GenerateDirectDrawSurface(void);
void LockSurfaceAndGetBufferPointer(void);
void UnlockSurface(void);
void finiObjects(void);
void ColourFillBackBuffer(int FillColour);
void ColourFillBackBufferQuad(int FillColour, int LeftX,
int TopY, int RightX, int BotY);
void FlipBuffers(void);
void BlitToBackBuffer(void* lpBackground, RECT* destRectPtr, RECT* srcRectPtr);
void BlitToBackBufferWithoutTearing(void* lpBackground, RECT* destRectPtr, RECT* srcRectPtr);
void BlitWin95Char(int x, int y, unsigned char toprint);
void ReleaseDDSurface(void* DDSurface);
BOOL InitialiseDirectDrawObject(void);
BOOL ChangeDirectDrawObject(void);
BOOL CheckForVideoModes(int TestVideoMode);
void finiObjectsExceptDD(void);
BOOL TestMemoryAccess(void);
int ChangePalette (unsigned char* NewPalette);
int GetAvailableVideoMemory(void);
void HandleVideoModeRestarts(HINSTANCE hInstance, int nCmdShow);
void* MakeBackdropSurface(void);
void ReleaseBackdropSurface(void);
void LockBackdropSurface(void);
void UnlockBackdropSurface(void);
void ComposeBackdropBackBuffer(void);
int GetSingleColourForPrimary(int Colour);
/*
DirectX functionality only available in
C++ under Watcom at present
*/
#ifdef __cplusplus
HRESULT CALLBACK EnumDisplayModesCallback(LPDDSURFACEDESC pddsd, LPVOID Context);
BOOL FAR PASCAL EnumDDObjectsCallback(GUID FAR* lpGUID, LPSTR lpDriverDesc,
LPSTR lpDriverName, LPVOID lpContext);
#if triplebuffer
/*
must be WINAPI to support Windows FAR PASCAL
calling convention. Must be HRESULT to support
enumeration return value. NOTE THIS FUNCTION
DOESN'T WORK (DOCS WRONG) AND TRIPLE BUFFERING
HAS BEEN REMOVED ANYWAY 'COS IT'S USELESS...
*/
HRESULT WINAPI InitTripleBuffers(LPDIRECTDRAWSURFACE lpdd,
LPDDSURFACEDESC lpsd, LPVOID lpc);
#endif
#endif
/* Direct 3D Immediate Mode Rasterisation Module */
BOOL InitialiseDirect3DImmediateMode(void);
BOOL LockExecuteBuffer(void);
BOOL UnlockExecuteBufferAndPrepareForUse(void);
BOOL BeginD3DScene(void);
BOOL EndD3DScene(void);
BOOL ExecuteBuffer(void);
BOOL RenderD3DScene(void);
void ReleaseDirect3D(void);
void WritePolygonToExecuteBuffer(int* itemptr);
void WriteGouraudPolygonToExecuteBuffer(int* itemptr);
void Write2dTexturedPolygonToExecuteBuffer(int* itemptr);
void WriteGouraud2dTexturedPolygonToExecuteBuffer(int* itemptr);
void Write3dTexturedPolygonToExecuteBuffer(int* itemptr);
void WriteGouraud3dTexturedPolygonToExecuteBuffer(int* itemptr);
void WriteBackdrop2dTexturedPolygonToExecuteBuffer(int* itemptr);
void WriteBackdrop3dTexturedPolygonToExecuteBuffer(int* itemptr);
void WriteEndCodeToExecuteBuffer(void);
void ReleaseD3DTexture(void* D3DTexture);
void ReleaseDirect3DNotDD(void);
void ReleaseDirect3DNotDDOrImages(void);
BOOL SetExecuteBufferDefaults(void);
void SelectD3DDriverAndDrawMode(void);
#if SUPPORT_MMX
void SelectMMXOptions(void);
#endif
BOOL TestInitD3DObject(void);
#if SupportZBuffering
BOOL CreateD3DZBuffer(void);
void FlushD3DZBuffer(void);
void WriteZBPolygonToExecuteBuffer(int* itemptr);
void WriteZBGouraudPolygonToExecuteBuffer(int* itemptr);
void WriteZB2dTexturedPolygonToExecuteBuffer(int* itemptr);
void WriteZBGouraud2dTexturedPolygonToExecuteBuffer(int* itemptr);
void WriteZB3dTexturedPolygonToExecuteBuffer(int* itemptr);
void WriteZBGouraud3dTexturedPolygonToExecuteBuffer(int* itemptr);
#endif
#ifdef __cplusplus
HRESULT WINAPI DeviceEnumerator(LPGUID lpGuid,
LPSTR lpDeviceDescription, LPSTR lpDeviceName,
LPD3DDEVICEDESC lpHWDesc, LPD3DDEVICEDESC lpHELDesc, LPVOID lpContext);
HRESULT CALLBACK TextureFormatsEnumerator
(LPDDSURFACEDESC lpDDSD, LPVOID lpContext);
#endif
/* KJL 11:28:31 9/9/97 - Direct Input prototypes */
BOOL InitialiseDirectInput(void);
void ReleaseDirectInput(void);
BOOL InitialiseDirectKeyboard();
void DirectReadKeyboard(void);
void ReleaseDirectKeyboard(void);
BOOL InitialiseDirectMouse();
void DirectReadMouse(void);
void ReleaseDirectMouse(void);
/*
Internal
*/
#ifdef AVP_DEBUG_VERSION
int textprint(const char* t, ...);
#else
#define textprint(ignore)
#endif
void MakePaletteShades(VGAPALETTEENTRY *vga_palptr, int hue, int pal_shades_per_hue);
void ConvertToDDPalette(unsigned char* src, unsigned char* dst, int length, int flags);
int textprintXY(int x, int y, const char* t, ...);
void LoadSystemFonts(char* fname);
void DisplayWin95String(int x, int y, unsigned char *buffer);
void WriteStringToTextBuffer(int x, int y, unsigned char *buffer);
void FlushTextprintBuffer(void);
void InitPrintQueue(void);
void InitJoysticks(void);
void ReadJoysticks(void);
int ChangeDisplayModes(HINSTANCE hInst, int nCmd,
int NewVideoMode, int NewWindowMode,
int NewZBufferMode, int NewRasterisationMode,
int NewSoftwareScanDrawMode, int NewDXMemoryMode);
int DeallocateAllImages(void);
int MinimizeAllImages(void);
int RestoreAllImages(void);
void ConvertDDToInternalPalette(unsigned char* src, unsigned char* dst, int length);
PROCESSORTYPES ReadProcessorType(void);
/* EXTERNS FOR GLOBALS GO HERE !!!!!! */
extern DDCAPS direct_draw_caps;
/*
Jake's image functions
*/
void * CopyD3DTexture(struct imageheader *iheader);
#ifdef MaxImageGroups
#if (MaxImageGroups > 1)
void SetCurrentImageGroup(unsigned int group);
int DeallocateCurrentImages(void);
#endif /* MaxImageGroups > 1 */
#endif /* defined(MaxImageGroups) */
/*
Project callbacks
*/
void ExitGame(void);
void ProjectSpecificBufferFlipPostProcessing();
void ProjectSpecificItemListPostProcessing();
#if optimiseflip
void ProcessProjectWhileWaitingToBeFlippable();
#endif
#ifdef __cplusplus
};
#endif
#define PLATFORM_INCLUDED
#endif

1475
src/win95/plspecfn.c Normal file

File diff suppressed because it is too large Load diff

Some files were not shown because too many files have changed in this diff Show more