t2 engine svn checkout

This commit is contained in:
loop 2024-01-07 04:36:33 +00:00
commit ff569bd2ae
988 changed files with 394180 additions and 0 deletions

10381
platformWin32/d3dgl.cc Normal file

File diff suppressed because it is too large Load diff

222
platformWin32/d3dgl.h Normal file
View file

@ -0,0 +1,222 @@
//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#ifndef _D3DGL_H_
#define _D3DGL_H_
#define D3D_OVERLOADS
#ifndef __D3DX_H__
#include "d3dx.h"
#endif
#ifndef _GLLIST_H_
#include "PlatformWin32/gllist.h"
#endif
#ifndef _PLATFORMGL_H_
#include "PlatformWin32/platformGL.h"
#endif
#define M_2PI (3.1415926535897932384626433 * 2.0)
#define mDegToRad(d) ((d*M_PI) / 180.0)
/* Multitexture extensions */
#define GL_TEXTURE0_SGIS 0x835E
#define GL_TEXTURE1_SGIS 0x835F
#define GL_TEXTURE2_SGIS 0x8360
#define GL_TEXTURE3_SGIS 0x8361
#define MAXGLTEXHANDLES 4096
struct QuakeVertex {
D3DVALUE x, y, z;
D3DVALUE nx, ny, nz;
D3DCOLOR color;
};
struct QuakeTVertex {
D3DVALUE x, y, z;
D3DVALUE nx, ny, nz;
D3DCOLOR color;
D3DVALUE tu, tv;
};
struct QuakeMTVertex {
D3DVALUE x, y, z;
D3DVALUE nx, ny, nz;
D3DCOLOR color;
D3DVALUE tu, tv, tu2, tv2;
};
struct QuakeFMTVertex {
D3DVALUE x, y, z;
D3DVALUE nx, ny, nz;
D3DCOLOR diffuse;
D3DCOLOR specular;
D3DVALUE tu, tv, tu2, tv2;
};
struct TransformedQuakeVertex {
D3DVALUE x, y, z, rhw;
D3DCOLOR color;
D3DVALUE tu, tv, tu2, tv2;
};
#define QUAKEVFMT (D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE)
#define QUAKETVFMT (D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_TEX1)
#define QUAKEMTVFMT (D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_TEX2)
#define QUAKEFMTVFMT (D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_TEX2 | D3DFVF_SPECULAR)
#define QUAKETRVFMT (D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX2)
#define VBUFSIZE 2048
#define MAXVERTSPERPRIM 128
#define RESPATH_QUAKE "Software\\Microsoft\\Quake"
struct TexInfo {
DWORD m_block;
DWORD m_dwStage;
BOOL m_capture;
GLint m_internalformat;
D3DX_SURFACEFORMAT m_fmt;
GLsizei m_width;
GLsizei m_height;
GLsizei m_oldwidth;
GLsizei m_oldheight;
LPDIRECTDRAWSURFACE7 m_ddsurf;
D3DTEXTUREMINFILTER m_minmode;
D3DTEXTUREMAGFILTER m_magmode;
D3DTEXTUREMIPFILTER m_mipmode;
D3DTEXTUREADDRESS m_addu, m_addv;
};
struct Globals {
// Cache Line 1
GLenum m_prim;
unsigned m_comp;
unsigned m_nfv[4];
unsigned m_vcnt[4];
// Cache Line 2
void *m_verts;
// Following always needs to be together
/********************************/
D3DVALUE m_nx, m_ny, m_nz;
D3DCOLOR m_color;
D3DVALUE m_tu, m_tv, m_tu2, m_tv2;
/********************************/
BOOL m_texturing;
BOOL m_mtex;
// Cache Line 3
LPDIRECT3DVERTEXBUFFER7 m_vbuf, m_tvbuf, m_mtvbuf, m_fmtvbuf;
LPDIRECT3DDEVICE7 m_d3ddev;
DWORD m_shaders[2][9];
int m_winWidth;
int m_winHeight;
GLint m_scix, m_sciy;
GLsizei m_sciw, m_scih;
GLint m_vwx, m_vwy;
GLsizei m_vww, m_vwh;
GLint m_lckfirst;
GLsizei m_lckcount;
HWND m_hwnd;
HDC m_hdc;
ID3DXContext *m_pD3DX;
D3DX_SURFACEFORMAT m_ddFourBitAlphaSurfFormat;
D3DX_SURFACEFORMAT m_ddEightBitAlphaSurfFormat;
D3DX_SURFACEFORMAT m_ddFiveBitSurfFormat;
D3DX_SURFACEFORMAT m_ddEightBitSurfFormat;
D3DX_SURFACEFORMAT m_ddLuminanceSurfFormat;
D3DX_SURFACEFORMAT m_ddAlphaSurfFormat;
D3DDEVICEDESC7 m_dd;
GLenum m_cullMode;
D3DTRANSFORMSTATETYPE m_matrixMode;
BOOL m_cullEnabled;
BOOL m_texHandleValid;
BOOL m_subsample;
BOOL m_usemtex;
BOOL m_usemipmap;
BOOL m_doFlip;
BOOL m_makeSquare;
BOOL m_scissoring;
BOOL m_updvwp;
BOOL m_usecolorary, m_usetexcoordary[2], m_usevertexary;
GLuint m_curstagebinding[2];
GLenum m_curtgt, m_client_active_texture_arb;
int m_blendmode[2];
D3DCOLOR m_clearColor;
GLclampd m_clearDepth;
const GLfloat *m_vertexary;
const void *m_colorary;
GLsizei m_numIndices;
WORD *m_wIndices;
const GLfloat *m_texcoordary[2];
LPDIRECTDRAWSURFACE7 m_curtex[2];
GLList<D3DMATRIX> m_matrixStack[3];
WNDPROC m_wndproc;
DWORD m_lod;
TexInfo m_tex[MAXGLTEXHANDLES]; // support upto MAXGLTEXHANDLES for the time being;
GLList<GLuint> m_freeTextures;
GLenum m_frontFace;
BOOL m_usenormalary;
const GLfloat *m_normalary;
DWORD m_normalstride;
DWORD m_texcoordstride[2];
DWORD m_vertexstride;
BOOL m_texgen[2];
GLint m_texgenmode[2];
GLfloat m_texgenplane[2][2][4];
D3DMATRIX m_inverseworld;
BOOL m_inversedirty;
BOOL m_objectdirty[2];
D3DCOLOR m_envcolor;
DWORD m_colorstride;
GLenum m_colortype;
D3DLIGHT7 m_lights[8];
GLfloat *m_spherecoords;
DWORD m_zbias;
BOOL m_usedirectional;
D3DMATRIX m_curtexmatrix;
BOOL m_usefogary;
D3DCOLOR m_fogcolor;
const GLfloat *m_fogary;
DWORD m_fogstride;
};
#ifndef M_PI
#define M_PI 3.1415926536
#endif
#define CEILING( A, B ) ( (A) % (B) == 0 ? (A)/(B) : (A)/(B)+1 )
/* To work around optimizer bug in MSVC4.1 */
#if defined(__WIN32__) && !defined(OPENSTEP)
void
dummy(GLuint j, GLuint k)
{
}
#else
#define dummy(J, K)
#endif
/* EXT_bgra */
#define GL_BGR 0x80E0
#define GL_BGRA 0x80E1
/* Errors */
#define GLU_NO_ERROR 0
#define GLU_ERROR 100103
#define GLU_INVALID_ENUM 100900
#define GLU_INVALID_VALUE 100901
#define GLU_OUT_OF_MEMORY 100902
/* GLU 1.1 and later */
#define GLU_VERSION 100800
#define GLU_EXTENSIONS 100801
#endif

346
platformWin32/gllist.h Normal file
View file

@ -0,0 +1,346 @@
//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#ifndef _GLLIST_H_
#define _GLLIST_H_
#include <iostream.h>
// forward class declarations
template<class Type> class GLListIter;
template<class Type> class GLListManip;
template<class Type> class GLLink {
// Private members
Type d_data;
GLLink<Type> *d_next_p;
// Links cannot be copied or assigned
GLLink(const GLLink<Type>&);
GLLink<Type>& operator=(const GLLink<Type>&);
// Public members
public:
// Construct & Destroy
inline GLLink(GLLink<Type> **addLinkPtr, const Type &data);
~GLLink() {}
// Modifiers
inline void setData(const Type &data);
inline void setNext(GLLink<Type> *link);
inline GLLink<Type>*& getNextRef(); // generally a bad practice
// Accessors
inline Type& getData();
inline GLLink<Type>* getNext() const;
};
template<class Type> class GLList {
// Private members
int d_length;
GLLink<Type> *d_head_p;
// Friends
friend class GLListIter<Type>;
friend class GLListManip<Type>;
// Public members
public:
// Construct & Destroy
GLList();
GLList(const GLList<Type>&);
~GLList();
// Modifiers
GLList<Type>& operator=(const GLList<Type> &list);
GLList<Type>& operator+=(const Type &i);
GLList<Type>& operator+=(const GLList<Type> &list);
GLList<Type>& prepend(const Type &i);
GLList<Type>& prepend(const GLList<Type> &list);
// Accessors
int length() const;
};
template<class Type> ostream& operator<<(ostream& o, const GLList<Type>& list);
template<class Type> class GLListIter {
// Private Data
GLLink<Type> *d_current_p;
// Public Members
public:
// Construct and Destroy
inline GLListIter(const GLList<Type> &list);
inline GLListIter(const GLListIter<Type> &iter);
~GLListIter() {}
// Modifiers
inline GLListIter<Type>& operator=(const GLListIter<Type> &iter);
inline void operator++();
// Accessors
inline operator const void* () const;
inline Type& operator()() const;
};
template<class Type> class GLListManip {
// Private Data
GLList<Type> *d_list_p;
GLLink<Type> **d_current_p;
// Links cannot be copied or assigned
GLListManip(const GLListManip<Type> &manip);
GLListManip<Type>& operator=(const GLListManip<Type> &manip);
// Public Members
public:
// Construct and Destroy
inline GLListManip(GLList<Type> *list);
~GLListManip() {}
// Modifiers
inline void operator++();
inline void insert (const Type &data);
inline void remove ();
// Accessors
inline operator const void *() const;
inline Type& operator()() const;
};
template<class Type> GLLink<Type>::GLLink(GLLink<Type> **addLinkPtr, const Type &data) : d_next_p(*addLinkPtr), d_data(data)
{
*addLinkPtr = this;
}
template<class Type> void GLLink<Type>::setData(const Type &data)
{
d_data = data;
}
template<class Type> void GLLink<Type>::setNext(GLLink<Type> *link)
{
d_next_p = link;
}
template<class Type> GLLink<Type>*& GLLink<Type>::getNextRef()
{
return d_next_p;
}
template<class Type> Type& GLLink<Type>::getData()
{
return d_data;
}
template<class Type> GLLink<Type>* GLLink<Type>::getNext() const
{
return d_next_p;
}
template<class Type> GLList<Type>::GLList() : d_head_p(0), d_length(0)
{
}
template<class Type> GLList<Type>::GLList(const GLList<Type>& list) : d_head_p(0)
{
GLListManip<Type> m(this);
GLListIter<Type> l(list);
while(l) {
m.insert(l());
++l;
++m;
}
}
template<class Type> GLList<Type>::~GLList()
{
GLListManip<Type> m(this);
while(m != 0)
m.remove();
}
template<class Type> GLList<Type>& GLList<Type>::operator=(const GLList<Type>& list)
{
GLListManip<Type> m(this);
GLListIter<Type> l(list);
if(this != &list) {
while(m)
m.remove();
while(l) {
m.insert(l());
++l;
++m;
}
}
return *this;
}
template<class Type> GLList<Type>& GLList<Type>::operator+=(const Type &i)
{
GLListManip<Type> m(this);
while(m)
++m;
m.insert(i);
return *this;
}
template<class Type> GLList<Type>& GLList<Type>::operator+=(const GLList<Type>& list)
{
unsigned i, s;
GLListIter<Type> l(list);
GLListManip<Type> m(this);
while(m)
++m;
s = list.d_length;
for(i = 0; i < s; ++i) {
m.insert(l());
++m;
++l;
}
return *this;
}
template<class Type> GLList<Type>& GLList<Type>::prepend(const Type &i)
{
GLListManip<Type> m(this);
m.insert(i);
return *this;
}
template<class Type> GLList<Type>& GLList<Type>::prepend(const GLList<Type> &list)
{
GLListIter<Type> l(list);
GLListManip<Type> m(this);
while(l) {
m.insert(l());
++m;
++l;
}
return *this;
}
template<class Type> int GLList<Type>::length() const
{
return d_length;
}
template<class Type> ostream& operator<<(ostream &o, const GLList<Type>& list)
{
GLListIter<Type> l(list);
o << "[ ";
while(l != 0) {
o << l();
o << " ";
++l;
}
return o << "]";
}
template<class Type> GLListIter<Type>::GLListIter(const GLList<Type> &list) : d_current_p(list.d_head_p)
{
}
template<class Type> GLListIter<Type>::GLListIter(const GLListIter<Type> &iter) : d_current_p(iter.d_current_p)
{
}
template<class Type> GLListIter<Type>& GLListIter<Type>::operator=(const GLListIter<Type> &iter)
{
d_current_p = iter.d_current_p;
return *this;
}
template<class Type> void GLListIter<Type>::operator++()
{
d_current_p = d_current_p -> getNext();
}
template<class Type> Type& GLListIter<Type>::operator()() const
{
return d_current_p -> getData();
}
template<class Type> GLListIter<Type>::operator const void* () const
{
return d_current_p;
}
template<class Type> GLListManip<Type>::GLListManip(GLList<Type> *list) : d_current_p(&(list -> d_head_p)), d_list_p(list)
{
}
template<class Type> void GLListManip<Type>::operator++()
{
d_current_p = &((*d_current_p) -> getNextRef());
}
template<class Type> void GLListManip<Type>::insert(const Type &data)
{
new GLLink<Type>(d_current_p, data);
++(d_list_p -> d_length);
}
template<class Type> void GLListManip<Type>::remove()
{
GLLink<Type> *t = *d_current_p;
*d_current_p = (*d_current_p) -> getNext();
delete t;
--(d_list_p -> d_length);
}
template<class Type> GLListManip<Type>::operator const void* () const
{
return *d_current_p;
}
template<class Type> Type& GLListManip<Type>::operator()() const
{
return (*d_current_p) -> getData();
}
#endif

148
platformWin32/platformAL.h Normal file
View file

@ -0,0 +1,148 @@
//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#ifndef _PLATFORMAL_H_
#define _PLATFORMAL_H_
#ifndef _PLATFORM_H_
#include "Platform/platform.h"
#endif
#define AL_NO_PROTOTYPES
#include <al/al.h>
#include <al/alc.h>
#include <al/alut.h>
// extra enums for win32/miles implementation
enum {
// error values
AL_CONTEXT_ALREADY_INSTANTIATED = 0xbaadf00d,
AL_ENVIRONMENT_ALREADY_INSTANTIATED,
AL_UNSUPPORTED,
AL_INVALID_BUFFER,
AL_ERROR,
// context extention
ALC_PROVIDER,
ALC_PROVIDER_COUNT,
ALC_PROVIDER_NAME,
ALC_SPEAKER,
ALC_SPEAKER_COUNT,
ALC_SPEAKER_NAME,
ALC_BUFFER_DYNAMIC_MEMORY_SIZE,
ALC_BUFFER_DYNAMIC_MEMORY_USAGE,
ALC_BUFFER_DYNAMIC_COUNT,
ALC_BUFFER_MEMORY_USAGE,
ALC_BUFFER_COUNT,
ALC_BUFFER_LATENCY,
// misc 3d params
AL_MIN_DISTANCE,
AL_MAX_DISTANCE,
AL_CONE_OUTER_GAIN,
// relative with pos(0,0,0) won't work for ambient sounds with miles
AL_SOURCE_AMBIENT,
AL_PAN,
// other extensions
AL_BUFFER_KEEP_RESIDENT,
AL_FORMAT_WAVE_EXT,
// Environment extensions:
AL_ENV_EFFECT_VOLUME_EXT,
AL_ENV_FLAGS_EXT,
AL_ENV_DAMPING_EXT,
AL_ENV_ENVIRONMENT_SIZE_EXT,
AL_ENV_ROOM_VOLUME_EXT,
};
enum {
// sample level environment:
AL_ENV_SAMPLE_REVERB_MIX_EXT = 0,
AL_ENV_SAMPLE_DIRECT_EXT,
AL_ENV_SAMPLE_DIRECT_HF_EXT,
AL_ENV_SAMPLE_ROOM_EXT,
AL_ENV_SAMPLE_ROOM_HF_EXT,
AL_ENV_SAMPLE_OBSTRUCTION_EXT,
AL_ENV_SAMPLE_OBSTRUCTION_LF_RATIO_EXT,
AL_ENV_SAMPLE_OCCLUSION_EXT,
AL_ENV_SAMPLE_OCCLUSION_LF_RATIO_EXT,
AL_ENV_SAMPLE_OCCLUSION_ROOM_RATIO_EXT,
AL_ENV_SAMPLE_ROOM_ROLLOFF_EXT,
AL_ENV_SAMPLE_AIR_ABSORPTION_EXT,
AL_ENV_SAMPLE_OUTSIDE_VOLUME_HF_EXT,
AL_ENV_SAMPLE_FLAGS_EXT,
AL_ENV_SAMPLE_COUNT,
};
// room types: same as miles/eax
enum {
AL_ENVIRONMENT_GENERIC = 0,
AL_ENVIRONMENT_PADDEDCELL,
AL_ENVIRONMENT_ROOM,
AL_ENVIRONMENT_BATHROOM,
AL_ENVIRONMENT_LIVINGROOM,
AL_ENVIRONMENT_STONEROOM,
AL_ENVIRONMENT_AUDITORIUM,
AL_ENVIRONMENT_CONCERTHALL,
AL_ENVIRONMENT_CAVE,
AL_ENVIRONMENT_ARENA,
AL_ENVIRONMENT_HANGAR,
AL_ENVIRONMENT_CARPETEDHALLWAY,
AL_ENVIRONMENT_HALLWAY,
AL_ENVIRONMENT_STONECORRIDOR,
AL_ENVIRONMENT_ALLEY,
AL_ENVIRONMENT_FOREST,
AL_ENVIRONMENT_CITY,
AL_ENVIRONMENT_MOUNTAINS,
AL_ENVIRONMENT_QUARRY,
AL_ENVIRONMENT_PLAIN,
AL_ENVIRONMENT_PARKINGLOT,
AL_ENVIRONMENT_SEWERPIPE,
AL_ENVIRONMENT_UNDERWATER,
AL_ENVIRONMENT_DRUGGED,
AL_ENVIRONMENT_DIZZY,
AL_ENVIRONMENT_PSYCHOTIC,
AL_ENVIRONMENT_COUNT
};
// declare OpenAL functions
#define AL_EXTENSION(ext_name) extern bool gDoesSupport_##ext_name;
#define AL_FUNCTION(fn_return,fn_name,fn_args) extern fn_return (FN_CDECL *fn_name)fn_args;
#define AL_EXT_FUNCTION(ext_name,fn_return,fn_name,fn_args) extern fn_return (FN_CDECL *fn_name)fn_args;
#ifndef _OPENALFN_H_
#include <openALFn.h>
//#include "OpenAL/win32/openALFn.h"
#endif
namespace Audio
{
bool libraryInit(const char *library);
void libraryInitExtensions();
void libraryShutdown();
inline bool doesSupportIASIG()
{
return gDoesSupport_AL_EXT_IASIG;
}
inline bool doesSupportDynamix()
{
return gDoesSupport_AL_EXT_DYNAMIX;
}
// helpers
F32 DBToLinear(F32 value);
F32 linearToDB(F32 value);
} // end namespace Audio
#endif // _H_PLATFORMAL_

1809
platformWin32/platformGL.h Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,90 @@
//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#ifndef _PLATFORMWIN32_H_
#define _PLATFORMWIN32_H_
#if defined(__MWERKS__)
# include <ansi_prefix.win32.h>
# include <stdio.h>
# include <string.h>
#else
# include <stdio.h>
# include <string.h>
#endif
#define NOMINMAX
// define this so that we can use WM_MOUSEWHEEL messages...
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0400
#endif
#include <windows.h>
#ifndef _PLATFORM_H_
#include "Platform/platform.h"
#endif
struct Win32PlatState
{
FILE *log_fp;
HINSTANCE hinstOpenGL;
HINSTANCE hinstGLU;
HINSTANCE hinstOpenAL;
HWND appWindow;
HDC appDC;
HINSTANCE appInstance;
HGLRC hGLRC;
DWORD processId;
S32 desktopBitsPixel;
S32 desktopWidth;
S32 desktopHeight;
U32 currentTime;
Win32PlatState();
};
extern Win32PlatState winState;
extern bool QGL_Init( const char *dllname_gl, const char *dllname_glu );
extern bool QGL_EXT_Init();
extern void QGL_Shutdown();
extern HWND CreateOpenGLWindow( U32 width, U32 height, bool fullScreen );
extern HWND CreateCurtain( U32 width, U32 height );
extern void CreatePixelFormat( PIXELFORMATDESCRIPTOR *pPFD, S32 colorBits, S32 depthBits, S32 stencilBits, bool stereo );
extern S32 ChooseBestPixelFormat( HDC hDC, PIXELFORMATDESCRIPTOR *pPFD );
extern void setModifierKeys( S32 modKeys );
extern S32 ( WINAPI * qwglSwapIntervalEXT )(S32 interval );
extern BOOL ( WINAPI * qwglGetDeviceGammaRamp3DFX )(HDC, LPVOID );
extern BOOL ( WINAPI * qwglSetDeviceGammaRamp3DFX )(HDC, LPVOID );
extern S32 ( WINAPI * qwglChoosePixelFormat )(HDC, CONST PIXELFORMATDESCRIPTOR *);
extern S32 ( WINAPI * qwglDescribePixelFormat) (HDC, S32, UINT, LPPIXELFORMATDESCRIPTOR);
extern S32 ( WINAPI * qwglGetPixelFormat )(HDC);
extern BOOL ( WINAPI * qwglSetPixelFormat )(HDC, S32, CONST PIXELFORMATDESCRIPTOR *);
extern BOOL ( WINAPI * qwglSwapBuffers )(HDC);
extern BOOL ( WINAPI * qwglCopyContext )(HGLRC, HGLRC, UINT);
extern HGLRC ( WINAPI * qwglCreateContext )(HDC);
extern HGLRC ( WINAPI * qwglCreateLayerContext )(HDC, S32);
extern BOOL ( WINAPI * qwglDeleteContext )(HGLRC);
extern HGLRC ( WINAPI * qwglGetCurrentContext )(VOID);
extern HDC ( WINAPI * qwglGetCurrentDC )(VOID);
extern PROC ( WINAPI * qwglGetProcAddress )(LPCSTR);
extern BOOL ( WINAPI * qwglMakeCurrent )(HDC, HGLRC);
extern BOOL ( WINAPI * qwglShareLists )(HGLRC, HGLRC);
extern BOOL ( WINAPI * qwglUseFontBitmaps )(HDC, DWORD, DWORD, DWORD);
extern BOOL ( WINAPI * qwglUseFontOutlines )(HDC, DWORD, DWORD, DWORD, FLOAT, FLOAT, S32, LPGLYPHMETRICSFLOAT);
extern BOOL ( WINAPI * qwglDescribeLayerPlane )(HDC, S32, S32, UINT, LPLAYERPLANEDESCRIPTOR);
extern S32 ( WINAPI * qwglSetLayerPaletteEntries )(HDC, S32, S32, S32, CONST COLORREF *);
extern S32 ( WINAPI * qwglGetLayerPaletteEntries )(HDC, S32, S32, S32, COLORREF *);
extern BOOL ( WINAPI * qwglRealizeLayerPalette )(HDC, S32, BOOL);
extern BOOL ( WINAPI * qwglSwapLayerBuffers )(HDC, UINT);
#endif //_PLATFORMWIN32_H_

View file

@ -0,0 +1,37 @@
// for the moment, this seems to be the best roundup of
// the npatch extensions on the PC.
#ifndef GL_ATI_pn_triangles
#define GL_ATI_pn_triangles 1
#define GL_PN_TRIANGLES_ATI 0x87F0
#define GL_MAX_PN_TRIANGLES_TESSELATION_LEVEL_ATI 0x87F1
#define GL_PN_TRIANGLES_POINT_MODE_ATI 0x87F2
#define GL_PN_TRIANGLES_NORMAL_MODE_ATI 0x87F3
#define GL_PN_TRIANGLES_TESSELATION_LEVEL_ATI 0x87F4
#define GL_PN_TRIANGLES_POINT_MODE_LINEAR_ATI 0x87F5
#define GL_PN_TRIANGLES_POINT_MODE_CUBIC_ATI 0x87F6
#define GL_PN_TRIANGLES_NORMAL_MODE_LINEAR_ATI 0x87F7
#define GL_PN_TRIANGLES_NORMAL_MODE_QUADRATIC_ATI 0x87F8
typedef void (APIENTRY *PFNGLPNTRIANGLESIATIPROC)(GLenum pname, GLint param);
typedef void (APIENTRY *PFNGLPNTRIANGLESFATIPROC)(GLenum pname, GLfloat param);
#endif
#define GL_NPATCH_EXT_STRING "GL_ATI_pn_triangles"
#define GL_NPATCH_SETINT_STRING "glPNTrianglesiATI"
typedef PFNGLPNTRIANGLESIATIPROC PFNNPatchSetInt;
#define GETINT_NPATCH_MAX_LEVEL GL_MAX_PN_TRIANGLES_TESSELATION_LEVEL_ATI
#define GL_NPATCH_FLAG GL_PN_TRIANGLES_ATI
#define GL_NPATCH_LOD GL_PN_TRIANGLES_TESSELATION_LEVEL_ATI
#define SETINT_NPATCH_POINTINTERP GL_PN_TRIANGLES_POINT_MODE_ATI
#define SETINT_NPATCH_NORMALINTERP GL_PN_TRIANGLES_NORMAL_MODE_ATI
#define NPATCH_POINTINTERP_MIN GL_PN_TRIANGLES_POINT_MODE_LINEAR_ATI
#define NPATCH_POINTINTERP_MAX GL_PN_TRIANGLES_POINT_MODE_CUBIC_ATI
#define NPATCH_NORMALINTERP_MIN GL_PN_TRIANGLES_NORMAL_MODE_LINEAR_ATI
#define NPATCH_NORMALINTERP_MAX GL_PN_TRIANGLES_NORMAL_MODE_QUADRATIC_ATI

338
platformWin32/winAsmBlit.cc Normal file
View file

@ -0,0 +1,338 @@
//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#include "terrain/terrData.h"
#include "Math/mMath.h"
#include "dgl/dgl.h"
#include "dgl/gBitmap.h"
#include "terrain/terrRender.h"
#if !defined(__MWERKS__) && defined(_MSC_VER)
#define asm _asm
#endif
//--------------------------------------------------------------------------
//void terrMipBlit_asm(U16 *dest, U32 destStride, U32 squareSize, const U8 *sourcePtr, U32 sourceStep, U32 sourceRowAdd)
//{
// //for(U32 k = 0; k < squareSize; k++)
// //{
// // for(U32 l = 0; l < squareSize; l++)
// // {
// // dest[l] = *((U16 *) sourcePtr);
// // sourcePtr += sourceStep;
// // }
// // dest -= destStride;
// // sourcePtr += sourceRowAdd;
// //}
// if(sourceStep == 2)
// {
// destStride <<= 1;
// sourceRowAdd += squareSize << 1;
// asm
// {
// push eax
// push ebx
// push ecx
// push edx
// push edi
// push esi
//
// mov edx, squareSize
// mov edi, dest
// mov esi, sourcePtr
// shr edx, 1
// mov ecx, 0
// mov ebx, 0
// pixelLoop2:
// mov eax, [esi+ebx*4]
// mov [edi+ebx*4], eax
// inc ebx
// cmp ebx, edx
// jnz pixelLoop2
//
// mov ebx, 0
// inc ecx
// sub edi, destStride
// add esi, sourceRowAdd
// cmp ecx, squareSize
// jl pixelLoop2
//
// pop esi
// pop edi
// pop edx
// pop ecx
// pop ebx
// pop eax
// }
// }
// else if(sourceStep == -2)
// {
// destStride <<= 1;
// asm
// {
// push eax
// push ebx
// push ecx
// push edx
// push edi
// push esi
//
// mov edx, squareSize
// mov edi, dest
// mov esi, sourcePtr
// shr edx, 1
// mov ecx, 0
// mov ebx, 0
// pixelLoopNeg2:
// mov eax, [esi-2]
// sub esi, 4
// ror eax, 16
// mov [edi+ebx*4], eax
// inc ebx
// cmp ebx, edx
// jnz pixelLoopNeg2
//
// mov ebx, 0
// inc ecx
// sub edi, destStride
// add esi, sourceRowAdd
// cmp ecx, squareSize
// jl pixelLoopNeg2
//
// pop esi
// pop edi
// pop edx
// pop ecx
// pop ebx
// pop eax
// }
// }
// else
// {
// destStride = (destStride + squareSize) << 1;
// asm
// {
// push eax
// push ebx
// push ecx
// push edx
// push edi
// push esi
//
// mov eax, squareSize
// mov edi, dest
// mov esi, sourcePtr
// lea edx, [edi + eax * 2]
// mov ecx, 0 // row index
// mov ebx, sourceStep
// pixelLoop:
// mov ax, [esi+ebx]
// shl eax, 16
// add edi, 4
// mov ax, [esi]
// lea esi, [esi+ebx*2]
// mov [edi-4], eax
// cmp edi, edx
// jnz pixelLoop
//
// inc ecx
// sub edi, destStride
// mov eax, squareSize
// add esi, sourceRowAdd
// lea edx, [edi + eax * 2]
// cmp ecx, squareSize
// jl pixelLoop
//
// pop esi
// pop edi
// pop edx
// pop ecx
// pop ebx
// pop eax
// }
// }
//}
//--------------------------------------------------------------------------
void bitmapExtrude5551_asm(const void *srcMip, void *mip, U32 height, U32 width)
{
const U16 *src = (const U16 *) srcMip;
U16 *dst = (U16 *) mip;
U32 stride = width << 1;
for(U32 y = 0; y < height; y++)
{
for(U32 x = 0; x < width; x++)
{
U32 a = src[0];
U32 b = src[1];
U32 c = src[stride];
U32 d = src[stride+1];
dst[x] = ((((a >> 11) + (b >> 11) + (c >> 11) + (d >> 11)) >> 2) << 11) |
((( ((a >> 6) & 0x1f) + ((b >> 6) & 0x1f) + ((c >> 6) & 0x1f) + ((d >> 6) & 0x1F) ) >> 2) << 6) |
((( ((a >> 1) & 0x1F) + ((b >> 1) & 0x1F) + ((c >> 1) & 0x1f) + ((d >> 1) & 0x1f)) >> 2) << 1);
src += 2;
}
src += stride;
dst += width;
}
}
#ifndef __BORLANDC__
//--------------------------------------------------------------------------
void bitmapExtrudeRGB_mmx(const void *srcMip, void *mip, U32 srcHeight, U32 srcWidth)
{
if (srcHeight == 1 || srcWidth == 1) {
bitmapExtrudeRGB_c(srcMip, mip, srcHeight, srcWidth);
return;
}
U32 width = srcWidth >> 1;
U32 height = srcHeight >> 1;
if (width <= 1)
{
bitmapExtrudeRGB_c(srcMip, mip, srcHeight, srcWidth);
return;
}
U64 ZERO = 0x0000000000000000;
const U8 *src = (const U8 *) srcMip;
U8 *dst = (U8 *) mip;
U32 srcStride = (width << 1) * 3;
U32 dstStride = width * 3;
for(U32 y = 0; y < height; y++)
{
asm
{
mov eax, src
mov ebx, eax
add ebx, srcStride
mov ecx, dst
mov edx, width
//--------------------------------------
row_loop:
punpcklbw mm0, [eax]
psrlw mm0, 8
punpcklbw mm1, [eax+3]
psrlw mm1, 8
paddw mm0, mm1
punpcklbw mm1, [ebx]
psrlw mm1, 8
paddw mm0, mm1
punpcklbw mm1, [ebx+3]
psrlw mm1, 8
paddw mm0, mm1
psrlw mm0, 2
//pxor mm1, mm1
packuswb mm0, ZERO // mm1
movd [ecx], mm0
add eax, 6
add ebx, 6
add ecx, 3
dec edx
jnz row_loop
}
src += srcStride + srcStride; // advance to next line
dst += dstStride;
}
asm
{
emms
}
}
//--------------------------------------------------------------------------
void bitmapConvertRGB_to_5551_mmx(U8 *src, U32 pixels)
{
U64 MULFACT = 0x0008200000082000; // RGB quad word multiplier
U64 REDBLUE = 0x00f800f800f800f8; // Red-Blue mask
U64 GREEN = 0x0000f8000000f800; // Green mask
U64 ALPHA = 0x0000000000010001; // 100% Alpha mask
U64 ZERO = 0x0000000000000000;
U32 evenPixels = pixels >> 1; // the MMX loop can only do an even number
U32 oddPixels = pixels & 1; // of pixels since it processes 2 at a time
U16 *dst = (U16*)src;
if (evenPixels)
{
asm
{
mov eax, src // YES, src = dst at start
mov ebx, dst // convert image in place
mov edx, evenPixels
pixel_loop2:
movd mm0, [eax] // get first 24-bit pixel
movd mm1, [eax+3] // get second 24-bit pixel
punpckldq mm0, mm1 // put second in high dword
movq mm1, mm0 // save the original data
pand mm0, REDBLUE // mask out all but the 5MSBits of red and blue
pmaddwd mm0, MULFACT // multiply each word by
// 2**13, 2**3, 2**13, 2**3 and add results
pand mm1, GREEN // mask out all but the 5MSBits of green
por mm0, mm1 // combine the red, green, and blue bits
psrld mm0, 6 // shift into position
packssdw mm0, ZERO // pack into single dword
pslld mm0, 1 // shift into final position
por mm0, ALPHA // add the alpha bit
movd [ebx], mm0
add eax, 6
add ebx, 4
dec edx
jnz pixel_loop2
mov src, eax
mov dst, ebx
emms
}
}
if (oddPixels)
{
U32 r = src[0] >> 3;
U32 g = src[1] >> 3;
U32 b = src[2] >> 3;
*dst = (b << 1) | (g << 6) | (r << 11) | 1;
}
}
#endif
//--------------------------------------------------------------------------
void PlatformBlitInit()
{
bitmapExtrude5551 = bitmapExtrude5551_asm;
bitmapExtrudeRGB = bitmapExtrudeRGB_c;
if (Platform::SystemInfo.processor.properties & CPU_PROP_MMX)
{
#ifndef __BORLANDC__
bitmapExtrudeRGB = bitmapExtrudeRGB_mmx;
bitmapConvertRGB_to_5551 = bitmapConvertRGB_to_5551_mmx;
#endif
}
// terrMipBlit = terrMipBlit_asm;
}

280
platformWin32/winCPUInfo.cc Normal file
View file

@ -0,0 +1,280 @@
//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#include "platform/platform.h"
#include "platformWIN32/platformWin32.h"
#include "console/console.h"
#include "core/stringTable.h"
#include <math.h>
Platform::SystemInfo_struct Platform::SystemInfo;
extern void PlatformBlitInit();
void Processor::init()
{
// Reference:
// www.cyrix.com
// www.amd.com
// www.intel.com
// http://developer.intel.com/design/PentiumII/manuals/24512701.pdf
Platform::SystemInfo.processor.type = CPU_X86Compatible;
Platform::SystemInfo.processor.name = StringTable->insert("Unknown x86 Compatible");
Platform::SystemInfo.processor.mhz = 0;
Platform::SystemInfo.processor.properties = CPU_PROP_C;
#ifndef __BORLANDC__
char vendor[13] = {0,};
U32 properties = 0;
U32 processor = 0;
enum
{
BIT_FPU = (1<<0),
BIT_RDTSC = (1<<4),
BIT_MMX = (1<<23),
BIT_SSE = (1<<25),
BIT_3DNOW = (1<<31),
};
__asm
{
//--------------------------------------
// is CPUID supported
push ebx
push edx
push ecx
pushfd
pushfd // save EFLAGS to stack
pop eax // move EFLAGS into EAX
mov ebx, eax
xor eax, 0x200000 // flip bit 21
push eax
popfd // restore EFLAGS
pushfd
pop eax
cmp eax, ebx
jz EXIT // doesn't support CPUID instruction
//--------------------------------------
// Get Vendor Informaion using CPUID eax==0
xor eax, eax
cpuid
mov DWORD PTR vendor, ebx
mov DWORD PTR vendor+4, edx
mov DWORD PTR vendor+8, ecx
// get Generic Extended CPUID info
mov eax, 1
cpuid // eax=1, so cpuid queries feature information
and eax, 0x0ff0
mov processor, eax // just store the model bits
mov properties, edx
// Want to check for 3DNow(tm). Need to see if extended cpuid functions present.
mov eax, 0x80000000
cpuid
cmp eax, 0x80000000
jbe MAYBE_3DLATER
mov eax, 0x80000001
cpuid
and edx, 0x80000000 // 3DNow if bit 31 set -> put bit in our properties
or properties, edx
MAYBE_3DLATER:
EXIT:
popfd
pop ecx
pop edx
pop ebx
}
Platform::SystemInfo.processor.properties |= (properties & BIT_FPU) ? CPU_PROP_FPU : 0;
Platform::SystemInfo.processor.properties |= (properties & BIT_RDTSC) ? CPU_PROP_RDTSC : 0;
Platform::SystemInfo.processor.properties |= (properties & BIT_MMX) ? CPU_PROP_MMX : 0;
//--------------------------------------
if (dStricmp(vendor, "GenuineIntel") == 0)
{
Platform::SystemInfo.processor.properties |= (properties & BIT_SSE) ? CPU_PROP_SSE : 0;
switch (processor & 0xf00)
{
case 0x600:
switch(processor & 0xf0)
{
case 0x10:
Platform::SystemInfo.processor.type = CPU_Intel_PentiumII;
Platform::SystemInfo.processor.name = StringTable->insert( "Intel Pentium Pro" );
break;
case 0x30:
case 0x50:
case 0x60:
Platform::SystemInfo.processor.type = CPU_Intel_PentiumII;
Platform::SystemInfo.processor.name = StringTable->insert( "Intel Pentium II" );
break;
case 0x70:
case 0x80:
case 0xa0:
Platform::SystemInfo.processor.type = CPU_Intel_PentiumIII;
Platform::SystemInfo.processor.name = StringTable->insert( "Intel Pentium III" );
break;
default:
Platform::SystemInfo.processor.type = CPU_Intel_PentiumII;
Platform::SystemInfo.processor.name = StringTable->insert( "Intel (unknown, PPro family)" );
break;
}
break;
case 0x500:
Platform::SystemInfo.processor.type = CPU_Intel_Pentium;
Platform::SystemInfo.processor.name = StringTable->insert("Intel Pentium");
break;
default:
Platform::SystemInfo.processor.type = CPU_Intel_Unknown;
Platform::SystemInfo.processor.name = StringTable->insert("Intel (unknown)");
break;
}
}
//--------------------------------------
else
if (dStricmp(vendor, "AuthenticAMD") == 0)
{
Platform::SystemInfo.processor.properties |= (properties & BIT_3DNOW) ? CPU_PROP_3DNOW : 0;
switch (processor)
{
case 0x700:
case 0x710:
Platform::SystemInfo.processor.type = CPU_AMD_K7;
Platform::SystemInfo.processor.name = StringTable->insert("AMD K7");
break;
case 0x660:
case 0x670:
Platform::SystemInfo.processor.type = CPU_AMD_K6;
Platform::SystemInfo.processor.name = StringTable->insert("AMD K6");
break;
case 0x680:
Platform::SystemInfo.processor.type = CPU_AMD_K6_2;
Platform::SystemInfo.processor.name = StringTable->insert("AMD K6-2");
break;
case 0x690:
Platform::SystemInfo.processor.type = CPU_AMD_K6_3;
Platform::SystemInfo.processor.name = StringTable->insert("AMD K6-3");
break;
case 0x510:
case 0x520:
case 0x530:
Platform::SystemInfo.processor.type = CPU_AMD_K6_3;
Platform::SystemInfo.processor.name = StringTable->insert("AMD K5");
break;
default:
Platform::SystemInfo.processor.type = CPU_AMD_Unknown;
Platform::SystemInfo.processor.name = StringTable->insert("AMD (unknown)");
break;
}
}
//--------------------------------------
else
if (dStricmp(vendor, "CyrixInstead") == 0)
{
switch (processor)
{
case 0x520:
Platform::SystemInfo.processor.type = CPU_Cyrix_6x86;
Platform::SystemInfo.processor.name = StringTable->insert("Cyrix 6x86");
break;
case 0x440:
Platform::SystemInfo.processor.type = CPU_Cyrix_MediaGX;
Platform::SystemInfo.processor.name = StringTable->insert("Cyrix Media GX");
break;
case 0x600:
Platform::SystemInfo.processor.type = CPU_Cyrix_6x86MX;
Platform::SystemInfo.processor.name = StringTable->insert("Cyrix 6x86mx/MII");
break;
case 0x540:
Platform::SystemInfo.processor.type = CPU_Cyrix_GXm;
Platform::SystemInfo.processor.name = StringTable->insert("Cyrix GXm");
break;
default:
Platform::SystemInfo.processor.type = CPU_Cyrix_Unknown;
Platform::SystemInfo.processor.name = StringTable->insert("Cyrix (unknown)");
break;
}
}
//--------------------------------------
// if RDTSC support calculate the aproximate Mhz of the CPU
if (Platform::SystemInfo.processor.properties & CPU_PROP_RDTSC &&
Platform::SystemInfo.processor.properties & CPU_PROP_FPU)
{
const U32 MS_INTERVAL = 750;
U32 time[2];
U32 ticks = 0;
__asm
{
push eax
push edx
//db 0fh, 31h
rdtsc
mov DWORD PTR time, eax
mov DWORD PTR time+4, edx
pop edx
pop eax
}
U32 ms = GetTickCount();
while ( GetTickCount() < ms+MS_INTERVAL )
{ /* empty */ }
ms = GetTickCount()-ms;
__asm
{
push eax
push edx
//db 0fh, 31h
rdtsc
sub edx, DWORD PTR time+4
sbb eax, DWORD PTR time
mov DWORD PTR ticks, eax
pop edx
pop eax
}
U32 mhz = F32(ticks) / F32(ms) / 1000.0f;
// catch-22 the timing method used above to calc Mhz is generally
// wrong by a few percent so we want to round to the nearest clock
// multiple but we also want to be careful to not touch overclocked results
// measure how close the Raw Mhz number is to the center of each clock bucket
U32 bucket25 = mhz % 25;
U32 bucket33 = mhz % 33;
U32 bucket50 = mhz % 50;
if (bucket50 < 8 || bucket50 > 42)
Platform::SystemInfo.processor.mhz = U32((mhz+(50.0f/2.0f))/50.0f) * 50;
else if (bucket25 < 5 || bucket25 > 20)
Platform::SystemInfo.processor.mhz = U32((mhz+(25.0f/2.0f))/25.0f) * 25;
else if (bucket33 < 5 || bucket33 > 28)
Platform::SystemInfo.processor.mhz = U32((mhz+(33.0f/2.0f))/33.0f) * 33;
else
Platform::SystemInfo.processor.mhz = U32(mhz);
}
#endif
Con::printf("Processor Init:");
Con::printf(" %s, %d Mhz", Platform::SystemInfo.processor.name, Platform::SystemInfo.processor.mhz);
if (Platform::SystemInfo.processor.properties & CPU_PROP_FPU)
Con::printf(" FPU detected");
if (Platform::SystemInfo.processor.properties & CPU_PROP_MMX)
Con::printf(" MMX detected");
if (Platform::SystemInfo.processor.properties & CPU_PROP_3DNOW)
Con::printf(" 3DNow detected");
if (Platform::SystemInfo.processor.properties & CPU_PROP_SSE)
Con::printf(" SSE detected");
Con::printf(" ");
PlatformBlitInit();
}

244
platformWin32/winConsole.cc Normal file
View file

@ -0,0 +1,244 @@
//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#include "PlatformWin32/platformWin32.h"
#include "PlatformWin32/winConsole.h"
//#include <stdio.h>
#include "Platform/event.h"
#include "Platform/gameInterface.h"
WinConsole *WindowsConsole = NULL;
ConsoleFunction(enableWinConsole, void, 2, 2, "enableWinConsole(bool);")
{
argc;
WindowsConsole->enable(dAtob(argv[1]));
}
void WinConsole::create()
{
WindowsConsole = new WinConsole();
}
void WinConsole::destroy()
{
delete WindowsConsole;
WindowsConsole = NULL;
}
void WinConsole::enable(bool enabled)
{
winConsoleEnabled = enabled;
if(winConsoleEnabled)
{
AllocConsole();
const char *title = Con::getVariable("Con::WindowTitle");
if (title && *title)
SetConsoleTitle(title);
stdOut = GetStdHandle(STD_OUTPUT_HANDLE);
stdIn = GetStdHandle(STD_INPUT_HANDLE);
stdErr = GetStdHandle(STD_ERROR_HANDLE);
printf("%s", Con::getVariable("Con::Prompt"));
}
}
bool WinConsole::isEnabled()
{
if ( WindowsConsole )
return WindowsConsole->winConsoleEnabled;
return false;
}
static void winConsoleConsumer(ConsoleLogEntry::Level, const char *line)
{
WindowsConsole->processConsoleLine(line);
}
WinConsole::WinConsole()
{
for (S32 iIndex = 0; iIndex < MAX_CMDS; iIndex ++)
rgCmds[iIndex][0] = '\0';
iCmdIndex = 0;
winConsoleEnabled = false;
Con::addConsumer(winConsoleConsumer);
inpos = 0;
lineOutput = false;
}
void WinConsole::printf(const char *s, ...)
{
static char buffer[512];
DWORD bytes;
va_list args;
va_start(args, s);
vsprintf(buffer, s, args);
WriteFile(stdOut, buffer, strlen(buffer), &bytes, NULL);
FlushFileBuffers( stdOut );
}
void WinConsole::processConsoleLine(const char *consoleLine)
{
if(winConsoleEnabled)
{
inbuf[inpos] = 0;
if(lineOutput)
printf("%s\n", consoleLine);
else
printf("%c%s\n%s%s", '\r', consoleLine, Con::getVariable("Con::Prompt"), inbuf);
}
}
void WinConsole::process()
{
if(winConsoleEnabled)
{
DWORD numEvents;
GetNumberOfConsoleInputEvents(stdIn, &numEvents);
if(numEvents)
{
INPUT_RECORD rec[20];
char outbuf[256];
S32 outpos = 0;
ReadConsoleInput(stdIn, rec, 20, &numEvents);
DWORD i;
for(i = 0; i < numEvents; i++)
{
if(rec[i].EventType == KEY_EVENT)
{
KEY_EVENT_RECORD *ke = &(rec[i].Event.KeyEvent);
if(ke->bKeyDown)
{
switch (ke->uChar.AsciiChar)
{
// If no ASCII char, check if it's a handled virtual key
case 0:
switch (ke->wVirtualKeyCode)
{
// UP ARROW
case 0x26 :
// Go to the previous command in the cyclic array
if ((-- iCmdIndex) < 0)
iCmdIndex = MAX_CMDS - 1;
// If this command isn't empty ...
if (rgCmds[iCmdIndex][0] != '\0')
{
// Obliterate current displayed text
for (S32 i = outpos = 0; i < inpos; i ++)
{
outbuf[outpos ++] = '\b';
outbuf[outpos ++] = ' ';
outbuf[outpos ++] = '\b';
}
// Copy command into command and display buffers
for (inpos = 0; inpos < (S32)strlen(rgCmds[iCmdIndex]); inpos ++, outpos ++)
{
outbuf[outpos] = rgCmds[iCmdIndex][inpos];
inbuf [inpos ] = rgCmds[iCmdIndex][inpos];
}
}
// If previous is empty, stay on current command
else if ((++ iCmdIndex) >= MAX_CMDS)
{
iCmdIndex = 0;
}
break;
// DOWN ARROW
case 0x28 : {
// Go to the next command in the command array, if
// it isn't empty
if (rgCmds[iCmdIndex][0] != '\0' && (++ iCmdIndex) >= MAX_CMDS)
iCmdIndex = 0;
// Obliterate current displayed text
for (S32 i = outpos = 0; i < inpos; i ++)
{
outbuf[outpos ++] = '\b';
outbuf[outpos ++] = ' ';
outbuf[outpos ++] = '\b';
}
// Copy command into command and display buffers
for (inpos = 0; inpos < (S32)strlen(rgCmds[iCmdIndex]); inpos ++, outpos ++)
{
outbuf[outpos] = rgCmds[iCmdIndex][inpos];
inbuf [inpos ] = rgCmds[iCmdIndex][inpos];
}
}
break;
// LEFT ARROW
case 0x25 :
break;
// RIGHT ARROW
case 0x27 :
break;
default :
break;
}
break;
case '\b':
if(inpos > 0)
{
outbuf[outpos++] = '\b';
outbuf[outpos++] = ' ';
outbuf[outpos++] = '\b';
inpos--;
}
break;
case '\n':
case '\r':
outbuf[outpos++] = '\r';
outbuf[outpos++] = '\n';
inbuf[inpos] = 0;
outbuf[outpos] = 0;
printf("%s", outbuf);
S32 eventSize;
eventSize = ConsoleEventHeaderSize;
dStrcpy(postEvent.data, inbuf);
postEvent.size = eventSize + dStrlen(inbuf) + 1;
Game->postEvent(postEvent);
// If we've gone off the end of our array, wrap
// back to the beginning
if (iCmdIndex >= MAX_CMDS)
iCmdIndex %= MAX_CMDS;
// Put the new command into the array
strcpy(rgCmds[iCmdIndex ++], inbuf);
printf("%s", Con::getVariable("Con::Prompt"));
inpos = outpos = 0;
break;
default:
inbuf[inpos++] = ke->uChar.AsciiChar;
outbuf[outpos++] = ke->uChar.AsciiChar;
break;
}
}
}
}
if(outpos)
{
outbuf[outpos] = 0;
printf("%s", outbuf);
}
}
}
}

View file

@ -0,0 +1,49 @@
//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#ifndef _WINCONSOLE_H_
#define _WINCONSOLE_H_
#define MAX_CMDS 10
#ifndef _CONSOLE_H_
#include "console/console.h"
#endif
#ifndef _EVENT_H_
#include "Platform/event.h"
#endif
class WinConsole
{
bool winConsoleEnabled;
HANDLE stdOut;
HANDLE stdIn;
HANDLE stdErr;
ConsoleEvent postEvent;
char inbuf[512];
S32 inpos;
bool lineOutput;
char curTabComplete[512];
S32 tabCompleteStart;
char rgCmds[MAX_CMDS][512];
S32 iCmdIndex;
void printf(const char *s, ...);
public:
WinConsole();
void process();
void enable(bool);
void processConsoleLine(const char *consoleLine);
static void create();
static void destroy();
static bool isEnabled();
};
extern WinConsole *WindowsConsole;
#endif

View file

@ -0,0 +1,720 @@
//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#include "platformWIN32/platformGL.h"
#include "platformWIN32/platformWin32.h"
#include "platform/platformAudio.h"
#include "platformWIN32/winD3DVideo.h"
#include "console/console.h"
#include "math/mPoint.h"
#include "platform/event.h"
#include "platform/gameInterface.h"
#include "console/consoleInternal.h"
#include "console/ast.h"
//------------------------------------------------------------------------------
bool D3DDevice::smCanSwitchBitDepth = true;
bool D3DDevice::smStay16 = false;
static void profileSystem(const char *vendor, const char *renderer)
{
Con::setBoolVariable("$pref::Video::safeModeOn", true);
Con::setBoolVariable("$pref::OpenGL::disableEXTCompiledVertexArray", false);
Con::setBoolVariable("$pref::OpenGL::disableSubImage", false);
Con::setBoolVariable("$pref::OpenGL::noEnvColor", true);
Con::setBoolVariable("$pref::OpenGL::disableARBTextureCompression", false);
Con::setBoolVariable("$pref::Interior::lockArrays", true);
Con::setBoolVariable("$pref::TS::skipFirstFog", false);
Con::setBoolVariable("$pref::OpenGL::disableEXTFogCoord", false);
Con::setVariable("$pref::Video::profiledVendor", vendor);
Con::setVariable("$pref::Video::profiledRenderer", renderer);
// write out prefs
gEvalState.globalVars.exportVariables("$pref::*", "prefs/ClientPrefs.cs", false);
}
//------------------------------------------------------------------------------
D3DDevice::D3DDevice()
{
initDevice();
}
//------------------------------------------------------------------------------
void D3DDevice::initDevice()
{
// Set the device name:
mDeviceName = "D3D";
// Set some initial conditions:
mResolutionList.clear();
// Enumerate all available resolutions:
DEVMODE devMode;
U32 modeNum = 0;
U32 stillGoing = true;
while ( stillGoing )
{
dMemset( &devMode, 0, sizeof( devMode ) );
devMode.dmSize = sizeof( devMode );
stillGoing = EnumDisplaySettings( NULL, modeNum++, &devMode );
if ( devMode.dmPelsWidth >= 640 && devMode.dmPelsHeight >= 480
&& ( devMode.dmBitsPerPel == 16 || (devMode.dmBitsPerPel == 32 && !smStay16) ) &&
( smCanSwitchBitDepth || devMode.dmBitsPerPel == winState.desktopBitsPixel ) )
{
// Only add this resolution if it is not already in the list:
bool alreadyInList = false;
for ( U32 i = 0; i < mResolutionList.size(); i++ )
{
if ( devMode.dmPelsWidth == mResolutionList[i].w
&& devMode.dmPelsHeight == mResolutionList[i].h
&& devMode.dmBitsPerPel == mResolutionList[i].bpp )
{
alreadyInList = true;
break;
}
}
if ( !alreadyInList )
{
Resolution newRes( devMode.dmPelsWidth, devMode.dmPelsHeight, devMode.dmBitsPerPel );
mResolutionList.push_back( newRes );
}
}
}
}
//------------------------------------------------------------------------------
bool D3DDevice::activate( U32 width, U32 height, U32 bpp, bool fullScreen )
{
bool needResurrect = false;
// If the rendering context exists, delete it:
if ( winState.hGLRC )
{
Con::printf( "Killing the texture manager..." );
Game->textureKill();
needResurrect = true;
Con::printf( "Making the rendering context not current..." );
if ( !qwglMakeCurrent( NULL, NULL ) )
{
AssertFatal( false, "D3DDevice::activate\nqwglMakeCurrent( NULL, NULL ) failed!" );
return false;
}
Con::printf( "Deleting the rendering context ..." );
if ( !qwglDeleteContext( winState.hGLRC ) )
{
AssertFatal( false, "D3DDevice::activate\nqwglDeleteContext failed!" );
return false;
}
winState.hGLRC = NULL;
}
// If the window already exists, kill it so we can start fresh:
if ( winState.appWindow )
{
Con::printf( "Releasing the device context..." );
ReleaseDC( winState.appWindow, winState.appDC );
winState.appDC = NULL;
Con::printf( "Destroying the window..." );
DestroyWindow( winState.appWindow );
winState.appWindow = NULL;
}
// If OpenGL library already loaded, shut it down and reload it:
if ( winState.hinstOpenGL )
QGL_Shutdown();
QGL_Init(OPENGL2D3D,GLU2D3D);
// Set the resolution:
if ( !setScreenMode( width, height, bpp, ( fullScreen || mFullScreenOnly ), true, false ) )
return false;
// Get original gamma ramp
mRestoreGamma = GetDeviceGammaRamp(winState.appDC, mOriginalRamp);
// Output some driver info to the console:
const char* vendorString = (const char*) glGetString( GL_VENDOR );
const char* rendererString = (const char*) glGetString( GL_RENDERER );
const char* versionString = (const char*) glGetString( GL_VERSION );
Con::printf( "OpenGL driver information:" );
if ( vendorString )
Con::printf( " Vendor: %s", vendorString );
if ( rendererString )
Con::printf( " Renderer: %s", rendererString );
if ( versionString )
Con::printf( " Version: %s", versionString );
if ( needResurrect )
{
// Reload the textures:
Con::printf( "Resurrecting the texture manager..." );
Game->textureResurrect();
}
QGL_EXT_Init();
Con::setVariable( "$pref::Video::displayDevice", mDeviceName );
Con::setBoolVariable( "$SwapIntervalSupported", false );
Con::setBoolVariable( "$pref::OpenGL::allowTexGen", false );
Con::setBoolVariable( "$pref::environmentMaps", false );
// only do this for the first session
if (!Con::getBoolVariable("$DisableSystemProfiling") && (dStrcmp(vendorString, Con::getVariable("$pref::Video::profiledVendor")) ||
dStrcmp(rendererString, Con::getVariable("$pref::Video::profiledRenderer"))))
profileSystem(vendorString, rendererString);
return true;
}
//------------------------------------------------------------------------------
void D3DDevice::shutdown()
{
if ( winState.hGLRC )
{
if (mRestoreGamma)
SetDeviceGammaRamp(winState.appDC, mOriginalRamp);
qwglMakeCurrent( NULL, NULL );
qwglDeleteContext( winState.hGLRC );
winState.hGLRC = NULL;
}
if ( winState.appDC )
{
ReleaseDC( winState.appWindow, winState.appDC );
winState.appDC = NULL;
}
if ( smIsFullScreen || (smStay16 && winState.desktopBitsPixel != 16))
ChangeDisplaySettings( NULL, 0 );
QGL_Shutdown();
}
//------------------------------------------------------------------------------
// This is the real workhorse function of the DisplayDevice...
//
bool D3DDevice::setScreenMode( U32 width, U32 height, U32 bpp, bool fullScreen, bool forceIt, bool repaint )
{
HWND curtain = NULL;
char errorMessage[256];
Resolution newRes( width, height, bpp );
bool newFullScreen = fullScreen;
bool safeModeOn = Con::getBoolVariable( "$pref::Video::safeModeOn" );
if ( !newFullScreen && mFullScreenOnly )
{
Con::warnf( ConsoleLogEntry::General, "D3DDevice::setScreenMode - device or desktop color depth does not allow windowed mode!" );
newFullScreen = true;
}
if ( !newFullScreen && ( newRes.w >= winState.desktopWidth || newRes.h >= winState.desktopHeight ) )
{
Con::warnf( ConsoleLogEntry::General, "D3DDevice::setScreenMode -- can't switch to resolution larger than desktop in windowed mode!" );
// Find the largest standard resolution that will fit on the desktop:
U32 resIndex;
for ( resIndex = mResolutionList.size() - 1; resIndex > 0; resIndex-- )
{
if ( mResolutionList[resIndex].w < winState.desktopWidth
&& mResolutionList[resIndex].h < winState.desktopHeight )
break;
}
newRes = mResolutionList[resIndex];
}
if ( newRes.w < 640 || newRes.h < 480 )
{
Con::warnf( ConsoleLogEntry::General, "D3DDevice::setScreenMode -- can't go smaller than 640x480!" );
return false;
}
if ( newFullScreen )
{
if (newRes.bpp != 16 && mFullScreenOnly)
newRes.bpp = 16;
// Match the new resolution to one in the list:
U32 resIndex = 0;
U32 bestScore = 0, thisScore = 0;
for ( int i = 0; i < mResolutionList.size(); i++ )
{
if ( newRes == mResolutionList[i] )
{
resIndex = i;
break;
}
else
{
thisScore = abs( S32( newRes.w ) - S32( mResolutionList[i].w ) )
+ abs( S32( newRes.h ) - S32( mResolutionList[i].h ) )
+ ( newRes.bpp == mResolutionList[i].bpp ? 0 : 1 );
if ( !bestScore || ( thisScore < bestScore ) )
{
bestScore = thisScore;
resIndex = i;
}
}
}
newRes = mResolutionList[resIndex];
}
else
// Basically ignore the bit depth parameter:
if (!smStay16)
newRes.bpp = winState.desktopBitsPixel;
else
newRes.bpp = 16;
// Return if already at this resolution:
if ( !forceIt && newRes == smCurrentRes && newFullScreen == smIsFullScreen )
return true;
Con::printf( "Setting screen mode to %dx%dx%d (%s)...", newRes.w, newRes.h, newRes.bpp, ( newFullScreen ? "fs" : "w" ) );
bool needResurrect = false;
// oh just always do it
//if ( ( newRes.bpp != smCurrentRes.bpp ) || ( safeModeOn && ( ( smIsFullScreen != newFullScreen ) || newFullScreen ) ) )
if (true)
{
// Delete the rendering context:
if ( winState.hGLRC )
{
if (!Video::smNeedResurrect)
{
Con::printf( "Killing the texture manager..." );
Game->textureKill();
needResurrect = true;
}
Con::printf( "Making the rendering context not current..." );
if ( !qwglMakeCurrent( NULL, NULL ) )
{
AssertFatal( false, "D3DDevice::setScreenMode\nqwglMakeCurrent( NULL, NULL ) failed!" );
return false;
}
Con::printf( "Deleting the rendering context..." );
if ( !qwglDeleteContext( winState.hGLRC ) )
{
AssertFatal( false, "D3DDevice::setScreenMode\nqwglDeleteContext failed!" );
return false;
}
winState.hGLRC = NULL;
}
// Release the device context:
if ( winState.appDC )
{
Con::printf( "Releasing the device context..." );
ReleaseDC( winState.appWindow, winState.appDC );
winState.appDC = NULL;
}
// Destroy the window:
if ( winState.appWindow )
{
Con::printf( "Destroying the window..." );
DestroyWindow( winState.appWindow );
winState.appWindow = NULL;
}
}
else if ( smIsFullScreen != newFullScreen )
{
// Change the window style:
Con::printf( "Changing the window style..." );
S32 windowStyle = WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
if ( newFullScreen )
windowStyle |= ( WS_POPUP | WS_MAXIMIZE );
else
windowStyle |= ( WS_OVERLAPPED | WS_CAPTION );
if ( !SetWindowLong( winState.appWindow, GWL_STYLE, windowStyle ) )
Platform::AlertOK( "Error", "Failed to change the window style!" );
}
U32 test;
if ( newFullScreen )
{
// Change the display settings:
DEVMODE devMode;
dMemset( &devMode, 0, sizeof( devMode ) );
devMode.dmSize = sizeof( devMode );
devMode.dmPelsWidth = newRes.w;
devMode.dmPelsHeight = newRes.h;
devMode.dmBitsPerPel = newRes.bpp;
devMode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL;
Con::printf( "Changing the display settings to %dx%dx%d...", newRes.w, newRes.h, newRes.bpp );
curtain = CreateCurtain( newRes.w, newRes.h );
test = ChangeDisplaySettings( &devMode, CDS_FULLSCREEN );
if ( test != DISP_CHANGE_SUCCESSFUL )
{
smIsFullScreen = false;
Con::setBoolVariable( "$pref::Video::fullScreen", false );
ChangeDisplaySettings( NULL, 0 );
Con::errorf( ConsoleLogEntry::General, "D3DDevice::setScreenMode - ChangeDisplaySettings failed." );
switch( test )
{
case DISP_CHANGE_RESTART:
Platform::AlertOK( "Display Change Failed", "You must restart your machine to get the specified mode." );
break;
case DISP_CHANGE_BADMODE:
Platform::AlertOK( "Display Change Failed", "The specified mode is not supported by this device." );
break;
default:
Platform::AlertOK( "Display Change Failed", "Hardware failed to switch to the specified mode." );
break;
};
DestroyWindow( curtain );
return false;
}
else
smIsFullScreen = true;
}
else if ( smIsFullScreen || (smStay16 && winState.desktopBitsPixel != 16))
{
if (!smStay16 || winState.desktopBitsPixel == 16)
{
Con::printf( "Changing to the desktop display settings (%dx%dx%d)...", winState.desktopWidth, winState.desktopHeight, winState.desktopBitsPixel );
ChangeDisplaySettings( NULL, 0 );
}
else
{
// Change the display settings:
DEVMODE devMode;
dMemset( &devMode, 0, sizeof( devMode ) );
devMode.dmSize = sizeof( devMode );
devMode.dmBitsPerPel = newRes.bpp;
devMode.dmFields = DM_BITSPERPEL;
Con::printf( "Changing the display settings to %dx%dx%d...", winState.desktopWidth, winState.desktopHeight, newRes.bpp );
test = ChangeDisplaySettings( &devMode, 0 );
if ( test != DISP_CHANGE_SUCCESSFUL )
{
smIsFullScreen = true;
Con::setBoolVariable( "$pref::Video::fullScreen", true );
ChangeDisplaySettings( NULL, 0 );
Con::errorf( ConsoleLogEntry::General, "D3DDevice::setScreenMode - ChangeDisplaySettings failed." );
switch ( test )
{
case DISP_CHANGE_RESTART:
Platform::AlertOK( "Display Change Failed", "You must restart your machine to get the specified mode." );
break;
case DISP_CHANGE_BADMODE:
Platform::AlertOK( "Display Change Failed", "The specified mode is not supported by this device." );
break;
default:
Platform::AlertOK( "Display Change Failed", "Hardware failed to switch to the specified mode." );
break;
};
return false;
}
}
smIsFullScreen = false;
}
Con::setBoolVariable( "$pref::Video::fullScreen", smIsFullScreen );
bool newWindow = false;
if ( !winState.appWindow )
{
Con::printf( "Creating a new %swindow...", ( fullScreen ? "full-screen " : "" ) );
winState.appWindow = CreateOpenGLWindow( newRes.w, newRes.h, newFullScreen );
if ( !winState.appWindow )
{
AssertFatal( false, "D3DDevice::setScreenMode\nFailed to create a new window!" );
return false;
}
newWindow = true;
}
// Move the window:
if ( !newFullScreen )
{
// Adjust the window rect to compensate for the window style:
RECT windowRect;
windowRect.left = windowRect.top = 0;
windowRect.right = newRes.w;
windowRect.bottom = newRes.h;
AdjustWindowRect( &windowRect, GetWindowLong( winState.appWindow, GWL_STYLE ), false );
U32 adjWidth = windowRect.right - windowRect.left;
U32 adjHeight = windowRect.bottom - windowRect.top;
// Center the window on the desktop:
U32 xPos = ( winState.desktopWidth - adjWidth ) / 2;
U32 yPos = ( winState.desktopHeight - adjHeight ) / 2;
test = SetWindowPos( winState.appWindow, 0, xPos, yPos, adjWidth, adjHeight, SWP_NOZORDER );
if ( !test )
{
dSprintf( errorMessage, 255, "D3DDevice::setScreenMode\nSetWindowPos failed trying to move the window to (%d,%d) and size it to %dx%d.", xPos, yPos, newRes.w, newRes.h );
AssertFatal( false, errorMessage );
return false;
}
}
else if ( !newWindow )
{
// Move and size the window to take up the whole screen:
if ( !SetWindowPos( winState.appWindow, 0, 0, 0, newRes.w, newRes.h, SWP_NOZORDER ) )
{
dSprintf( errorMessage, 255, "D3DDevice::setScreenMode\nSetWindowPos failed to move the window to (0,0) and size it to %dx%d.", newRes.w, newRes.h );
AssertFatal( false, errorMessage );
return false;
}
}
if ( !winState.appDC )
{
// Get a new device context:
Con::printf( "Acquiring a new device context..." );
winState.appDC = GetDC( winState.appWindow );
if ( !winState.appDC )
{
AssertFatal( false, "D3DDevice::setScreenMode\nGetDC failed to get a valid device context!" );
return false;
}
}
if ( newWindow )
{
// Set the pixel format of the new window:
PIXELFORMATDESCRIPTOR pfd;
qwglDescribePixelFormat( winState.appDC, 1, sizeof( pfd ), &pfd );
if ( !SetPixelFormat( winState.appDC, 1, &pfd ) )
{
//AssertFatal( false, "D3DDevice::setScreenMode\nFailed to set the pixel format!" );
//return false;
}
Con::printf( "Pixel format set:" );
Con::printf( " %d color bits, %d depth bits, %d stencil bits", pfd.cColorBits, pfd.cDepthBits, pfd.cStencilBits );
}
if ( !winState.hGLRC )
{
// Create a new rendering context:
Con::printf( "Creating a new rendering context..." );
winState.hGLRC = qwglCreateContext( winState.appDC );
if ( !winState.hGLRC )
{
AssertFatal( false, "D3DDevice::setScreenMode\nqwglCreateContext failed to create an OpenGL rendering context!" );
return false;
}
// Make the new rendering context current:
Con::printf( "Making the new rendering context current..." );
if ( !qwglMakeCurrent( winState.appDC, winState.hGLRC ) )
{
AssertFatal( false, "D3DDevice::setScreenMode\nqwglMakeCurrent failed to make the rendering context current!" );
return false;
}
if ( needResurrect )
{
// Reload the textures:
Con::printf( "Resurrecting the texture manager..." );
Game->textureResurrect();
}
}
smCurrentRes = newRes;
Platform::setWindowSize( newRes.w, newRes.h );
char tempBuf[15];
dSprintf( tempBuf, sizeof( tempBuf ), "%d %d %d", smCurrentRes.w, smCurrentRes.h, smCurrentRes.bpp );
Con::setVariable( "$pref::Video::resolution", tempBuf );
if ( curtain )
DestroyWindow( curtain );
// Doesn't hurt to do this even it isn't necessary:
ShowWindow( winState.appWindow, SW_SHOW );
SetForegroundWindow( winState.appWindow );
SetFocus( winState.appWindow );
if ( repaint )
Con::evaluate( "resetCanvas();" );
return true;
}
//------------------------------------------------------------------------------
void D3DDevice::swapBuffers()
{
qwglSwapBuffers( winState.appDC );
}
//------------------------------------------------------------------------------
const char* D3DDevice::getDriverInfo()
{
// Output some driver info to the console:
const char* vendorString = (const char*) glGetString( GL_VENDOR );
const char* rendererString = (const char*) glGetString( GL_RENDERER );
const char* versionString = (const char*) glGetString( GL_VERSION );
const char* extensionsString = (const char*) glGetString( GL_EXTENSIONS );
U32 bufferLen = ( vendorString ? dStrlen( vendorString ) : 0 )
+ ( rendererString ? dStrlen( rendererString ) : 0 )
+ ( versionString ? dStrlen( versionString ) : 0 )
+ ( extensionsString ? dStrlen( extensionsString ) : 0 )
+ 4;
char* returnString = Con::getReturnBuffer( bufferLen );
dSprintf( returnString, bufferLen, "%s\t%s\t%s\t%s",
( vendorString ? vendorString : "" ),
( rendererString ? rendererString : "" ),
( versionString ? versionString : "" ),
( extensionsString ? extensionsString : "" ) );
return( returnString );
}
//------------------------------------------------------------------------------
bool D3DDevice::getGammaCorrection(F32 &g)
{
U16 ramp[256*3];
if (!GetDeviceGammaRamp(winState.appDC, ramp))
return false;
F32 csum = 0.0;
U32 ccount = 0;
for (U16 i = 0; i < 256; ++i)
{
if (i != 0 && ramp[i] != 0 && ramp[i] != 65535)
{
F64 b = (F64) i/256.0;
F64 a = (F64) ramp[i]/65535.0;
F32 c = (F32) (mLog(a)/mLog(b));
csum += c;
++ccount;
}
}
g = csum/ccount;
return true;
}
//------------------------------------------------------------------------------
bool D3DDevice::setGammaCorrection(F32 g)
{
U16 ramp[256*3];
for (U16 i = 0; i < 256; ++i)
ramp[i] = mPow((F32) i/256.0f, g) * 65535.0f;
dMemcpy(&ramp[256],ramp,256*sizeof(U16));
dMemcpy(&ramp[512],ramp,256*sizeof(U16));
return SetDeviceGammaRamp(winState.appDC, ramp);
}
//------------------------------------------------------------------------------
bool D3DDevice::setVerticalSync( bool on )
{
on;
return( false );
}
//------------------------------------------------------------------------------
DisplayDevice* D3DDevice::create()
{
bool result = false;
OSVERSIONINFO OSVersionInfo;
dMemset( &OSVersionInfo, 0, sizeof( OSVERSIONINFO ) );
OSVersionInfo.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
if ( GetVersionEx( &OSVersionInfo ) &&
(OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT &&
OSVersionInfo.dwMajorVersion <= 4) )
return NULL;
// If we can't do OpenGL, don't attempt D3D either (probably Voodoo2 only)
if (Video::getDevice("OpenGL") == NULL)
return NULL;
// This shouldn't happen, but just to be safe...
if ( winState.hinstOpenGL )
QGL_Shutdown();
if (!QGL_Init(OPENGL2D3D,GLU2D3D))
return NULL;
// Create a test window to see if OpenGL hardware acceleration is available:
WNDCLASS wc;
dMemset(&wc, 0, sizeof(wc));
wc.style = CS_OWNDC;
wc.lpfnWndProc = DefWindowProc;
wc.hInstance = winState.appInstance;
wc.lpszClassName = "D3DTest";
RegisterClass( &wc );
HWND testWindow = CreateWindow(
"D3DTest",
"",
WS_POPUP,
0, 0, 640, 480,
NULL,
NULL,
winState.appInstance,
NULL );
if ( testWindow )
{
HDC testDC = GetDC( testWindow );
if ( testDC )
{
PIXELFORMATDESCRIPTOR pfd;
result = qwglDescribePixelFormat( testDC, 1, sizeof( pfd ), &pfd );
ReleaseDC( testWindow, testDC );
}
DestroyWindow( testWindow );
}
UnregisterClass( "D3DTest", winState.appInstance );
QGL_Shutdown();
if ( result )
{
D3DDevice* newOGLDevice = new D3DDevice();
if ( newOGLDevice )
{
newOGLDevice->mFullScreenOnly = Video::getDevice("OpenGL")->isFullScreenOnly();
return (DisplayDevice*) newOGLDevice;
}
else
return NULL;
}
else
return NULL;
}

View file

@ -0,0 +1,41 @@
//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#ifndef _WIND3DVIDEO_H_
#define _WIND3DVIDEO_H_
#ifndef _PLATFORMVIDEO_H_
#include "Platform/platformVideo.h"
#endif
class D3DDevice : public DisplayDevice
{
static bool smCanSwitchBitDepth;
bool mRestoreGamma;
U16 mOriginalRamp[256*3];
public:
D3DDevice();
void initDevice();
bool activate( U32 width, U32 height, U32 bpp, bool fullScreen );
void shutdown();
void destroy();
bool setScreenMode( U32 width, U32 height, U32 bpp, bool fullScreen, bool forceIt = false, bool repaint = true );
void swapBuffers();
const char* getDriverInfo();
bool getGammaCorrection(F32 &g);
bool setGammaCorrection(F32 g);
bool setVerticalSync( bool on );
static DisplayDevice* create();
static bool smStay16;
};
#endif // _H_WIND3DVIDEO

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,144 @@
//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#ifndef _WINDINPUTDEVICE_H_
#define _WINDINPUTDEVICE_H_
#ifndef _PLATFORMWIN32_H_
#include "PlatformWin32/platformWin32.h"
#endif
#ifndef _PLATFORMINPUT_H_
#include "Platform/platformInput.h"
#endif
#ifndef _EVENT_H_
#include "Platform/event.h"
#endif
#include <dinput.h>
class DInputDevice : public InputDevice
{
public:
static LPDIRECTINPUT smDInputInterface;
static bool smIsDX5;
protected:
enum Constants
{
QUEUED_BUFFER_SIZE = 128,
SIZEOF_BUTTON = 1, // size of an object's data in bytes
SIZEOF_KEY = 1,
SIZEOF_AXIS = 4,
SIZEOF_POV = 4,
};
static U8 smKeyboardCount;
static U8 smMouseCount;
static U8 smJoystickCount;
static U8 smUnknownCount;
static U8 smModifierKeys;
static bool smKeyStates[256];
static bool smInitialized;
//--------------------------------------
LPDIRECTINPUTDEVICE mDevice;
LPDIRECTINPUTDEVICE2 mDevice2;
DIDEVICEINSTANCE mDeviceInstance;
DIDEVCAPS mDeviceCaps;
U8 mDeviceType;
U8 mDeviceID;
bool mAcquired;
bool mNeedSync;
//--------------------------------------
DIDEVICEOBJECTINSTANCE* mObjInstance;
DIOBJECTDATAFORMAT* mObjFormat;
ObjInfo* mObjInfo;
U8* mObjBuffer1; // polled device input buffers
U8* mObjBuffer2;
U8* mPrevObjBuffer; // points to buffer 1 or 2
U32 mObjBufferSize; // size of objBuffer*
U32 mObjCount; // number of objects on this device
U32 mObjEnumCount; // used during enumeration ONLY
U32 mObjBufferOfs; // used during enumeration ONLY
static BOOL CALLBACK EnumObjectsProc( const DIDEVICEOBJECTINSTANCE *doi, LPVOID pvRef );
bool enumerateObjects();
bool processAsync();
bool processImmediate();
bool processKeyEvent( InputEvent &event );
void syncKeyboardState();
DWORD findObjInstance( DWORD offset );
bool buildEvent( DWORD offset, S32 newData, S32 oldData );
public:
DInputDevice( const DIDEVICEINSTANCE* deviceInst );
~DInputDevice();
static void init();
static void resetModifierKeys();
bool create();
void destroy();
bool acquire();
bool unacquire();
bool isAcquired();
bool isPolled();
U8 getDeviceType();
U8 getDeviceID();
const char* getName();
const char* getProductName();
// Console interface functions:
const char* getJoystickAxesString();
static bool joystickDetected();
//
bool process();
};
//------------------------------------------------------------------------------
inline bool DInputDevice::isAcquired()
{
return mAcquired;
}
//------------------------------------------------------------------------------
inline bool DInputDevice::isPolled()
{
//return true;
return ( mDeviceCaps.dwFlags & DIDC_POLLEDDEVICE );
}
//------------------------------------------------------------------------------
inline U8 DInputDevice::getDeviceType()
{
return mDeviceType;
}
//------------------------------------------------------------------------------
inline U8 DInputDevice::getDeviceID()
{
return mDeviceID;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
U16 DIK_to_Key( U8 dikCode );
U8 Key_to_DIK( U16 keyCode );
#endif // _H_WINDINPUTDEVICE_

View file

@ -0,0 +1,553 @@
//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#include "platformWIN32/platformWin32.h"
#include "platform/platformVideo.h"
#include "platformWIN32/winDirectInput.h"
#include "platformWIN32/winDInputDevice.h"
#include "platform/event.h"
#include "console/console.h"
#include "console/consoleTypes.h"
//------------------------------------------------------------------------------
// Static class variables:
bool DInputManager::smKeyboardEnabled = true;
bool DInputManager::smMouseEnabled = false;
bool DInputManager::smJoystickEnabled = false;
// Type definitions:
typedef HRESULT (WINAPI* FN_DirectInputCreate)( HINSTANCE hInst, DWORD dwVersion, LPDIRECTINPUT * ppDI, IUnknown FAR *pUnkOuter );
//------------------------------------------------------------------------------
DInputManager::DInputManager()
{
mEnabled = false;
mDInputLib = NULL;
mDInputInterface = NULL;
mKeyboardActive = mMouseActive = mJoystickActive = false;
}
//------------------------------------------------------------------------------
void DInputManager::init()
{
Con::addVariable( "pref::Input::KeyboardEnabled", TypeBool, &smKeyboardEnabled );
Con::addVariable( "pref::Input::MouseEnabled", TypeBool, &smMouseEnabled );
Con::addVariable( "pref::Input::JoystickEnabled", TypeBool, &smJoystickEnabled );
}
//------------------------------------------------------------------------------
bool DInputManager::enable()
{
FN_DirectInputCreate fnDInputCreate;
disable();
#ifdef LOG_INPUT
Input::log( "Enabling DirectInput...\n" );
#endif
mDInputLib = LoadLibrary( "DInput.dll" );
if ( mDInputLib )
{
fnDInputCreate = (FN_DirectInputCreate) GetProcAddress( mDInputLib, "DirectInputCreateA" );
if ( fnDInputCreate )
{
bool result = SUCCEEDED( fnDInputCreate( winState.appInstance, 0x500, &mDInputInterface, NULL ) );
if ( result )
{
DInputDevice::smIsDX5 = true;
#ifdef LOG_INPUT
Input::log( "DirectX 5 or greater detected.\n" );
#endif
}
else
{
result = SUCCEEDED( fnDInputCreate( winState.appInstance, 0x300, &mDInputInterface, NULL ) );
if ( result )
{
DInputDevice::smIsDX5 = false;
#ifdef LOG_INPUT
Input::log( "DirectX 3 detected.\n" );
#endif
}
}
if ( result )
{
enumerateDevices();
mEnabled = true;
return true;
}
}
}
disable();
#ifdef LOG_INPUT
Input::log( "Failed to enable DirectInput.\n" );
#endif
return false;
}
//------------------------------------------------------------------------------
void DInputManager::disable()
{
unacquire( SI_ANY, SI_ANY );
DInputDevice* dptr;
iterator ptr = begin();
while ( ptr != end() )
{
dptr = dynamic_cast<DInputDevice*>( *ptr );
if ( dptr )
{
removeObject( dptr );
//if ( dptr->getManager() )
//dptr->getManager()->unregisterObject( dptr );
delete dptr;
ptr = begin();
}
else
ptr++;
}
if ( mDInputInterface )
{
mDInputInterface->Release();
mDInputInterface = NULL;
}
if ( mDInputLib )
{
FreeLibrary( mDInputLib );
mDInputLib = NULL;
}
mEnabled = false;
}
//------------------------------------------------------------------------------
void DInputManager::onDeleteNotify( SimObject* object )
{
Parent::onDeleteNotify( object );
}
//------------------------------------------------------------------------------
bool DInputManager::onAdd()
{
if ( !Parent::onAdd() )
return false;
acquire( SI_ANY, SI_ANY );
return true;
}
//------------------------------------------------------------------------------
void DInputManager::onRemove()
{
unacquire( SI_ANY, SI_ANY );
Parent::onRemove();
}
//------------------------------------------------------------------------------
bool DInputManager::acquire( U8 deviceType, U8 deviceID )
{
bool anyActive = false;
DInputDevice* dptr;
for ( iterator ptr = begin(); ptr != end(); ptr++ )
{
dptr = dynamic_cast<DInputDevice*>( *ptr );
if ( dptr
&& ( ( deviceType == SI_ANY ) || ( dptr->getDeviceType() == deviceType ) )
&& ( ( deviceID == SI_ANY ) || ( dptr->getDeviceID() == deviceID ) ) )
{
if ( dptr->acquire() )
anyActive = true;
}
}
return anyActive;
}
//------------------------------------------------------------------------------
void DInputManager::unacquire( U8 deviceType, U8 deviceID )
{
DInputDevice* dptr;
for ( iterator ptr = begin(); ptr != end(); ptr++ )
{
dptr = dynamic_cast<DInputDevice*>( *ptr );
if ( dptr
&& ( ( deviceType == SI_ANY ) || ( dptr->getDeviceType() == deviceType ) )
&& ( ( deviceID == SI_ANY ) || ( dptr->getDeviceID() == deviceID ) ) )
dptr->unacquire();
}
}
//------------------------------------------------------------------------------
void DInputManager::process()
{
DInputDevice* dptr;
for ( iterator ptr = begin(); ptr != end(); ptr++ )
{
dptr = dynamic_cast<DInputDevice*>( *ptr );
if ( dptr )
dptr->process();
}
}
//------------------------------------------------------------------------------
void DInputManager::enumerateDevices()
{
if ( mDInputInterface )
{
#ifdef LOG_INPUT
Input::log( "Enumerating input devices...\n" );
#endif
DInputDevice::init();
DInputDevice::smDInputInterface = mDInputInterface;
mDInputInterface->EnumDevices( DIDEVTYPE_KEYBOARD, EnumDevicesProc, this, DIEDFL_ATTACHEDONLY );
mDInputInterface->EnumDevices( DIDEVTYPE_MOUSE, EnumDevicesProc, this, DIEDFL_ATTACHEDONLY );
mDInputInterface->EnumDevices( DIDEVTYPE_JOYSTICK, EnumDevicesProc, this, DIEDFL_ATTACHEDONLY );
}
}
//------------------------------------------------------------------------------
BOOL CALLBACK DInputManager::EnumDevicesProc( const DIDEVICEINSTANCE* pddi, LPVOID pvRef )
{
DInputManager* manager = (DInputManager*) pvRef;
DInputDevice* newDevice = new DInputDevice( pddi );
manager->addObject( newDevice );
if ( !newDevice->create() )
{
manager->removeObject( newDevice );
delete newDevice;
}
return (DIENUM_CONTINUE);
}
//------------------------------------------------------------------------------
bool DInputManager::enableKeyboard()
{
DInputManager* mgr = dynamic_cast<DInputManager*>( Input::getManager() );
if ( !mgr || !mgr->isEnabled() )
return( false );
if ( smKeyboardEnabled && mgr->isKeyboardActive() )
return( true );
smKeyboardEnabled = true;
if ( Input::isActive() )
smKeyboardEnabled = mgr->activateKeyboard();
if ( smKeyboardEnabled )
{
Con::printf( "DirectInput keyboard enabled." );
#ifdef LOG_INPUT
Input::log( "Keyboard enabled.\n" );
#endif
}
else
{
Con::warnf( "DirectInput keyboard failed to enable!" );
#ifdef LOG_INPUT
Input::log( "Keyboard failed to enable!\n" );
#endif
}
return( smKeyboardEnabled );
}
//------------------------------------------------------------------------------
void DInputManager::disableKeyboard()
{
DInputManager* mgr = dynamic_cast<DInputManager*>( Input::getManager() );
if ( !mgr || !mgr->isEnabled() || !smKeyboardEnabled )
return;
mgr->deactivateKeyboard();
smKeyboardEnabled = false;
Con::printf( "DirectInput keyboard disabled." );
#ifdef LOG_INPUT
Input::log( "Keyboard disabled.\n" );
#endif
}
//------------------------------------------------------------------------------
bool DInputManager::isKeyboardEnabled()
{
return( smKeyboardEnabled );
}
//------------------------------------------------------------------------------
bool DInputManager::activateKeyboard()
{
if ( !mEnabled || !Input::isActive() || !smKeyboardEnabled )
return( false );
// Acquire only one keyboard:
mKeyboardActive = acquire( KeyboardDeviceType, 0 );
#ifdef LOG_INPUT
Input::log( mKeyboardActive ? "Keyboard activated.\n" : "Keyboard failed to activate!\n" );
#endif
return( mKeyboardActive );
}
//------------------------------------------------------------------------------
void DInputManager::deactivateKeyboard()
{
if ( mEnabled && mKeyboardActive )
{
unacquire( KeyboardDeviceType, SI_ANY );
mKeyboardActive = false;
#ifdef LOG_INPUT
Input::log( "Keyboard deactivated.\n" );
#endif
}
}
//------------------------------------------------------------------------------
bool DInputManager::enableMouse()
{
DInputManager* mgr = dynamic_cast<DInputManager*>( Input::getManager() );
if ( !mgr || !mgr->isEnabled() )
return( false );
if ( smMouseEnabled && mgr->isMouseActive() )
return( true );
smMouseEnabled = true;
if ( Input::isActive() )
smMouseEnabled = mgr->activateMouse();
if ( smMouseEnabled )
{
Con::printf( "DirectInput mouse enabled." );
#ifdef LOG_INPUT
Input::log( "Mouse enabled.\n" );
#endif
}
else
{
Con::warnf( "DirectInput mouse failed to enable!" );
#ifdef LOG_INPUT
Input::log( "Mouse failed to enable!\n" );
#endif
}
return( smMouseEnabled );
}
//------------------------------------------------------------------------------
void DInputManager::disableMouse()
{
DInputManager* mgr = dynamic_cast<DInputManager*>( Input::getManager() );
if ( !mgr || !mgr->isEnabled() || !smMouseEnabled )
return;
mgr->deactivateMouse();
smMouseEnabled = false;
Con::printf( "DirectInput mouse disabled." );
#ifdef LOG_INPUT
Input::log( "Mouse disabled.\n" );
#endif
}
//------------------------------------------------------------------------------
bool DInputManager::isMouseEnabled()
{
return( smMouseEnabled );
}
//------------------------------------------------------------------------------
bool DInputManager::activateMouse()
{
if ( !mEnabled || !Input::isActive() || !smMouseEnabled )
return( false );
mMouseActive = acquire( MouseDeviceType, SI_ANY );
#ifdef LOG_INPUT
Input::log( mMouseActive ? "Mouse activated.\n" : "Mouse failed to activate!\n" );
#endif
return( mMouseActive );
}
//------------------------------------------------------------------------------
void DInputManager::deactivateMouse()
{
if ( mEnabled && mMouseActive )
{
unacquire( MouseDeviceType, SI_ANY );
mMouseActive = false;
#ifdef LOG_INPUT
Input::log( "Mouse deactivated.\n" );
#endif
}
}
//------------------------------------------------------------------------------
bool DInputManager::enableJoystick()
{
DInputManager* mgr = dynamic_cast<DInputManager*>( Input::getManager() );
if ( !mgr || !mgr->isEnabled() )
return( false );
if ( smJoystickEnabled && mgr->isJoystickActive() )
return( true );
smJoystickEnabled = true;
if ( Input::isActive() )
smJoystickEnabled = mgr->activateJoystick();
if ( smJoystickEnabled )
{
Con::printf( "DirectInput joystick enabled." );
#ifdef LOG_INPUT
Input::log( "Joystick enabled.\n" );
#endif
}
else
{
Con::warnf( "DirectInput joystick failed to enable!" );
#ifdef LOG_INPUT
Input::log( "Joystick failed to enable!\n" );
#endif
}
return( smJoystickEnabled );
}
//------------------------------------------------------------------------------
void DInputManager::disableJoystick()
{
DInputManager* mgr = dynamic_cast<DInputManager*>( Input::getManager() );
if ( !mgr || !mgr->isEnabled() || !smJoystickEnabled )
return;
mgr->deactivateJoystick();
smJoystickEnabled = false;
Con::printf( "DirectInput joystick disabled." );
#ifdef LOG_INPUT
Input::log( "Joystick disabled.\n" );
#endif
}
//------------------------------------------------------------------------------
bool DInputManager::isJoystickEnabled()
{
return( smJoystickEnabled );
}
//------------------------------------------------------------------------------
bool DInputManager::activateJoystick()
{
if ( !mEnabled || !Input::isActive() || !smJoystickEnabled )
return( false );
mJoystickActive = acquire( JoystickDeviceType, SI_ANY );
#ifdef LOG_INPUT
Input::log( mJoystickActive ? "Joystick activated.\n" : "Joystick failed to activate!\n" );
#endif
return( mJoystickActive );
}
//------------------------------------------------------------------------------
void DInputManager::deactivateJoystick()
{
if ( mEnabled && mJoystickActive )
{
unacquire( JoystickDeviceType, SI_ANY );
mJoystickActive = false;
#ifdef LOG_INPUT
Input::log( "Joystick deactivated.\n" );
#endif
}
}
//------------------------------------------------------------------------------
const char* DInputManager::getJoystickAxesString( U32 deviceID )
{
DInputDevice* dptr;
for ( iterator ptr = begin(); ptr != end(); ptr++ )
{
dptr = dynamic_cast<DInputDevice*>( *ptr );
if ( dptr && ( dptr->getDeviceType() == JoystickDeviceType ) && ( dptr->getDeviceID() == deviceID ) )
return( dptr->getJoystickAxesString() );
}
return( "" );
}
//------------------------------------------------------------------------------
ConsoleFunction( activateKeyboard, bool, 1, 1, "activateKeyboard()" )
{
argc; argv;
DInputManager* mgr = dynamic_cast<DInputManager*>( Input::getManager() );
if ( mgr )
return( mgr->activateKeyboard() );
return( false );
}
//------------------------------------------------------------------------------
ConsoleFunction( deactivateKeyboard, void, 1, 1, "deactivateKeyboard()" )
{
argc; argv;
DInputManager* mgr = dynamic_cast<DInputManager*>( Input::getManager() );
if ( mgr )
mgr->deactivateKeyboard();
}
//------------------------------------------------------------------------------
ConsoleFunction( enableMouse, bool, 1, 1, "enableMouse()" )
{
argc; argv;
return( DInputManager::enableMouse() );
}
//------------------------------------------------------------------------------
ConsoleFunction( disableMouse, void, 1, 1, "disableMouse()" )
{
argc; argv;
DInputManager::disableMouse();
}
//------------------------------------------------------------------------------
ConsoleFunction( enableJoystick, bool, 1, 1, "enableJoystick()" )
{
argc; argv;
return( DInputManager::enableJoystick() );
}
//------------------------------------------------------------------------------
ConsoleFunction( disableJoystick, void, 1, 1, "disableJoystick()" )
{
argc; argv;
DInputManager::disableJoystick();
}
//------------------------------------------------------------------------------
ConsoleFunction( echoInputState, void, 1, 1, "echoInputState()" )
{
argc; argv;
DInputManager* mgr = dynamic_cast<DInputManager*>( Input::getManager() );
if ( mgr && mgr->isEnabled() )
{
Con::printf( "DirectInput is enabled %s.", Input::isActive() ? "and active" : "but inactive" );
Con::printf( "- Keyboard is %sabled and %sactive.",
mgr->isKeyboardEnabled() ? "en" : "dis",
mgr->isKeyboardActive() ? "" : "in" );
Con::printf( "- Mouse is %sabled and %sactive.",
mgr->isMouseEnabled() ? "en" : "dis",
mgr->isMouseActive() ? "" : "in" );
Con::printf( "- Joystick is %sabled and %sactive.",
mgr->isJoystickEnabled() ? "en" : "dis",
mgr->isJoystickActive() ? "" : "in" );
}
else
Con::printf( "DirectInput is not enabled." );
}

View file

@ -0,0 +1,88 @@
//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#ifndef _WINDIRECTINPUT_H_
#define _WINDIRECTINPUT_H_
#ifndef _PLATFORMWIN32_H_
#include "platformWIN32/platformWin32.h"
#endif
#ifndef _PLATFORMINPUT_H_
#include "platform/platformInput.h"
#endif
#ifndef _WINDINPUTDEVICE_H_
#include "platformWIN32/winDInputDevice.h"
#endif
#include <dinput.h>
struct InputEvent;
//------------------------------------------------------------------------------
class DInputManager : public InputManager
{
private:
typedef SimGroup Parent;
HMODULE mDInputLib;
LPDIRECTINPUT mDInputInterface;
static bool smKeyboardEnabled;
static bool smMouseEnabled;
static bool smJoystickEnabled;
bool mKeyboardActive;
bool mMouseActive;
bool mJoystickActive;
void enumerateDevices();
static BOOL CALLBACK EnumDevicesProc( const DIDEVICEINSTANCE *pddi, LPVOID pvRef );
bool acquire( U8 deviceType, U8 deviceID );
void unacquire( U8 deviceType, U8 deviceID );
public:
DInputManager();
bool enable();
void disable();
void onDeleteNotify( SimObject* object );
bool onAdd();
void onRemove();
void process();
// DirectInput functions:
static void init();
static bool enableKeyboard();
static void disableKeyboard();
static bool isKeyboardEnabled();
bool activateKeyboard();
void deactivateKeyboard();
bool isKeyboardActive() { return( mKeyboardActive ); }
static bool enableMouse();
static void disableMouse();
static bool isMouseEnabled();
bool activateMouse();
void deactivateMouse();
bool isMouseActive() { return( mMouseActive ); }
static bool enableJoystick();
static void disableJoystick();
static bool isJoystickEnabled();
bool activateJoystick();
void deactivateJoystick();
bool isJoystickActive() { return( mJoystickActive ); }
// Console interface:
const char* getJoystickAxesString( U32 deviceID );
};
#endif // _H_WINDIRECTINPUT_

589
platformWin32/winFileio.cc Normal file
View file

@ -0,0 +1,589 @@
//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#include "platformWIN32/platformWin32.h"
#include "core/fileio.h"
#include "core/tVector.h"
#include "core/stringTable.h"
#include "console/console.h"
// Microsoft VC++ has this POSIX header in the wrong directory
#ifdef _MSC_VER
#include <sys/utime.h>
#else
#include <utime.h>
#endif
//-------------------------------------- Helper Functions
static void forwardslash(char *str)
{
while(*str)
{
if(*str == '\\')
*str = '/';
str++;
}
}
static void backslash(char *str)
{
while(*str)
{
if(*str == '/')
*str = '\\';
str++;
}
}
//-----------------------------------------------------------------------------
bool dFileDelete(const char * name)
{
if(!name || (dStrlen(name) >= MAX_PATH))
return(false);
return(::DeleteFile(name));
}
bool dFileTouch(const char * name)
{
// change the modified time to the current time (0byte WriteFile fails!)
return(utime(name, 0) != -1);
}
//-----------------------------------------------------------------------------
// Constructors & Destructor
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// After construction, the currentStatus will be Closed and the capabilities
// will be 0.
//-----------------------------------------------------------------------------
File::File()
: currentStatus(Closed), capability(0)
{
AssertFatal(sizeof(HANDLE) == sizeof(void *), "File::File: cannot cast void* to HANDLE");
handle = (void *)INVALID_HANDLE_VALUE;
}
//-----------------------------------------------------------------------------
// insert a copy constructor here... (currently disabled)
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Destructor
//-----------------------------------------------------------------------------
File::~File()
{
close();
handle = (void *)INVALID_HANDLE_VALUE;
}
//-----------------------------------------------------------------------------
// Open a file in the mode specified by openMode (Read, Write, or ReadWrite).
// Truncate the file if the mode is either Write or ReadWrite and truncate is
// true.
//
// Sets capability appropriate to the openMode.
// Returns the currentStatus of the file.
//-----------------------------------------------------------------------------
File::Status File::open(const char *filename, const AccessMode openMode)
{
static char filebuf[2048];
dStrcpy(filebuf, filename);
backslash(filebuf);
filename = filebuf;
AssertFatal(NULL != filename, "File::open: NULL filename");
AssertWarn(INVALID_HANDLE_VALUE == (HANDLE)handle, "File::open: handle already valid");
// Close the file if it was already open...
if (Closed != currentStatus)
close();
// create the appropriate type of file...
switch (openMode)
{
case Read:
handle = (void *)CreateFile(filename,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
NULL);
break;
case Write:
handle = (void *)CreateFile(filename,
GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
NULL);
break;
case ReadWrite:
handle = (void *)CreateFile(filename,
GENERIC_WRITE | GENERIC_READ,
0,
NULL,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
NULL);
break;
case WriteAppend:
handle = (void *)CreateFile(filename,
GENERIC_WRITE,
0,
NULL,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
NULL);
break;
default:
AssertFatal(false, "File::open: bad access mode"); // impossible
}
if (INVALID_HANDLE_VALUE == (HANDLE)handle) // handle not created successfully
return setStatus();
else
{
// successfully created file, so set the file capabilities...
switch (openMode)
{
case Read:
capability = U32(FileRead);
break;
case Write:
case WriteAppend:
capability = U32(FileWrite);
break;
case ReadWrite:
capability = U32(FileRead) |
U32(FileWrite);
break;
default:
AssertFatal(false, "File::open: bad access mode");
}
return currentStatus = Ok; // success!
}
}
//-----------------------------------------------------------------------------
// Get the current position of the file pointer.
//-----------------------------------------------------------------------------
U32 File::getPosition() const
{
AssertFatal(Closed != currentStatus, "File::getPosition: file closed");
AssertFatal(INVALID_HANDLE_VALUE != (HANDLE)handle, "File::getPosition: invalid file handle");
return SetFilePointer((HANDLE)handle,
0, // how far to move
NULL, // pointer to high word
FILE_CURRENT); // from what point
}
//-----------------------------------------------------------------------------
// Set the position of the file pointer.
// Absolute and relative positioning is supported via the absolutePos
// parameter.
//
// If positioning absolutely, position MUST be positive - an IOError results if
// position is negative.
// Position can be negative if positioning relatively, however positioning
// before the start of the file is an IOError.
//
// Returns the currentStatus of the file.
//-----------------------------------------------------------------------------
File::Status File::setPosition(S32 position, bool absolutePos)
{
AssertFatal(Closed != currentStatus, "File::setPosition: file closed");
AssertFatal(INVALID_HANDLE_VALUE != (HANDLE)handle, "File::setPosition: invalid file handle");
if (Ok != currentStatus && EOS != currentStatus)
return currentStatus;
U32 finalPos;
switch (absolutePos)
{
case true: // absolute position
AssertFatal(0 <= position, "File::setPosition: negative absolute position");
// position beyond EOS is OK
finalPos = SetFilePointer((HANDLE)handle,
position,
NULL,
FILE_BEGIN);
break;
case false: // relative position
AssertFatal((getPosition() >= (U32)abs(position) && 0 > position) || 0 <= position, "File::setPosition: negative relative position");
// position beyond EOS is OK
finalPos = SetFilePointer((HANDLE)handle,
position,
NULL,
FILE_CURRENT);
}
if (0xffffffff == finalPos)
return setStatus(); // unsuccessful
else if (finalPos >= getSize())
return currentStatus = EOS; // success, at end of file
else
return currentStatus = Ok; // success!
}
//-----------------------------------------------------------------------------
// Get the size of the file in bytes.
// It is an error to query the file size for a Closed file, or for one with an
// error status.
//-----------------------------------------------------------------------------
U32 File::getSize() const
{
AssertWarn(Closed != currentStatus, "File::getSize: file closed");
AssertFatal(INVALID_HANDLE_VALUE != (HANDLE)handle, "File::getSize: invalid file handle");
if (Ok == currentStatus || EOS == currentStatus)
{
DWORD high;
return GetFileSize((HANDLE)handle, &high); // success!
}
else
return 0; // unsuccessful
}
//-----------------------------------------------------------------------------
// Flush the file.
// It is an error to flush a read-only file.
// Returns the currentStatus of the file.
//-----------------------------------------------------------------------------
File::Status File::flush()
{
AssertFatal(Closed != currentStatus, "File::flush: file closed");
AssertFatal(INVALID_HANDLE_VALUE != (HANDLE)handle, "File::flush: invalid file handle");
AssertFatal(true == hasCapability(FileWrite), "File::flush: cannot flush a read-only file");
if (0 != FlushFileBuffers((HANDLE)handle))
return setStatus(); // unsuccessful
else
return currentStatus = Ok; // success!
}
//-----------------------------------------------------------------------------
// Close the File.
//
// Returns the currentStatus
//-----------------------------------------------------------------------------
File::Status File::close()
{
// check if it's already closed...
if (Closed == currentStatus)
return currentStatus;
// it's not, so close it...
if (INVALID_HANDLE_VALUE != (HANDLE)handle)
{
if (0 == CloseHandle((HANDLE)handle))
return setStatus(); // unsuccessful
}
handle = (void *)INVALID_HANDLE_VALUE;
return currentStatus = Closed;
}
//-----------------------------------------------------------------------------
// Self-explanatory.
//-----------------------------------------------------------------------------
File::Status File::getStatus() const
{
return currentStatus;
}
//-----------------------------------------------------------------------------
// Sets and returns the currentStatus when an error has been encountered.
//-----------------------------------------------------------------------------
File::Status File::setStatus()
{
switch (GetLastError())
{
case ERROR_INVALID_HANDLE:
case ERROR_INVALID_ACCESS:
case ERROR_TOO_MANY_OPEN_FILES:
case ERROR_FILE_NOT_FOUND:
case ERROR_SHARING_VIOLATION:
case ERROR_HANDLE_DISK_FULL:
return currentStatus = IOError;
default:
return currentStatus = UnknownError;
}
}
//-----------------------------------------------------------------------------
// Sets and returns the currentStatus to status.
//-----------------------------------------------------------------------------
File::Status File::setStatus(File::Status status)
{
return currentStatus = status;
}
//-----------------------------------------------------------------------------
// Read from a file.
// The number of bytes to read is passed in size, the data is returned in src.
// The number of bytes read is available in bytesRead if a non-Null pointer is
// provided.
//-----------------------------------------------------------------------------
File::Status File::read(U32 size, char *dst, U32 *bytesRead)
{
AssertFatal(Closed != currentStatus, "File::read: file closed");
AssertFatal(INVALID_HANDLE_VALUE != (HANDLE)handle, "File::read: invalid file handle");
AssertFatal(NULL != dst, "File::read: NULL destination pointer");
AssertFatal(true == hasCapability(FileRead), "File::read: file lacks capability");
AssertWarn(0 != size, "File::read: size of zero");
if (Ok != currentStatus || 0 == size)
return currentStatus;
else
{
DWORD lastBytes;
DWORD *bytes = (NULL == bytesRead) ? &lastBytes : (DWORD *)bytesRead;
if (0 != ReadFile((HANDLE)handle, dst, size, bytes, NULL))
{
if(*((U32 *)bytes) != size)
return currentStatus = EOS; // end of stream
}
else
return setStatus(); // unsuccessful
}
return currentStatus = Ok; // successfully read size bytes
}
//-----------------------------------------------------------------------------
// Write to a file.
// The number of bytes to write is passed in size, the data is passed in src.
// The number of bytes written is available in bytesWritten if a non-Null
// pointer is provided.
//-----------------------------------------------------------------------------
File::Status File::write(U32 size, const char *src, U32 *bytesWritten)
{
AssertFatal(Closed != currentStatus, "File::write: file closed");
AssertFatal(INVALID_HANDLE_VALUE != (HANDLE)handle, "File::write: invalid file handle");
AssertFatal(NULL != src, "File::write: NULL source pointer");
AssertFatal(true == hasCapability(FileWrite), "File::write: file lacks capability");
AssertWarn(0 != size, "File::write: size of zero");
if ((Ok != currentStatus && EOS != currentStatus) || 0 == size)
return currentStatus;
else
{
DWORD lastBytes;
DWORD *bytes = (NULL == bytesWritten) ? &lastBytes : (DWORD *)bytesWritten;
if (0 != WriteFile((HANDLE)handle, src, size, bytes, NULL))
return currentStatus = Ok; // success!
else
return setStatus(); // unsuccessful
}
}
//-----------------------------------------------------------------------------
// Self-explanatory.
//-----------------------------------------------------------------------------
bool File::hasCapability(Capability cap) const
{
return (0 != (U32(cap) & capability));
}
S32 Platform::compareFileTimes(const FileTime &a, const FileTime &b)
{
if(a.v2 > b.v2)
return 1;
if(a.v2 < b.v2)
return -1;
if(a.v1 > b.v1)
return 1;
if(a.v1 < b.v1)
return -1;
return 0;
}
static bool _recurseDumpPath(const char* in_pBasePath,
const char* in_pCurPath,
Vector<Platform::FileInfo>& out_rFileVector)
{
char buf[1024];
char curPath[1024];
char basePath[1024];
char scratchBuf[1024];
if(in_pCurPath)
dStrcpy(curPath, in_pCurPath);
else
curPath[0] = 0;
dStrcpy(basePath, in_pBasePath);
in_pBasePath = basePath;
if (curPath[0] != '\0')
dSprintf(buf, sizeof(buf), "%s/%s/*", basePath, curPath);
else
dSprintf(buf, sizeof(buf), "%s/*", basePath);
WIN32_FIND_DATA findData;
backslash(buf);
HANDLE hFind = FindFirstFile(buf, &findData);
if (hFind == INVALID_HANDLE_VALUE)
return false;
while (hFind != INVALID_HANDLE_VALUE) {
if ((findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) {
// Directory
if (findData.cFileName[0] != '.') {
scratchBuf[0] = '\0';
if (curPath[0] != '\0') {
dStrcpy(scratchBuf, curPath);
dStrcat(scratchBuf, "/");
}
dStrcat(scratchBuf, findData.cFileName);
_recurseDumpPath(basePath, scratchBuf, out_rFileVector);
}
} else {
// File
out_rFileVector.increment();
Platform::FileInfo& rInfo = out_rFileVector.last();
if (curPath[0] != '\0') {
dSprintf(scratchBuf, sizeof(scratchBuf), "%s/%s", basePath, curPath);
rInfo.pFullPath = StringTable->insert(scratchBuf);
rInfo.pVirtPath = StringTable->insert(curPath);
} else {
rInfo.pFullPath = StringTable->insert(basePath);
rInfo.pVirtPath = NULL;
}
rInfo.pFileName = StringTable->insert(findData.cFileName);
rInfo.fileSize = findData.nFileSizeLow;
}
if(FindNextFile(hFind, &findData) == FALSE) {
FindClose(hFind);
hFind = INVALID_HANDLE_VALUE;
}
}
return true;
}
//--------------------------------------
bool Platform::getFileTimes(const char *filePath, FileTime *createTime, FileTime *modifyTime)
{
WIN32_FIND_DATA findData;
HANDLE h = FindFirstFile(filePath, &findData);
if(h == INVALID_HANDLE_VALUE)
return false;
if(createTime)
{
createTime->v1 = findData.ftCreationTime.dwLowDateTime;
createTime->v2 = findData.ftCreationTime.dwHighDateTime;
}
if(modifyTime)
{
modifyTime->v1 = findData.ftLastWriteTime.dwLowDateTime;
modifyTime->v2 = findData.ftLastWriteTime.dwHighDateTime;
}
FindClose(h);
return true;
}
//--------------------------------------
bool Platform::createPath(const char *file)
{
char pathbuf[1024];
const char *dir;
pathbuf[0] = 0;
U32 pathLen = 0;
while((dir = dStrchr(file, '/')) != NULL)
{
dStrncpy(pathbuf + pathLen, file, dir - file);
pathbuf[pathLen + dir-file] = 0;
bool ret = CreateDirectory(pathbuf, NULL);
pathLen += dir - file;
pathbuf[pathLen++] = '/';
file = dir + 1;
}
return true;
}
bool Platform::cdFileExists(const char *filePath, const char *volumeName, S32 serialNum)
{
if (!filePath || !filePath[0])
return true;
//first find the CD device...
char fileBuf[256];
char drivesBuf[256];
S32 length = GetLogicalDriveStrings(256, drivesBuf);
char *drivePtr = drivesBuf;
while (S32(drivePtr - drivesBuf) < length)
{
char driveVolume[256], driveFileSystem[256];
U32 driveSerial, driveFNLength, driveFlags;
if ((dStricmp(drivePtr, "A:\\") != 0 && dStricmp(drivePtr, "B:\\") != 0) &&
GetVolumeInformation((const char*)drivePtr, &driveVolume[0], (unsigned long)255,
(unsigned long*)&driveSerial, (unsigned long*)&driveFNLength,
(unsigned long*)&driveFlags, &driveFileSystem[0], (unsigned long)255))
{
#if defined (DEBUG) || defined (INTERNAL_RELEASE)
Con::printf("Found Drive: %s, vol: %s, serial: %d", drivePtr, driveVolume, driveSerial);
#endif
//see if the volume and serial number match
if (!dStricmp(volumeName, driveVolume) && (!serialNum || (serialNum == driveSerial)))
{
//see if the file exists on this volume
if(dStrlen(drivePtr) == 3 && drivePtr[2] == '\\' && filePath[0] == '\\')
dSprintf(fileBuf, sizeof(fileBuf), "%s%s", drivePtr, filePath + 1);
else
dSprintf(fileBuf, sizeof(fileBuf), "%s%s", drivePtr, filePath);
#if defined (DEBUG) || defined (INTERNAL_RELEASE)
Con::printf("Looking for file: %s on %s", fileBuf, driveVolume);
#endif
WIN32_FIND_DATA findData;
HANDLE h = FindFirstFile(fileBuf, &findData);
if(h != INVALID_HANDLE_VALUE)
{
FindClose(h);
return true;
}
FindClose(h);
}
}
//check the next drive
drivePtr += dStrlen(drivePtr) + 1;
}
return false;
}
//--------------------------------------
bool Platform::dumpPath(const char *in_pBasePath, Vector<Platform::FileInfo>& out_rFileVector)
{
return _recurseDumpPath(in_pBasePath, NULL, out_rFileVector);
}
//--------------------------------------
void Platform::getCurrentDirectory(char *dirBuf, const U32 in_bufferSize)
{
GetCurrentDirectory(in_bufferSize - 1, dirBuf);
forwardslash(dirBuf);
}

133
platformWin32/winFont.cc Normal file
View file

@ -0,0 +1,133 @@
//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#include "PlatformWin32/platformWin32.h"
#include "dgl/gFont.h"
#include "dgl/gBitmap.h"
#include "Math/mRect.h"
#include "console/console.h"
static HDC fontHDC = NULL;
static HBITMAP fontBMP = NULL;
void createFontInit(void);
void createFontShutdown(void);
void CopyCharToBitmap(GBitmap *pDstBMP, HDC hSrcHDC, const RectI &r);
void createFontInit()
{
fontHDC = CreateCompatibleDC(NULL);
fontBMP = CreateCompatibleBitmap(fontHDC, 256, 256);
}
void createFontShutdown()
{
DeleteObject(fontBMP);
DeleteObject(fontHDC);
}
void CopyCharToBitmap(GBitmap *pDstBMP, HDC hSrcHDC, const RectI &r)
{
for (S32 i = r.point.y; i < r.point.y + r.extent.y; i++)
{
for (S32 j = r.point.x; j < r.point.x + r.extent.x; j++)
{
COLORREF color = GetPixel(hSrcHDC, j, i);
if (color)
*pDstBMP->getAddress(j, i) = 255;
else
*pDstBMP->getAddress(j, i) = 0;
}
}
}
GFont *createFont(const char *name, S32 size)
{
if(!name)
return NULL;
if(size < 1)
return NULL;
HFONT hNewFont = CreateFont(size,0,0,0,0,0,0,0,0,0,0,0,0,name);
if(!hNewFont)
return NULL;
GFont *retFont = new GFont;
static U8 scratchPad[65536];
TEXTMETRIC textMetric;
COLORREF backgroundColorRef = RGB( 0, 0, 0);
COLORREF foregroundColorRef = RGB(255, 255, 255);
SelectObject(fontHDC, fontBMP);
SelectObject(fontHDC, hNewFont);
SetBkColor(fontHDC, backgroundColorRef);
SetTextColor(fontHDC, foregroundColorRef);
GetTextMetrics(fontHDC, &textMetric);
MAT2 matrix;
GLYPHMETRICS metrics;
RectI clip;
FIXED zero;
zero.fract = 0;
zero.value = 0;
FIXED one;
one.fract = 0;
one.value = 1;
matrix.eM11 = one;
matrix.eM12 = zero;
matrix.eM21 = zero;
matrix.eM22 = one;
S32 glyphCount = 0;
for(S32 i = 32; i < 256; i++)
{
if(GetGlyphOutline(
fontHDC, // handle of device context
i, // character to query
GGO_GRAY8_BITMAP, // format of data to return
&metrics, // address of structure for metrics
sizeof(scratchPad), // size of buffer for data
scratchPad, // address of buffer for data
&matrix // address of transformation matrix structure
) != GDI_ERROR)
{
glyphCount++;
U32 rowStride = (metrics.gmBlackBoxX + 3) & ~3; // DWORD aligned
U32 size = rowStride * metrics.gmBlackBoxY;
for(U32 j = 0; j < size; j++)
{
U32 pad = U32(scratchPad[j]) << 2;
if(pad > 255)
pad = 255;
scratchPad[j] = pad;
}
S32 inc = metrics.gmCellIncX;
if(inc < 0)
inc = -inc;
retFont->insertBitmap(i, scratchPad, rowStride, metrics.gmBlackBoxX, metrics.gmBlackBoxY, metrics.gmptGlyphOrigin.x, metrics.gmptGlyphOrigin.y, metrics.gmCellIncX);
}
else
{
char b = i;
SIZE size;
GetTextExtentPoint32(fontHDC, &b, 1, &size);
if(size.cx)
retFont->insertBitmap(i, scratchPad, 0, 0, 0, 0, 0, size.cx);
}
}
retFont->pack(textMetric.tmHeight, textMetric.tmAscent);
//clean up local vars
DeleteObject(hNewFont);
if (!glyphCount)
Con::errorf(ConsoleLogEntry::General,"Error creating font: %s %d",name, size);
return retFont;
}

5948
platformWin32/winGL.cc Normal file

File diff suppressed because it is too large Load diff

808
platformWin32/winInput.cc Normal file
View file

@ -0,0 +1,808 @@
//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#include "platformWIN32/platformWin32.h"
#include "platform/platformInput.h"
#include "platform/platformVideo.h"
#include "platformWIN32/winDirectInput.h"
#include "platform/event.h"
#include "console/console.h"
#ifdef LOG_INPUT
#include <time.h>
#include <stdarg.h>
#endif
// Static class variables:
InputManager* Input::smManager;
bool Input::smActive;
#ifdef LOG_INPUT
static HANDLE gInputLog;
#endif
static void fillAsciiTable();
//------------------------------------------------------------------------------
//
// This function gets the standard ASCII code corresponding to our key code
// and the existing modifier key state.
//
//------------------------------------------------------------------------------
struct AsciiData
{
struct KeyData
{
U16 ascii;
bool isDeadChar;
};
KeyData upper;
KeyData lower;
KeyData goofy;
};
#define NUM_KEYS ( KEY_OEM_102 + 1 )
#define KEY_FIRST KEY_ESCAPE
static AsciiData AsciiTable[NUM_KEYS];
//------------------------------------------------------------------------------
void Input::init()
{
Con::printf( "Input Init:" );
destroy();
#ifdef LOG_INPUT
struct tm* newTime;
time_t aclock;
time( &aclock );
newTime = localtime( &aclock );
asctime( newTime );
gInputLog = CreateFile( "input.log", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
log( "Input log opened at %s\n", asctime( newTime ) );
#endif
smActive = false;
OSVERSIONINFO OSVersionInfo;
dMemset( &OSVersionInfo, 0, sizeof( OSVERSIONINFO ) );
OSVersionInfo.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
if ( GetVersionEx( &OSVersionInfo ) )
{
#ifdef LOG_INPUT
log( "Operating System:\n" );
switch ( OSVersionInfo.dwPlatformId )
{
case VER_PLATFORM_WIN32s:
log( " Win32s on Windows 3.1 version %d.%d\n", OSVersionInfo.dwMajorVersion, OSVersionInfo.dwMinorVersion );
break;
case VER_PLATFORM_WIN32_WINDOWS:
log( " Windows 95 version %d.%d\n", OSVersionInfo.dwMajorVersion, OSVersionInfo.dwMinorVersion );
log( " Build number %d\n", LOWORD( OSVersionInfo.dwBuildNumber ) );
break;
case VER_PLATFORM_WIN32_NT:
log( " WinNT version %d.%d\n", OSVersionInfo.dwMajorVersion, OSVersionInfo.dwMinorVersion );
log( " Build number %d\n", OSVersionInfo.dwBuildNumber );
break;
}
if ( OSVersionInfo.szCSDVersion != NULL )
log( " %s\n", OSVersionInfo.szCSDVersion );
log( "\n" );
#endif
if ( !( OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT && OSVersionInfo.dwMajorVersion < 5 ) )
{
smManager = new DInputManager;
if ( !smManager->enable() )
{
Con::printf( " DirectInput not enabled." );
delete smManager;
smManager = NULL;
}
else
{
DInputManager::init();
Con::printf( " DirectInput enabled." );
}
}
else
Con::printf( " WinNT detected -- DirectInput not enabled." );
}
fillAsciiTable();
Con::printf( "" );
}
//------------------------------------------------------------------------------
ConsoleFunction( isJoystickDetected, bool, 1, 1, "isJoystickDetected()" )
{
argc; argv;
return( DInputDevice::joystickDetected() );
}
//------------------------------------------------------------------------------
ConsoleFunction( getJoystickAxes, const char*, 2, 2, "getJoystickAxes( instance )" )
{
argc;
DInputManager* mgr = dynamic_cast<DInputManager*>( Input::getManager() );
if ( mgr )
return( mgr->getJoystickAxesString( dAtoi( argv[1] ) ) );
return( "" );
}
//------------------------------------------------------------------------------
static void fillAsciiTable()
{
#ifdef LOG_INPUT
char buf[256];
Input::log( "--- Filling the ASCII table! ---\n" );
#endif
//HKL layout = GetKeyboardLayout( 0 );
U8 state[256];
U16 ascii[2];
U32 dikCode, vKeyCode, keyCode;
S32 result;
dMemset( &AsciiTable, 0, sizeof( AsciiTable ) );
dMemset( &state, 0, sizeof( state ) );
for ( keyCode = KEY_FIRST; keyCode < NUM_KEYS; keyCode++ )
{
ascii[0] = ascii[1] = 0;
dikCode = Key_to_DIK( keyCode );
if ( dikCode )
{
//vKeyCode = MapVirtualKeyEx( dikCode, 1, layout );
vKeyCode = MapVirtualKey( dikCode, 1 );
#ifdef LOG_INPUT
dSprintf( buf, sizeof( buf ), "KC: %#04X DK: %#04X VK: %#04X\n",
keyCode, dikCode, vKeyCode );
Input::log( buf );
#endif
// Lower case:
ascii[0] = ascii[1] = 0;
//result = ToAsciiEx( vKeyCode, dikCode, state, ascii, 0, layout );
result = ToAscii( vKeyCode, dikCode, state, ascii, 0 );
#ifdef LOG_INPUT
dSprintf( buf, sizeof( buf ), " LOWER- R: %d A[0]: %#06X A[1]: %#06X\n",
result, ascii[0], ascii[1] );
Input::log( buf );
#endif
if ( result == 2 )
AsciiTable[keyCode].lower.ascii = ascii[1] ? ascii[1] : ( ascii[0] >> 8 );
else if ( result == 1 )
AsciiTable[keyCode].lower.ascii = ascii[0];
else if ( result < 0 )
{
AsciiTable[keyCode].lower.ascii = ascii[0];
AsciiTable[keyCode].lower.isDeadChar = true;
// Need to clear the dead character from the keyboard layout:
//ToAsciiEx( vKeyCode, dikCode, state, ascii, 0, layout );
ToAscii( vKeyCode, dikCode, state, ascii, 0 );
}
// Upper case:
ascii[0] = ascii[1] = 0;
state[VK_SHIFT] = 0x80;
//result = ToAsciiEx( vKeyCode, dikCode, state, ascii, 0, layout );
result = ToAscii( vKeyCode, dikCode, state, ascii, 0 );
#ifdef LOG_INPUT
dSprintf( buf, sizeof( buf ), " UPPER- R: %d A[0]: %#06X A[1]: %#06X\n",
result, ascii[0], ascii[1] );
Input::log( buf );
#endif
if ( result == 2 )
AsciiTable[keyCode].upper.ascii = ascii[1] ? ascii[1] : ( ascii[0] >> 8 );
else if ( result == 1 )
AsciiTable[keyCode].upper.ascii = ascii[0];
else if ( result < 0 )
{
AsciiTable[keyCode].upper.ascii = ascii[0];
AsciiTable[keyCode].upper.isDeadChar = true;
// Need to clear the dead character from the keyboard layout:
//ToAsciiEx( vKeyCode, dikCode, state, ascii, 0, layout );
ToAscii( vKeyCode, dikCode, state, ascii, 0 );
}
state[VK_SHIFT] = 0;
// Foreign mod case:
ascii[0] = ascii[1] = 0;
state[VK_CONTROL] = 0x80;
state[VK_MENU] = 0x80;
//result = ToAsciiEx( vKeyCode, dikCode, state, ascii, 0, layout );
result = ToAscii( vKeyCode, dikCode, state, ascii, 0 );
#ifdef LOG_INPUT
dSprintf( buf, sizeof( buf ), " GOOFY- R: %d A[0]: %#06X A[1]: %#06X\n",
result, ascii[0], ascii[1] );
Input::log( buf );
#endif
if ( result == 2 )
AsciiTable[keyCode].goofy.ascii = ascii[1] ? ascii[1] : ( ascii[0] >> 8 );
else if ( result == 1 )
AsciiTable[keyCode].goofy.ascii = ascii[0];
else if ( result < 0 )
{
AsciiTable[keyCode].goofy.ascii = ascii[0];
AsciiTable[keyCode].goofy.isDeadChar = true;
// Need to clear the dead character from the keyboard layout:
//ToAsciiEx( vKeyCode, dikCode, state, ascii, 0, layout );
ToAscii( vKeyCode, dikCode, state, ascii, 0 );
}
state[VK_CONTROL] = 0;
state[VK_MENU] = 0;
}
}
#ifdef LOG_INPUT
Input::log( "--- Finished filling the ASCII table! ---\n\n" );
#endif
}
//------------------------------------------------------------------------------
U16 Input::getKeyCode( U16 asciiCode )
{
U16 keyCode = 0;
U16 i;
// This is done three times so the lowerkey will always
// be found first. Some foreign keyboards have duplicate
// chars on some keys.
for ( i = KEY_FIRST; i < NUM_KEYS && !keyCode; i++ )
{
if ( AsciiTable[i].lower.ascii == asciiCode )
{
keyCode = i;
break;
};
}
for ( i = KEY_FIRST; i < NUM_KEYS && !keyCode; i++ )
{
if ( AsciiTable[i].upper.ascii == asciiCode )
{
keyCode = i;
break;
};
}
for ( i = KEY_FIRST; i < NUM_KEYS && !keyCode; i++ )
{
if ( AsciiTable[i].goofy.ascii == asciiCode )
{
keyCode = i;
break;
};
}
return( keyCode );
}
//------------------------------------------------------------------------------
U16 Input::getAscii( U16 keyCode, KEY_STATE keyState )
{
if ( keyCode >= NUM_KEYS )
return 0;
switch ( keyState )
{
case STATE_LOWER:
return AsciiTable[keyCode].lower.ascii;
case STATE_UPPER:
return AsciiTable[keyCode].upper.ascii;
case STATE_GOOFY:
return AsciiTable[keyCode].goofy.ascii;
default:
return(0);
}
}
//------------------------------------------------------------------------------
void Input::destroy()
{
#ifdef LOG_INPUT
if ( gInputLog )
{
log( "*** CLOSING LOG ***\n" );
CloseHandle( gInputLog );
gInputLog = NULL;
}
#endif
if ( smManager && smManager->isEnabled() )
{
smManager->disable();
delete smManager;
smManager = NULL;
}
}
//------------------------------------------------------------------------------
bool Input::enable()
{
if ( smManager && !smManager->isEnabled() )
return( smManager->enable() );
return( false );
}
//------------------------------------------------------------------------------
void Input::disable()
{
if ( smManager && smManager->isEnabled() )
smManager->disable();
}
//------------------------------------------------------------------------------
void Input::activate()
{
DInputDevice::resetModifierKeys();
if ( !Con::getBoolVariable( "$enableDirectInput" ) )
return;
if ( smManager && smManager->isEnabled() && !smActive )
{
Con::printf( "Activating DirectInput..." );
#ifdef LOG_INPUT
Input::log( "Activating DirectInput...\n" );
#endif
smActive = true;
DInputManager* dInputManager = dynamic_cast<DInputManager*>( smManager );
if ( dInputManager )
{
if ( dInputManager->isKeyboardEnabled() )
dInputManager->activateKeyboard();
if ( Video::isFullScreen() )
{
// DirectInput Mouse Hook-Up:
if ( dInputManager->isMouseEnabled() )
dInputManager->activateMouse();
}
else
dInputManager->deactivateMouse();
if ( dInputManager->isJoystickEnabled() )
dInputManager->activateJoystick();
}
}
}
//------------------------------------------------------------------------------
void Input::deactivate()
{
if ( smManager && smManager->isEnabled() && smActive )
{
#ifdef LOG_INPUT
Input::log( "Deactivating DirectInput...\n" );
#endif
DInputManager* dInputManager = dynamic_cast<DInputManager*>( smManager );
if ( dInputManager )
{
dInputManager->deactivateKeyboard();
dInputManager->deactivateMouse();
dInputManager->deactivateJoystick();
}
smActive = false;
Con::printf( "DirectInput deactivated." );
}
}
//------------------------------------------------------------------------------
void Input::reactivate()
{
// This is soo hacky...
SetForegroundWindow( winState.appWindow );
PostMessage( winState.appWindow, WM_ACTIVATE, WA_ACTIVE, NULL );
}
//------------------------------------------------------------------------------
bool Input::isEnabled()
{
if ( smManager )
return smManager->isEnabled();
return false;
}
//------------------------------------------------------------------------------
bool Input::isActive()
{
return smActive;
}
//------------------------------------------------------------------------------
void Input::process()
{
if ( smManager && smManager->isEnabled() && smActive )
smManager->process();
}
//------------------------------------------------------------------------------
InputManager* Input::getManager()
{
return( smManager );
}
#ifdef LOG_INPUT
//------------------------------------------------------------------------------
void Input::log( const char* format, ... )
{
if ( !gInputLog )
return;
va_list argptr;
va_start( argptr, format );
char buffer[512];
dVsprintf( buffer, 511, format, argptr );
DWORD bytes;
WriteFile( gInputLog, buffer, dStrlen( buffer ), &bytes, NULL );
va_end( argptr );
}
ConsoleFunction( inputLog, void, 2, 2, "inputLog( string )" )
{
argc;
Input::log( "%s\n", argv[1] );
}
#endif // LOG_INPUT
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
static U8 VcodeRemap[256] =
{
0, // 0x00
0, // 0x01 VK_LBUTTON
0, // 0x02 VK_RBUTTON
0, // 0x03 VK_CANCEL
0, // 0x04 VK_MBUTTON
0, // 0x05
0, // 0x06
0, // 0x07
KEY_BACKSPACE, // 0x08 VK_BACK
KEY_TAB, // 0x09 VK_TAB
0, // 0x0A
0, // 0x0B
0, // 0x0C VK_CLEAR
KEY_RETURN, // 0x0D VK_RETURN
0, // 0x0E
0, // 0x0F
KEY_SHIFT, // 0x10 VK_SHIFT
KEY_CONTROL, // 0x11 VK_CONTROL
KEY_ALT, // 0x12 VK_MENU
KEY_PAUSE, // 0x13 VK_PAUSE
KEY_CAPSLOCK, // 0x14 VK_CAPITAL
0, // 0x15 VK_KANA, VK_HANGEUL, VK_HANGUL
0, // 0x16
0, // 0x17 VK_JUNJA
0, // 0x18 VK_FINAL
0, // 0x19 VK_HANJA, VK_KANJI
0, // 0x1A
KEY_ESCAPE, // 0x1B VK_ESCAPE
0, // 0x1C VK_CONVERT
0, // 0x1D VK_NONCONVERT
0, // 0x1E VK_ACCEPT
0, // 0x1F VK_MODECHANGE
KEY_SPACE, // 0x20 VK_SPACE
KEY_PAGE_UP, // 0x21 VK_PRIOR
KEY_PAGE_DOWN, // 0x22 VK_NEXT
KEY_END, // 0x23 VK_END
KEY_HOME, // 0x24 VK_HOME
KEY_LEFT, // 0x25 VK_LEFT
KEY_UP, // 0x26 VK_UP
KEY_RIGHT, // 0x27 VK_RIGHT
KEY_DOWN, // 0x28 VK_DOWN
0, // 0x29 VK_SELECT
KEY_PRINT, // 0x2A VK_PRINT
0, // 0x2B VK_EXECUTE
0, // 0x2C VK_SNAPSHOT
KEY_INSERT, // 0x2D VK_INSERT
KEY_DELETE, // 0x2E VK_DELETE
KEY_HELP, // 0x2F VK_HELP
KEY_0, // 0x30 VK_0 VK_0 thru VK_9 are the same as ASCII '0' thru '9' (// 0x30 - // 0x39)
KEY_1, // 0x31 VK_1
KEY_2, // 0x32 VK_2
KEY_3, // 0x33 VK_3
KEY_4, // 0x34 VK_4
KEY_5, // 0x35 VK_5
KEY_6, // 0x36 VK_6
KEY_7, // 0x37 VK_7
KEY_8, // 0x38 VK_8
KEY_9, // 0x39 VK_9
0, // 0x3A
0, // 0x3B
0, // 0x3C
0, // 0x3D
0, // 0x3E
0, // 0x3F
0, // 0x40
KEY_A, // 0x41 VK_A VK_A thru VK_Z are the same as ASCII 'A' thru 'Z' (// 0x41 - // 0x5A)
KEY_B, // 0x42 VK_B
KEY_C, // 0x43 VK_C
KEY_D, // 0x44 VK_D
KEY_E, // 0x45 VK_E
KEY_F, // 0x46 VK_F
KEY_G, // 0x47 VK_G
KEY_H, // 0x48 VK_H
KEY_I, // 0x49 VK_I
KEY_J, // 0x4A VK_J
KEY_K, // 0x4B VK_K
KEY_L, // 0x4C VK_L
KEY_M, // 0x4D VK_M
KEY_N, // 0x4E VK_N
KEY_O, // 0x4F VK_O
KEY_P, // 0x50 VK_P
KEY_Q, // 0x51 VK_Q
KEY_R, // 0x52 VK_R
KEY_S, // 0x53 VK_S
KEY_T, // 0x54 VK_T
KEY_U, // 0x55 VK_U
KEY_V, // 0x56 VK_V
KEY_W, // 0x57 VK_W
KEY_X, // 0x58 VK_X
KEY_Y, // 0x59 VK_Y
KEY_Z, // 0x5A VK_Z
KEY_WIN_LWINDOW, // 0x5B VK_LWIN
KEY_WIN_RWINDOW, // 0x5C VK_RWIN
KEY_WIN_APPS, // 0x5D VK_APPS
0, // 0x5E
0, // 0x5F
KEY_NUMPAD0, // 0x60 VK_NUMPAD0
KEY_NUMPAD1, // 0x61 VK_NUMPAD1
KEY_NUMPAD2, // 0x62 VK_NUMPAD2
KEY_NUMPAD3, // 0x63 VK_NUMPAD3
KEY_NUMPAD4, // 0x64 VK_NUMPAD4
KEY_NUMPAD5, // 0x65 VK_NUMPAD5
KEY_NUMPAD6, // 0x66 VK_NUMPAD6
KEY_NUMPAD7, // 0x67 VK_NUMPAD7
KEY_NUMPAD8, // 0x68 VK_NUMPAD8
KEY_NUMPAD9, // 0x69 VK_NUMPAD9
KEY_MULTIPLY, // 0x6A VK_MULTIPLY
KEY_ADD, // 0x6B VK_ADD
KEY_SEPARATOR, // 0x6C VK_SEPARATOR
KEY_SUBTRACT, // 0x6D VK_SUBTRACT
KEY_DECIMAL, // 0x6E VK_DECIMAL
KEY_DIVIDE, // 0x6F VK_DIVIDE
KEY_F1, // 0x70 VK_F1
KEY_F2, // 0x71 VK_F2
KEY_F3, // 0x72 VK_F3
KEY_F4, // 0x73 VK_F4
KEY_F5, // 0x74 VK_F5
KEY_F6, // 0x75 VK_F6
KEY_F7, // 0x76 VK_F7
KEY_F8, // 0x77 VK_F8
KEY_F9, // 0x78 VK_F9
KEY_F10, // 0x79 VK_F10
KEY_F11, // 0x7A VK_F11
KEY_F12, // 0x7B VK_F12
KEY_F13, // 0x7C VK_F13
KEY_F14, // 0x7D VK_F14
KEY_F15, // 0x7E VK_F15
KEY_F16, // 0x7F VK_F16
KEY_F17, // 0x80 VK_F17
KEY_F18, // 0x81 VK_F18
KEY_F19, // 0x82 VK_F19
KEY_F20, // 0x83 VK_F20
KEY_F21, // 0x84 VK_F21
KEY_F22, // 0x85 VK_F22
KEY_F23, // 0x86 VK_F23
KEY_F24, // 0x87 VK_F24
0, // 0x88
0, // 0x89
0, // 0x8A
0, // 0x8B
0, // 0x8C
0, // 0x8D
0, // 0x8E
0, // 0x8F
KEY_NUMLOCK, // 0x90 VK_NUMLOCK
KEY_SCROLLLOCK, // 0x91 VK_OEM_SCROLL
0, // 0x92
0, // 0x93
0, // 0x94
0, // 0x95
0, // 0x96
0, // 0x97
0, // 0x98
0, // 0x99
0, // 0x9A
0, // 0x9B
0, // 0x9C
0, // 0x9D
0, // 0x9E
0, // 0x9F
KEY_LSHIFT, // 0xA0 VK_LSHIFT
KEY_RSHIFT, // 0xA1 VK_RSHIFT
KEY_LCONTROL, // 0xA2 VK_LCONTROL
KEY_RCONTROL, // 0xA3 VK_RCONTROL
KEY_LALT, // 0xA4 VK_LMENU
KEY_RALT, // 0xA5 VK_RMENU
0, // 0xA6
0, // 0xA7
0, // 0xA8
0, // 0xA9
0, // 0xAA
0, // 0xAB
0, // 0xAC
0, // 0xAD
0, // 0xAE
0, // 0xAF
0, // 0xB0
0, // 0xB1
0, // 0xB2
0, // 0xB3
0, // 0xB4
0, // 0xB5
0, // 0xB6
0, // 0xB7
0, // 0xB8
0, // 0xB9
KEY_SEMICOLON, // 0xBA VK_OEM_1
KEY_EQUALS, // 0xBB VK_OEM_PLUS
KEY_COMMA, // 0xBC VK_OEM_COMMA
KEY_MINUS, // 0xBD VK_OEM_MINUS
KEY_PERIOD, // 0xBE VK_OEM_PERIOD
KEY_SLASH, // 0xBF VK_OEM_2
KEY_TILDE, // 0xC0 VK_OEM_3
0, // 0xC1
0, // 0xC2
0, // 0xC3
0, // 0xC4
0, // 0xC5
0, // 0xC6
0, // 0xC7
0, // 0xC8
0, // 0xC9
0, // 0xCA
0, // 0xCB
0, // 0xCC
0, // 0xCD
0, // 0xCE
0, // 0xCF
0, // 0xD0
0, // 0xD1
0, // 0xD2
0, // 0xD3
0, // 0xD4
0, // 0xD5
0, // 0xD6
0, // 0xD7
0, // 0xD8
0, // 0xD9
0, // 0xDA
KEY_LBRACKET, // 0xDB VK_OEM_4
KEY_BACKSLASH, // 0xDC VK_OEM_5
KEY_RBRACKET, // 0xDD VK_OEM_6
KEY_APOSTROPHE, // 0xDE VK_OEM_7
0, // 0xDF VK_OEM_8
0, // 0xE0
0, // 0xE1 VK_OEM_AX AX key on Japanese AX keyboard
KEY_OEM_102, // 0xE2 VK_OEM_102
0, // 0xE3
0, // 0xE4
0, // 0xE5 VK_PROCESSKEY
0, // 0xE6
0, // 0xE7
0, // 0xE8
0, // 0xE9
0, // 0xEA
0, // 0xEB
0, // 0xEC
0, // 0xED
0, // 0xEE
0, // 0xEF
0, // 0xF0
0, // 0xF1
0, // 0xF2
0, // 0xF3
0, // 0xF4
0, // 0xF5
0, // 0xF6 VK_ATTN
0, // 0xF7 VK_CRSEL
0, // 0xF8 VK_EXSEL
0, // 0xF9 VK_EREOF
0, // 0xFA VK_PLAY
0, // 0xFB VK_ZOOM
0, // 0xFC VK_NONAME
0, // 0xFD VK_PA1
0, // 0xFE VK_OEM_CLEAR
0 // 0xFF
};
//------------------------------------------------------------------------------
//
// This function translates a virtual key code to our corresponding internal
// key code using the preceding table.
//
//------------------------------------------------------------------------------
U8 TranslateOSKeyCode(U8 vcode)
{
return VcodeRemap[vcode];
}
//-----------------------------------------------------------------------------
// Clipboard functions
const char* Platform::getClipboard()
{
HGLOBAL hGlobal;
LPVOID pGlobal;
//make sure we can access the clipboard
if (!IsClipboardFormatAvailable(CF_TEXT))
return "";
if (!OpenClipboard(NULL))
return "";
hGlobal = GetClipboardData(CF_TEXT);
pGlobal = GlobalLock(hGlobal);
S32 cbLength = strlen((char *)pGlobal);
char *returnBuf = Con::getReturnBuffer(cbLength + 1);
strcpy(returnBuf, (char *)pGlobal);
returnBuf[cbLength] = '\0';
GlobalUnlock(hGlobal);
CloseClipboard();
//note - this function never returns NULL
return returnBuf;
}
//-----------------------------------------------------------------------------
bool Platform::setClipboard(const char *text)
{
if (!text)
return false;
//make sure we can access the clipboard
if (!OpenClipboard(NULL))
return false;
S32 cbLength = strlen(text);
HGLOBAL hGlobal;
LPVOID pGlobal;
hGlobal = GlobalAlloc(GHND, cbLength + 1);
pGlobal = GlobalLock (hGlobal);
strcpy((char *)pGlobal, text);
GlobalUnlock(hGlobal);
EmptyClipboard();
SetClipboardData(CF_TEXT, hGlobal);
CloseClipboard();
return true;
}

103
platformWin32/winMath.cc Normal file
View file

@ -0,0 +1,103 @@
//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#include "platform/platform.h"
#include "console/console.h"
#include "math/mMath.h"
extern void mInstallLibrary_C();
extern void mInstallLibrary_ASM();
extern void mInstall_AMD_Math();
extern void mInstall_Library_SSE();
//--------------------------------------
static void cMathInit(SimObject*, S32 argc, const char** argv)
{
U32 properties = CPU_PROP_C; // C entensions are always used
if (argc == 1)
{
Math::init(0);
return;
}
for (argc--, argv++; argc; argc--, argv++)
{
if (dStricmp(*argv, "DETECT") == 0) {
Math::init(0);
return;
}
if (dStricmp(*argv, "C") == 0) {
properties |= CPU_PROP_C;
continue;
}
if (dStricmp(*argv, "FPU") == 0) {
properties |= CPU_PROP_FPU;
continue;
}
if (dStricmp(*argv, "MMX") == 0) {
properties |= CPU_PROP_MMX;
continue;
}
if (dStricmp(*argv, "3DNOW") == 0) {
properties |= CPU_PROP_3DNOW;
continue;
}
if (dStricmp(*argv, "SSE") == 0) {
properties |= CPU_PROP_SSE;
continue;
}
Con::printf("Error: MathInit(): ignoring unknown math extension '%s'", *argv);
}
Math::init(properties);
}
//------------------------------------------------------------------------------
void Math::init(U32 properties)
{
Con::addCommand( "MathInit", cMathInit, "MathInit(detect|C|FPU|MMX|3DNOW|SSE|...)", 1, 10);
if (!properties)
// detect what's available
properties = Platform::SystemInfo.processor.properties;
else
// Make sure we're not asking for anything that's not supported
properties &= Platform::SystemInfo.processor.properties;
Con::printf("Math Init:");
Con::printf(" Installing Standard C extensions");
mInstallLibrary_C();
Con::printf(" Installing Assembly extensions");
mInstallLibrary_ASM();
if (properties & CPU_PROP_FPU)
{
Con::printf(" Installing FPU extensions");
}
if (properties & CPU_PROP_MMX)
{
Con::printf(" Installing MMX extensions");
if (properties & CPU_PROP_3DNOW)
{
Con::printf(" Installing 3DNow extensions");
mInstall_AMD_Math();
}
}
if (properties & CPU_PROP_SSE)
{
Con::printf(" Installing SSE extensions");
mInstall_Library_SSE();
}
Con::printf(" ");
}

View file

@ -0,0 +1,54 @@
//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#include "Math/mMath.h"
#if !defined(__MWERKS__) && defined(_MSC_VER)
#define asm _asm
#endif
static S32 m_mulDivS32_ASM(S32 a, S32 b, S32 c)
{ // a * b / c
S32 r;
asm
{
mov eax, a
imul b
idiv c
mov r, eax
}
return r;
}
static U32 m_mulDivU32_ASM(S32 a, S32 b, U32 c)
{ // a * b / c
S32 r;
asm
{
mov eax, a
mov edx, 0
mul b
div c
mov r, eax
}
return r;
}
//------------------------------------------------------------------------------
void mInstallLibrary_ASM()
{
m_mulDivS32 = m_mulDivS32_ASM;
m_mulDivU32 = m_mulDivU32_ASM;
}

View file

@ -0,0 +1,53 @@
//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#include "PlatformWin32/platformWin32.h"
void* dMemcpy(void *dst, const void *src, unsigned size)
{
return memcpy(dst,src,size);
}
//--------------------------------------
void* dMemmove(void *dst, const void *src, unsigned size)
{
return memmove(dst,src,size);
}
//--------------------------------------
void* dMemset(void *dst, S32 c, unsigned size)
{
return memset(dst,c,size);
}
//--------------------------------------
S32 dMemcmp(const void *ptr1, const void *ptr2, unsigned len)
{
return memcmp(ptr1, ptr2, len);
}
#ifdef new
#undef new
#endif
//--------------------------------------
void* FN_CDECL operator new(dsize_t, void* ptr)
{
return (ptr);
}
void* dRealMalloc(dsize_t s)
{
return malloc(s);
}
void dRealFree(void* p)
{
free(p);
}

35
platformWin32/winMutex.cc Normal file
View file

@ -0,0 +1,35 @@
//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#include "PlatformWin32/platformWin32.h"
#include "Platform/platformMutex.h"
void * Mutex::createMutex()
{
CRITICAL_SECTION * mutex = new CRITICAL_SECTION;
InitializeCriticalSection(mutex);
return((void*)mutex);
}
void Mutex::destroyMutex(void * mutex)
{
AssertFatal(mutex, "Mutex::destroyMutex: invalid mutex");
DeleteCriticalSection((CRITICAL_SECTION*)mutex);
delete mutex;
}
void Mutex::lockMutex(void * mutex)
{
AssertFatal(mutex, "Mutex::lockMutex: invalid mutex");
EnterCriticalSection((CRITICAL_SECTION*)mutex);
}
void Mutex::unlockMutex(void * mutex)
{
AssertFatal(mutex, "Mutex::unlockMutex: invalid mutex");
LeaveCriticalSection((CRITICAL_SECTION*)mutex);
}

801
platformWin32/winNet.cc Normal file
View file

@ -0,0 +1,801 @@
//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#include "PlatformWin32/platformWin32.h"
#include "Platform/platform.h"
#include "Platform/event.h"
#include <winsock.h>
#include <wsipx.h>
#include "console/console.h"
#include "Platform/gameInterface.h"
#include "Core/fileStream.h"
struct NameLookup
{
U8 hostEntStruct[MAXGETHOSTSTRUCT];
HANDLE lookupHandle;
SOCKET socket;
U16 port;
NameLookup *nextLookup;
};
static NameLookup *lookupList = NULL;
// process receives data and posts it to the game.
static Net::Error getLastError();
static S32 defaultPort = 28000;
static S32 netPort = 0;
static SOCKET ipxSocket = INVALID_SOCKET;
static SOCKET udpSocket = INVALID_SOCKET;
enum {
MaxConnections = 1024,
};
HWND winsockWindow = NULL;
static LRESULT PASCAL WinsockProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
U32 error;
U32 bufLen;
U32 event;
SOCKET socket;
Net::Error err;
S32 bytesRead;
static ConnectedNotifyEvent notifyEvent;
static ConnectedReceiveEvent receiveEvent;
static ConnectedAcceptEvent acceptEvent;
switch(message)
{
case WM_USER:
error = WSAGETSELECTERROR(lParam);
event = WSAGETSELECTEVENT(lParam);
socket = wParam;
switch(event)
{
case FD_READ:
err = Net::recv(socket, receiveEvent.data, MaxPacketDataSize, &bytesRead);
if(err == Net::NoError && bytesRead != 0)
{
receiveEvent.tag = socket;
receiveEvent.size = ConnectedReceiveEventHeaderSize + bytesRead;
Game->postEvent(receiveEvent);
}
break;
case FD_CONNECT:
notifyEvent.tag = socket;
if(error)
notifyEvent.state = ConnectedNotifyEvent::ConnectFailed;
else
notifyEvent.state = ConnectedNotifyEvent::Connected;
Game->postEvent(notifyEvent);
break;
case FD_CLOSE:
// see first if there is anything to read:
for(;;)
{
err = Net::recv(socket, receiveEvent.data, MaxPacketDataSize, &bytesRead);
if(err != Net::NoError || bytesRead == 0)
break;
receiveEvent.tag = socket;
receiveEvent.size = ConnectedReceiveEventHeaderSize + bytesRead;
Game->postEvent(receiveEvent);
}
notifyEvent.tag = socket;
notifyEvent.state = ConnectedNotifyEvent::Disconnected;
Game->postEvent(notifyEvent);
break;
case FD_ACCEPT:
acceptEvent.portTag = socket;
acceptEvent.connectionTag = Net::accept(socket, &acceptEvent.address);
if(acceptEvent.connectionTag != InvalidSocket)
{
Net::setBlocking(acceptEvent.connectionTag, false);
WSAAsyncSelect(acceptEvent.connectionTag, winsockWindow, WM_USER, FD_READ | FD_CONNECT | FD_CLOSE);
Game->postEvent(acceptEvent);
}
break;
}
break;
case WM_USER + 1:
error = WSAGETASYNCERROR(lParam);
bufLen = WSAGETASYNCBUFLEN(lParam);
HANDLE handle;
handle = HANDLE(wParam);
NameLookup **walk;
for(walk = &lookupList; *walk; walk = &((*walk)->nextLookup))
{
if((*walk)->lookupHandle == handle)
{
NameLookup *temp = *walk;
struct hostent *hp = (struct hostent *) temp->hostEntStruct;
SOCKADDR_IN ipAddr;
memcpy(&ipAddr.sin_addr.s_addr, hp->h_addr, sizeof(IN_ADDR));
ipAddr.sin_port = temp->port;
ipAddr.sin_family = AF_INET;
notifyEvent.tag = temp->socket;
bool wserr = ::connect(temp->socket, (PSOCKADDR) &ipAddr, sizeof(ipAddr)); // always errors out
if(wserr && WSAGetLastError() != WSAEWOULDBLOCK)
{
notifyEvent.state = ConnectedNotifyEvent::DNSFailed;
::closesocket(temp->socket);
}
else
{
WSAAsyncSelect(temp->socket, winsockWindow, WM_USER, FD_READ | FD_CONNECT | FD_CLOSE);
notifyEvent.state = ConnectedNotifyEvent::DNSResolved;
}
Game->postEvent(notifyEvent);
*walk = temp->nextLookup;
delete temp;
break;
}
}
break;
default:
return DefWindowProc( hWnd, message, wParam, lParam );
}
return 0;
}
static void InitNetWindow()
{
WNDCLASS wc;
dMemset(&wc, 0, sizeof(wc));
wc.style = 0;
wc.lpfnWndProc = WinsockProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = winState.appInstance;
wc.hIcon = 0;
wc.hCursor = 0;
wc.hbrBackground = 0;
wc.lpszMenuName = 0;
wc.lpszClassName = "WinSockClass";
RegisterClass( &wc );
winsockWindow = CreateWindowEx(
0,
"WinSockClass",
"",
0,
0, 0, 0, 0,
NULL, NULL,
winState.appInstance,
NULL);
}
bool Net::init()
{
WSADATA stWSAData;
InitNetWindow();
return !WSAStartup(0x0101, &stWSAData);
}
void Net::shutdown()
{
while(lookupList)
{
NameLookup *temp = lookupList;
lookupList = temp->nextLookup;
WSACancelAsyncRequest ( temp->lookupHandle );
delete temp;
}
DestroyWindow(winsockWindow);
closePort();
WSACleanup();
}
static void netToIPSocketAddress(const NetAddress *address, SOCKADDR_IN *sockAddr)
{
dMemset(sockAddr, 0, sizeof(SOCKADDR_IN));
sockAddr->sin_family = AF_INET;
sockAddr->sin_port = htons(address->port);
sockAddr->sin_addr.s_net = address->netNum[0];
sockAddr->sin_addr.s_host = address->netNum[1];
sockAddr->sin_addr.s_lh = address->netNum[2];
sockAddr->sin_addr.s_impno = address->netNum[3];
}
static void IPSocketToNetAddress(const SOCKADDR_IN *sockAddr, NetAddress *address)
{
address->type = NetAddress::IPAddress;
address->port = htons(sockAddr->sin_port);
address->netNum[0] = sockAddr->sin_addr.s_net;
address->netNum[1] = sockAddr->sin_addr.s_host;
address->netNum[2] = sockAddr->sin_addr.s_lh;
address->netNum[3] = sockAddr->sin_addr.s_impno;
}
static void netToIPXSocketAddress(const NetAddress *address, SOCKADDR_IPX *sockAddr)
{
dMemset(sockAddr, 0, sizeof(SOCKADDR_IPX));
sockAddr->sa_family = AF_INET;
sockAddr->sa_socket = htons(address->port);
sockAddr->sa_netnum[0] = address->netNum[0];
sockAddr->sa_netnum[1] = address->netNum[1];
sockAddr->sa_netnum[2] = address->netNum[2];
sockAddr->sa_netnum[3] = address->netNum[3];
sockAddr->sa_nodenum[0] = address->nodeNum[0];
sockAddr->sa_nodenum[1] = address->nodeNum[1];
sockAddr->sa_nodenum[2] = address->nodeNum[2];
sockAddr->sa_nodenum[3] = address->nodeNum[3];
sockAddr->sa_nodenum[4] = address->nodeNum[4];
sockAddr->sa_nodenum[5] = address->nodeNum[5];
}
static void IPXSocketToNetAddress(const SOCKADDR_IPX *sockAddr, NetAddress *address)
{
address->type = NetAddress::IPXAddress;
address->port = htons(sockAddr->sa_socket);
address->netNum[0] = sockAddr->sa_netnum[0] ;
address->netNum[1] = sockAddr->sa_netnum[1] ;
address->netNum[2] = sockAddr->sa_netnum[2] ;
address->netNum[3] = sockAddr->sa_netnum[3] ;
address->nodeNum[0] = sockAddr->sa_nodenum[0];
address->nodeNum[1] = sockAddr->sa_nodenum[1];
address->nodeNum[2] = sockAddr->sa_nodenum[2];
address->nodeNum[3] = sockAddr->sa_nodenum[3];
address->nodeNum[4] = sockAddr->sa_nodenum[4];
address->nodeNum[5] = sockAddr->sa_nodenum[5];
}
NetSocket Net::openListenPort(U16 port)
{
if(Game->isJournalReading())
{
U32 ret;
Game->journalRead(&ret);
return NetSocket(ret);
}
NetSocket sock = openSocket();
bind(sock, port);
listen(sock, 4);
setBlocking(sock, false);
if(WSAAsyncSelect ( sock, winsockWindow, WM_USER, FD_ACCEPT ))
Con::printf("Error: %d", WSAGetLastError());
if(Game->isJournalWriting())
Game->journalWrite(U32(sock));
return sock;
}
NetSocket Net::openConnectTo(const char *addressString)
{
if(!dStrnicmp(addressString, "ipx:", 4))
return InvalidSocket;
if(!dStrnicmp(addressString, "ip:", 3))
addressString += 3; // eat off the ip:
char remoteAddr[256];
dStrcpy(remoteAddr, addressString);
char *portString = dStrchr(remoteAddr, ':');
U16 port;
if(portString)
{
*portString++ = 0;
port = htons(dAtoi(portString));
}
else
port = htons(defaultPort);
if(!dStricmp(remoteAddr, "broadcast"))
return InvalidSocket;
if(Game->isJournalReading())
{
U32 ret;
Game->journalRead(&ret);
return NetSocket(ret);
}
NetSocket sock = openSocket();
setBlocking(sock, false);
SOCKADDR_IN ipAddr;
ipAddr.sin_addr.s_addr = inet_addr(remoteAddr);
if(ipAddr.sin_addr.s_addr != INADDR_NONE)
{
ipAddr.sin_port = port;
ipAddr.sin_family = AF_INET;
if(::connect(sock, (PSOCKADDR) &ipAddr, sizeof(ipAddr) ) )
{
if(WSAGetLastError() != WSAEWOULDBLOCK)
{
Con::printf("Last error: %d", WSAGetLastError());
::closesocket(sock);
sock = InvalidSocket;
}
}
if(sock != InvalidSocket)
WSAAsyncSelect(sock, winsockWindow, WM_USER, FD_READ | FD_CONNECT | FD_CLOSE);
}
else
{
NameLookup *lookup = new NameLookup;
lookup->socket = sock;
lookup->port = port;
lookup->lookupHandle = WSAAsyncGetHostByName (winsockWindow, WM_USER + 1, remoteAddr, (char *) lookup->hostEntStruct, MAXGETHOSTSTRUCT );
if(!lookup->lookupHandle)
{
delete lookup;
::closesocket(sock);
sock = InvalidSocket;
}
else
{
lookup->nextLookup = lookupList;
lookupList = lookup;
}
}
if(Game->isJournalWriting())
Game->journalWrite(U32(sock));
return sock;
}
void Net::closeConnectTo(NetSocket sock)
{
if(Game->isJournalReading())
return;
for(NameLookup **walk = &lookupList; *walk; walk = &((*walk)->nextLookup) )
{
NameLookup *lookup = *walk;
if(lookup->socket == sock)
{
WSACancelAsyncRequest ( lookup->lookupHandle );
closesocket(lookup->socket);
*walk = lookup->nextLookup;
delete lookup;
return;
}
}
closesocket(sock);
}
Net::Error Net::sendTo(NetSocket socket, const U8 *buffer, int bufferSize)
{
if(Game->isJournalReading())
{
U32 e;
Game->journalRead(&e);
return (Net::Error) e;
}
Net::Error e = send(socket, buffer, bufferSize);
if(Game->isJournalWriting())
Game->journalWrite(U32(e));
return e;
}
bool Net::openPort(S32 port)
{
if(udpSocket != INVALID_SOCKET)
closesocket(udpSocket);
if(ipxSocket != INVALID_SOCKET)
closesocket(ipxSocket);
udpSocket = socket(AF_INET, SOCK_DGRAM, 0);
ipxSocket = socket(AF_IPX, SOCK_DGRAM, NSPROTO_IPX);
if(udpSocket != INVALID_SOCKET)
{
Net::Error error;
error = bind(udpSocket, port);
if(error == NoError)
error = setBufferSize(udpSocket, 32768);
if(error == NoError)
error = setBroadcast(udpSocket, true);
if(error == NoError)
error = setBlocking(udpSocket, false);
if(error == NoError)
Con::printf("UDP initialized on port %d", port);
else
{
closesocket(udpSocket);
udpSocket = INVALID_SOCKET;
Con::printf("Unable to initialize UDP - error %d", error);
}
}
if(ipxSocket != INVALID_SOCKET)
{
Net::Error error = NoError;
SOCKADDR_IPX ipxAddress;
memset((char *)&ipxAddress, 0, sizeof(ipxAddress));
ipxAddress.sa_family = AF_IPX;
ipxAddress.sa_socket = htons(port);
S32 err = ::bind(ipxSocket, (PSOCKADDR) &ipxAddress, sizeof(ipxAddress));
if(err)
error = getLastError();
if(error == NoError)
error = setBufferSize(ipxSocket, 32768);
if(error == NoError)
error = setBroadcast(ipxSocket, true);
if(error == NoError)
error = setBlocking(ipxSocket, false);
if(error == NoError)
Con::printf("IPX initialized on port %d", port);
else
{
closesocket(ipxSocket);
ipxSocket = INVALID_SOCKET;
Con::printf("Unable to initialize IPX - error %d", error);
}
}
netPort = port;
return ipxSocket != INVALID_SOCKET || udpSocket != INVALID_SOCKET;
}
void Net::closePort()
{
if(ipxSocket != INVALID_SOCKET)
closesocket(ipxSocket);
if(udpSocket != INVALID_SOCKET)
closesocket(udpSocket);
}
Net::Error Net::sendto(const NetAddress *address, const U8 *buffer, S32 bufferSize)
{
if(Game->isJournalReading())
return NoError;
if(address->type == NetAddress::IPXAddress)
{
SOCKADDR_IPX ipxAddr;
netToIPXSocketAddress(address, &ipxAddr);
if(::sendto(ipxSocket, (const char*)buffer, bufferSize, 0,
(PSOCKADDR) &ipxAddr, sizeof(SOCKADDR_IPX)) == SOCKET_ERROR)
return getLastError();
else
return NoError;
}
else
{
SOCKADDR_IN ipAddr;
netToIPSocketAddress(address, &ipAddr);
if(::sendto(udpSocket, (const char*)buffer, bufferSize, 0,
(PSOCKADDR) &ipAddr, sizeof(SOCKADDR_IN)) == SOCKET_ERROR)
return getLastError();
else
return NoError;
}
}
void Net::process()
{
SOCKADDR sa;
PacketReceiveEvent receiveEvent;
for(;;)
{
S32 addrLen = sizeof(sa);
S32 bytesRead = SOCKET_ERROR;
if(udpSocket != INVALID_SOCKET)
bytesRead = recvfrom(udpSocket, (char *) receiveEvent.data, MaxPacketDataSize, 0, &sa, &addrLen);
if(bytesRead == SOCKET_ERROR && ipxSocket != INVALID_SOCKET)
{
addrLen = sizeof(sa);
bytesRead = recvfrom(ipxSocket, (char *) receiveEvent.data, MaxPacketDataSize, 0, &sa, &addrLen);
}
if(bytesRead == SOCKET_ERROR)
break;
if(sa.sa_family == AF_INET)
IPSocketToNetAddress((SOCKADDR_IN *) &sa, &receiveEvent.sourceAddress);
else if(sa.sa_family == AF_IPX)
IPXSocketToNetAddress((SOCKADDR_IPX *) &sa, &receiveEvent.sourceAddress);
else
continue;
NetAddress &na = receiveEvent.sourceAddress;
if(na.type == NetAddress::IPAddress &&
na.netNum[0] == 127 &&
na.netNum[1] == 0 &&
na.netNum[2] == 0 &&
na.netNum[3] == 1 &&
na.port == netPort)
continue;
if(bytesRead <= 0)
continue;
receiveEvent.size = PacketReceiveEventHeaderSize + bytesRead;
Game->postEvent(receiveEvent);
}
}
NetSocket Net::openSocket()
{
SOCKET retSocket;
retSocket = socket(AF_INET, SOCK_STREAM, 0);
if(retSocket == INVALID_SOCKET)
return InvalidSocket;
else
return retSocket;
}
Net::Error Net::closeSocket(NetSocket socket)
{
if(socket != InvalidSocket)
{
if(!closesocket(socket))
return NoError;
else
return getLastError();
}
else
return NotASocket;
}
Net::Error Net::connect(NetSocket socket, const NetAddress *address)
{
if(address->type != NetAddress::IPAddress)
return WrongProtocolType;
SOCKADDR_IN socketAddress;
netToIPSocketAddress(address, &socketAddress);
if(!::connect(socket, (PSOCKADDR) &socketAddress, sizeof(socketAddress)))
return NoError;
return getLastError();
}
Net::Error Net::listen(NetSocket socket, S32 backlog)
{
if(!::listen(socket, backlog))
return NoError;
return getLastError();
}
NetSocket Net::accept(NetSocket acceptSocket, NetAddress *remoteAddress)
{
SOCKADDR_IN socketAddress;
S32 addrLen = sizeof(socketAddress);
SOCKET retVal = ::accept(acceptSocket, (PSOCKADDR) &socketAddress, &addrLen);
if(retVal != INVALID_SOCKET)
{
IPSocketToNetAddress(&socketAddress, remoteAddress);
return retVal;
}
return InvalidSocket;
}
Net::Error Net::bind(NetSocket socket, U16 port)
{
S32 error;
SOCKADDR_IN socketAddress;
dMemset((char *)&socketAddress, 0, sizeof(socketAddress));
socketAddress.sin_family = AF_INET;
// It's entirely possible that there are two NIC cards.
// We let the user specify which one the server runs on.
// thanks to [TPG]P1aGu3 for the name
const char* serverIP = Con::getVariable( "Host::BindAddress" );
// serverIP is guaranteed to be non-0.
AssertFatal( serverIP, "serverIP is NULL!" );
if( serverIP[0] != '\0' ) {
// we're not empty
socketAddress.sin_addr.s_addr = inet_addr( serverIP );
if( socketAddress.sin_addr.s_addr != INADDR_NONE ) {
Con::printf( "Binding server port to %s", serverIP );
} else {
Con::warnf( ConsoleLogEntry::General,
"inet_addr() failed for %s while binding!",
serverIP );
socketAddress.sin_addr.s_addr = INADDR_ANY;
}
} else {
Con::printf( "Binding server port to default IP" );
socketAddress.sin_addr.s_addr = INADDR_ANY;
}
socketAddress.sin_port = htons(port);
error = ::bind(socket, (PSOCKADDR) &socketAddress, sizeof(socketAddress));
if(!error)
return NoError;
return getLastError();
}
Net::Error Net::setBufferSize(NetSocket socket, S32 bufferSize)
{
S32 error;
error = setsockopt(socket, SOL_SOCKET, SO_RCVBUF, (char *) &bufferSize, sizeof(bufferSize));
if(!error)
error = setsockopt(socket, SOL_SOCKET, SO_SNDBUF, (char *) &bufferSize, sizeof(bufferSize));
if(!error)
return NoError;
return getLastError();
}
Net::Error Net::setBroadcast(NetSocket socket, bool broadcast)
{
S32 bc = broadcast;
S32 error = setsockopt(socket, SOL_SOCKET, SO_BROADCAST, (char*)&bc, sizeof(bc));
if(!error)
return NoError;
return getLastError();
}
Net::Error Net::setBlocking(NetSocket socket, bool blockingIO)
{
DWORD notblock = !blockingIO;
S32 error = ioctlsocket(socket, FIONBIO, &notblock);
if(!error)
return NoError;
return getLastError();
}
Net::Error Net::send(NetSocket socket, const U8 *buffer, S32 bufferSize)
{
S32 error = ::send(socket, (const char*)buffer, bufferSize, 0);
if(!error)
return NoError;
return getLastError();
}
Net::Error Net::recv(NetSocket socket, U8 *buffer, S32 bufferSize, S32 *bytesRead)
{
*bytesRead = ::recv(socket, (char*)buffer, bufferSize, 0);
if(*bytesRead == SOCKET_ERROR)
return getLastError();
return NoError;
}
bool Net::compareAddresses(const NetAddress *a1, const NetAddress *a2)
{
if((a1->type != a2->type) ||
(*((U32 *)a1->netNum) != *((U32 *)a2->netNum)) ||
(a1->port != a2->port))
return false;
if(a1->type == NetAddress::IPAddress)
return true;
for(S32 i = 0; i < 6; i++)
if(a1->nodeNum[i] != a2->nodeNum[i])
return false;
return true;
}
bool Net::stringToAddress(const char *addressString, NetAddress *address)
{
if(dStrnicmp(addressString, "ipx:", 4))
{
// assume IP if it doesn't have ipx: at the front.
if(!dStrnicmp(addressString, "ip:", 3))
addressString += 3; // eat off the ip:
SOCKADDR_IN ipAddr;
char remoteAddr[256];
if(strlen(addressString) > 255)
return false;
dStrcpy(remoteAddr, addressString);
char *portString = dStrchr(remoteAddr, ':');
if(portString)
*portString++ = 0;
struct hostent *hp;
if(!dStricmp(remoteAddr, "broadcast"))
ipAddr.sin_addr.s_addr = htonl(INADDR_BROADCAST);
else
{
ipAddr.sin_addr.s_addr = inet_addr(remoteAddr);
if(ipAddr.sin_addr.s_addr == INADDR_NONE)
{
if((hp = gethostbyname(remoteAddr)) == NULL)
return false;
else
memcpy(&ipAddr.sin_addr.s_addr, hp->h_addr, sizeof(IN_ADDR));
}
}
if(portString)
ipAddr.sin_port = htons(dAtoi(portString));
else
ipAddr.sin_port = htons(defaultPort);
ipAddr.sin_family = AF_INET;
IPSocketToNetAddress(&ipAddr, address);
return true;
}
else
{
S32 i;
S32 port;
address->type = NetAddress::IPXAddress;
for(i = 0; i < 6; i++)
address->nodeNum[i] = 0xFF;
// it's an IPX string
addressString += 4;
if(!dStricmp(addressString, "broadcast"))
{
address->port = defaultPort;
return true;
}
else if(sscanf(addressString, "broadcast:%d", &port) == 1)
{
address->port = port;
return true;
}
else
{
S32 nodeNum[6];
S32 netNum[4];
S32 count = dSscanf(addressString, "%2x%2x%2x%2x:%2x%2x%2x%2x%2x%2x:%d",
&netNum[0], &netNum[1], &netNum[2], &netNum[3],
&nodeNum[0], &nodeNum[1], &nodeNum[2], &nodeNum[3], &nodeNum[4], &nodeNum[5],
&port);
if(count == 10)
{
port = defaultPort;
count++;
}
if(count != 11)
return false;
for(i = 0; i < 6; i++)
address->nodeNum[i] = nodeNum[i];
for(i = 0; i < 4; i++)
address->netNum[i] = netNum[i];
address->port = port;
return true;
}
}
}
void Net::addressToString(const NetAddress *address, char addressString[256])
{
if(address->type == NetAddress::IPAddress)
{
SOCKADDR_IN ipAddr;
netToIPSocketAddress(address, &ipAddr);
if(ipAddr.sin_addr.s_addr == htonl(INADDR_BROADCAST))
dSprintf(addressString, 256, "IP:Broadcast:%d", ntohs(ipAddr.sin_port));
else
dSprintf(addressString, 256, "IP:%d.%d.%d.%d:%d", ipAddr.sin_addr.s_net,
ipAddr.sin_addr.s_host, ipAddr.sin_addr.s_lh,
ipAddr.sin_addr.s_impno, ntohs(ipAddr.sin_port));
}
else
{
dSprintf(addressString, 256, "IPX:%.2X%.2X%.2X%.2X:%.2X%.2X%.2X%.2X%.2X%.2X:%d",
address->netNum[0], address->netNum[1], address->netNum[2], address->netNum[3],
address->nodeNum[0], address->nodeNum[1], address->nodeNum[2], address->nodeNum[3], address->nodeNum[4], address->nodeNum[5],
address->port);
}
}
Net::Error getLastError()
{
S32 err = WSAGetLastError();
switch(err)
{
case WSAEWOULDBLOCK:
return Net::WouldBlock;
default:
return Net::UnknownError;
}
}

1219
platformWin32/winOGLVideo.cc Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,39 @@
//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#ifndef _WINOGLVIDEO_H_
#define _WINOGLVIDEO_H_
#ifndef _PLATFORMVIDEO_H_
#include "Platform/platformVideo.h"
#endif
class OpenGLDevice : public DisplayDevice
{
static bool smCanSwitchBitDepth;
bool mRestoreGamma;
U16 mOriginalRamp[256*3];
public:
OpenGLDevice();
void initDevice();
bool activate( U32 width, U32 height, U32 bpp, bool fullScreen );
void shutdown();
void destroy();
bool setScreenMode( U32 width, U32 height, U32 bpp, bool fullScreen, bool forceIt = false, bool repaint = true );
void swapBuffers();
const char* getDriverInfo();
bool getGammaCorrection(F32 &g);
bool setGammaCorrection(F32 g);
bool setVerticalSync( bool on );
static DisplayDevice* create();
};
#endif // _H_WINOGLVIDEO

253
platformWin32/winOpenAL.cc Normal file
View file

@ -0,0 +1,253 @@
//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#include "PlatformWin32/platformWin32.h"
#include "console/console.h"
#define AL_NO_PROTOTYPES
#include <al/al.h>
#include <al/alc.h>
#include <al/alut.h>
#define MILES_REENTRANT_CHECK
// Stub functions: ---------------------------------------------------------
// AL:
ALvoid stub_alEnable( ALenum ) {}
ALvoid stub_alDisable( ALenum ) {}
ALboolean stub_alIsEnabled( ALenum ) {return(AL_FALSE);}
ALvoid stub_alHint( ALenum , ALenum ) {}
ALboolean stub_alGetBoolean( ALenum ) {return(AL_FALSE);}
ALint stub_alGetInteger( ALenum ) {return(0);}
ALfloat stub_alGetFloat( ALenum ) {return(0.f);}
ALdouble stub_alGetDouble( ALenum ) {return(0.f);}
ALvoid stub_alGetBooleanv( ALenum, ALboolean* ) {}
ALvoid stub_alGetIntegerv( ALenum, ALint* ) {}
ALvoid stub_alGetFloatv( ALenum, ALfloat* ) {}
ALvoid stub_alGetDoublev( ALenum, ALdouble* ) {}
const ALubyte* stub_alGetString( ALenum pname )
{
switch(pname)
{
case AL_VENDOR: return (ALubyte*)"None";
case AL_VERSION: return (ALubyte*)"OpenAL 0.1";
case AL_RENDERER: return (ALubyte*)"None";
case AL_EXTENSIONS: return (ALubyte*)"";
}
return(0);
}
ALenum stub_alGetError( ALvoid ) {return(0);}
ALboolean stub_alIsExtensionPresent( const ALubyte* ) {return(AL_FALSE);}
ALvoid* stub_alGetProcAddress( const ALubyte* ) {return(0);}
ALenum stub_alGetEnumValue( const ALubyte* ) {return(0);}
ALvoid stub_alListenerf( ALenum, ALfloat ) {}
ALvoid stub_alListener3f( ALenum, ALfloat, ALfloat, ALfloat ) {}
ALvoid stub_alListenerfv( ALenum, ALfloat* ) {}
ALvoid stub_alGetListeneri( ALenum, ALint* ) {}
ALvoid stub_alGetListenerf( ALenum, ALfloat* ) {}
ALvoid stub_alGetListenerfv( ALenum, ALfloat* ) {}
ALvoid stub_alGenSources( ALsizei, ALuint* ) {}
ALvoid stub_alDeleteSources( ALsizei, ALuint* ) {}
ALboolean stub_alIsSource( ALuint ) {return(AL_FALSE);}
ALvoid stub_alSourcei( ALuint, ALenum, ALint ) {}
ALvoid stub_alSourcef( ALuint, ALenum, ALfloat ) {}
ALvoid stub_alSource3f( ALuint, ALenum, ALfloat, ALfloat, ALfloat ) {}
ALvoid stub_alSourcefv( ALuint, ALenum, ALfloat* ) {}
ALvoid stub_alGetSourcei( ALuint, ALenum, ALint* ) {}
ALvoid stub_alGetSourcef( ALuint, ALenum, ALfloat* ) {}
ALvoid stub_alGetSourcefv( ALuint, ALenum, ALfloat* ) {}
ALvoid stub_alSourcePlayv( ALuint, ALuint* ) {}
ALvoid stub_alSourceStopv( ALuint, ALuint* ) {}
ALvoid stub_alSourcePlay( ALuint ) {}
ALvoid stub_alSourcePause( ALuint ) {}
ALvoid stub_alSourceStop( ALuint ) {}
ALvoid stub_alGenBuffers( ALsizei, ALuint* ) {}
ALvoid stub_alDeleteBuffers( ALsizei, ALuint* ) {}
ALboolean stub_alIsBuffer( ALuint ) {return(AL_FALSE);}
ALvoid stub_alBufferData( ALuint, ALenum, ALvoid*, ALsizei, ALsizei ) {}
ALsizei stub_alBufferAppendData( ALuint, ALenum, ALvoid*, ALsizei, ALsizei ) {return(0);}
ALvoid stub_alGetBufferi( ALuint, ALenum, ALint* ) {}
ALvoid stub_alGetBufferf( ALuint, ALenum, ALfloat* ) {}
// ALC:
ALvoid* stub_alcCreateContext( ALint *) {return(0);}
ALCenum stub_alcMakeContextCurrent( ALvoid *) {return(ALC_INVALID);}
ALvoid* stub_alcUpdateContext( ALvoid * ) {return(0);}
ALCenum stub_alcDestroyContext( ALvoid * ) {return(ALC_INVALID);}
ALCenum stub_alcGetError( ALvoid ) {return(ALC_INVALID);}
const ALubyte* stub_alcGetErrorString( ALvoid ) {return(0);}
ALvoid* stub_alcGetCurrentContext( ALvoid ) {return(0);}
// ALUT:
void stub_alutInit( int *, char ** ) {}
void stub_alutExit( ALvoid ) {}
ALboolean stub_alutLoadWAV( const char *, ALvoid **, ALsizei *, ALsizei *, ALsizei *, ALsizei *) {return(AL_FALSE);}
// Extension: IASIG
ALvoid stub_alGenEnvironmentIASIG( ALsizei, ALuint* ) {}
ALvoid stub_alDeleteEnvironmentIASIG( ALsizei, ALuint*) {}
ALboolean stub_alIsEnvironmentIASIG( ALuint ) {return(AL_FALSE);}
ALvoid stub_alEnvironmentiIASIG( ALuint, ALenum, ALint ) {}
ALvoid stub_alEnvironmentfIASIG( ALuint, ALenum, ALfloat ) {}
ALvoid stub_alGetEnvironmentiIASIG_EXT( ALuint, ALenum, ALint * ) {}
ALvoid stub_alGetEnvironmentfIASIG_EXT( ALuint, ALenum, ALfloat * ) {}
// Extension: Dynamix
ALboolean stub_alBufferi_EXT( ALuint, ALenum, ALint ) { return(AL_FALSE); }
ALboolean stub_alBufferSyncData_EXT( ALuint, ALenum, ALvoid *, ALsizei, ALsizei ) {return(AL_FALSE); }
ALboolean stub_alBufferStreamFile_EXT( ALuint, const ALubyte * ) { return(AL_FALSE); }
ALboolean stub_alSourceCallback_EXT( ALuint, ALvoid * ) { return(AL_FALSE); }
ALvoid stub_alSourceResetEnvironment_EXT( ALuint ) {}
ALboolean stub_alContexti_EXT( ALenum, ALint) { return(AL_FALSE); }
ALboolean stub_alGetContexti_EXT( ALenum, ALint * ) { return(AL_FALSE); }
ALboolean stub_alGetContextstr_EXT( ALenum, ALuint, ALubyte ** ) { return(AL_FALSE); }
ALboolean stub_alCaptureInit_EXT( ALenum, ALuint, ALsizei ) { return(AL_FALSE); }
ALboolean stub_alCaptureDestroy_EXT( ALvoid ) { return(AL_FALSE); }
ALboolean stub_alCaptureStart_EXT( ALvoid ) { return(AL_FALSE); }
ALboolean stub_alCaptureStop_EXT( ALvoid ) { return(AL_FALSE); }
ALsizei stub_alCaptureGetData_EXT( ALvoid *, ALsizei, ALenum, ALuint ) { return(AL_FALSE); }
// declare OpenAL functions
#define AL_EXTENSION(ext_name) bool gDoesSupport_##ext_name = false;
#define AL_FUNCTION(fn_return,fn_name,fn_args) fn_return (*fn_name)fn_args = stub_##fn_name;
#define AL_EXT_FUNCTION(ext_name,fn_return,fn_name,fn_args) fn_return (*fn_name)fn_args = stub_##fn_name;
#include <openALFn.h>
// DLL's: ------------------------------------------------------------------
static bool findExtension( const char* name )
{
bool result = false;
if (alGetString != NULL)
{
result = dStrstr( (const char*)alGetString(AL_EXTENSIONS), name) != NULL;
}
return result;
}
static bool bindFunction( void *&fnAddress, const char *name )
{
fnAddress = GetProcAddress( winState.hinstOpenAL, name );
if( !fnAddress )
Con::errorf(ConsoleLogEntry::General, " Missing OpenAL function '%s'", name);
return (fnAddress != NULL);
}
static void bindExtension( void *&fnAddress, const char *name, bool &supported )
{
if (supported)
{
bindFunction(fnAddress, name);
if (fnAddress == NULL)
supported = NULL;
}
else
fnAddress = NULL;
}
static bool bindDLLFunctions()
{
bool result = true;
#define AL_FUNCTION(fn_return,fn_name,fn_args) result &= bindFunction( *(void**)&fn_name, #fn_name);
#include <openALFn.h>
return result;
}
// Stub: -------------------------------------------------------------------
static void bindStubFunctions()
{
#define AL_EXTENSION(ext_name) gDoesSupport_##ext_name = false;
#define AL_FUNCTION(fn_return,fn_name,fn_parms) fn_name = stub_##fn_name;
#define AL_EXT_FUNCTION(ext_name,fn_return,fn_name,fn_args) fn_name = stub_##fn_name;
#include <openALFn.h>
}
// Miles: ------------------------------------------------------------------
#ifndef NO_MILES_OPENAL
#ifdef MILES_REENTRANT_CHECK
#define AL_FUNCTION(fn_return, fn_name, fn_args) extern fn_return miles_api_##fn_name fn_args;
#define AL_EXT_FUNCTION(ext_name, fn_return, fn_name, fn_args) extern fn_return miles_api_##fn_name fn_args;
#else
#define AL_FUNCTION(fn_return, fn_name, fn_args) extern fn_return miles_##fn_name fn_args;
#define AL_EXT_FUNCTION(ext_name, fn_return, fn_name, fn_args) extern fn_return miles_##fn_name fn_args;
#endif
#include <openALFn.h>
#endif
static void bindMilesFunctions()
{
#ifndef NO_MILES_OPENAL
#define AL_EXTENSION(ext_name) gDoesSupport_##ext_name = false;
#ifdef MILES_REENTRANT_CHECK
#define AL_FUNCTION(fn_return,fn_name,fn_parms) fn_name = miles_api_##fn_name;
#define AL_EXT_FUNCTION(ext_name, fn_return, fn_name, fn_args) fn_name = miles_api_##fn_name;
#else
#define AL_FUNCTION(fn_return,fn_name,fn_parms) fn_name = miles_##fn_name;
#define AL_EXT_FUNCTION(ext_name, fn_return, fn_name, fn_args) fn_name = miles_##fn_name;
#endif
#include <openALFn.h>
#endif
}
namespace Audio
{
static bool sStaticLibrary;
void libraryShutdown()
{
if (winState.hinstOpenAL)
FreeLibrary(winState.hinstOpenAL);
winState.hinstOpenAL = NULL;
bindStubFunctions();
sStaticLibrary = true;
}
bool libraryInit(const char *library)
{
libraryShutdown();
if(!library || !library[0])
return(false);
// static drivers...
if(!dStricmp(library, "Miles"))
{
bindMilesFunctions();
return(true);
}
winState.hinstOpenAL = LoadLibrary( avar("%s.dll", library) );
if(winState.hinstOpenAL != NULL)
{
if(bindDLLFunctions())
{
sStaticLibrary = false;
return(true);
}
libraryShutdown();
}
return(false);
}
void libraryInitExtensions()
{
// static library extensions are bound on libraryInit (need to be defined anyways...)
if(sStaticLibrary)
{
#define AL_EXTENSION(ext_name) gDoesSupport_##ext_name = findExtension( #ext_name );
#include <openALFn.h>
}
else
{
#define AL_EXTENSION(ext_name) gDoesSupport_##ext_name = findExtension( #ext_name );
#define AL_EXT_FUNCTION(ext_name, fn_return,fn_name,fn_args) bindExtension( *(void**)&fn_name, #fn_name, gDoesSupport_##ext_name );
#include <openALFn.h>
}
}
} // end namespace Audio

View file

@ -0,0 +1,23 @@
//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#include "PlatformWin32/platformWin32.h"
void Platform::postQuitMessage(const U32 in_quitVal)
{
PostQuitMessage(in_quitVal);
}
void Platform::debugBreak()
{
DebugBreak();
}
void Platform::forceShutdown(S32 returnValue)
{
ExitProcess(returnValue);
}

468
platformWin32/winRedbook.cc Normal file
View file

@ -0,0 +1,468 @@
//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#include "PlatformWin32/platformWin32.h"
#include "Platform/platformRedBook.h"
class Win32RedBookDevice : public RedBookDevice
{
private:
typedef RedBookDevice Parent;
U32 mDeviceId;
void setLastError(const char *);
void setLastError(U32);
MIXERCONTROLDETAILS mMixerVolumeDetails;
MIXERCONTROLDETAILS_UNSIGNED mMixerVolumeValue;
U32 mVolumeDeviceId;
U32 mOriginalVolume;
bool mVolumeInitialized;
bool mUsingMixer;
void openVolume();
void closeVolume();
public:
Win32RedBookDevice();
~Win32RedBookDevice();
U32 getDeviceId();
bool open();
bool close();
bool play(U32);
bool stop();
bool getTrackCount(U32 *);
bool getVolume(F32 *);
bool setVolume(F32);
};
//------------------------------------------------------------------------------
// Win32 specific
//------------------------------------------------------------------------------
void installRedBookDevices()
{
U32 bufSize = ::GetLogicalDriveStrings(0,0);
char * buf = new char[bufSize];
::GetLogicalDriveStrings(bufSize, buf);
char * str = buf;
while(*str)
{
if(::GetDriveType(str) == DRIVE_CDROM)
{
Win32RedBookDevice * device = new Win32RedBookDevice;
device->mDeviceName = new char[dStrlen(str) + 1];
dStrcpy(device->mDeviceName, str);
RedBook::installDevice(device);
}
str += dStrlen(str) + 1;
}
delete [] buf;
}
void handleRedBookCallback(U32 code, U32 deviceId)
{
if(code != MCI_NOTIFY_SUCCESSFUL)
return;
Win32RedBookDevice * device = dynamic_cast<Win32RedBookDevice*>(RedBook::getCurrentDevice());
if(!device)
return;
if(device->getDeviceId() != deviceId)
return;
// only installed callback on play (no callback if play is aborted)
RedBook::handleCallback(RedBook::PlayFinished);
}
//------------------------------------------------------------------------------
// Class: Win32RedBookDevice
//------------------------------------------------------------------------------
Win32RedBookDevice::Win32RedBookDevice()
{
mVolumeInitialized = false;
}
Win32RedBookDevice::~Win32RedBookDevice()
{
close();
}
U32 Win32RedBookDevice::getDeviceId()
{
return(mDeviceId);
}
bool Win32RedBookDevice::open()
{
if(mAcquired)
{
setLastError("Device is already open.");
return(false);
}
U32 error;
// open the device
MCI_OPEN_PARMS openParms;
openParms.lpstrDeviceType = (LPCSTR)MCI_DEVTYPE_CD_AUDIO;
openParms.lpstrElementName = mDeviceName;
error = mciSendCommand(0, MCI_OPEN, MCI_OPEN_TYPE | MCI_OPEN_TYPE_ID, (DWORD)(LPMCI_OPEN_PARMS)&openParms);
if(error)
{
// attempt to open as a shared device
error = mciSendCommand(NULL, MCI_OPEN, MCI_OPEN_TYPE | MCI_OPEN_TYPE_ID|MCI_OPEN_SHAREABLE, (DWORD)(LPMCI_OPEN_PARMS)&openParms);
if(error)
{
setLastError(error);
return(false);
}
}
// set time mode to milliseconds
MCI_SET_PARMS setParms;
setParms.dwTimeFormat = MCI_FORMAT_MILLISECONDS;
error = mciSendCommand(openParms.wDeviceID, MCI_SET, MCI_SET_TIME_FORMAT, (DWORD)(LPMCI_SET_PARMS)&setParms);
if(error)
{
setLastError(error);
return(false);
}
//
mDeviceId = openParms.wDeviceID;
mAcquired = true;
openVolume();
setLastError("");
return(true);
}
bool Win32RedBookDevice::close()
{
if(!mAcquired)
{
setLastError("Device has not been acquired");
return(false);
}
stop();
U32 error;
MCI_GENERIC_PARMS closeParms;
error = mciSendCommand(mDeviceId, MCI_CLOSE, 0, (DWORD)(LPMCI_GENERIC_PARMS)&closeParms);
if(error)
{
setLastError(error);
return(false);
}
mAcquired = false;
closeVolume();
setLastError("");
return(true);
}
bool Win32RedBookDevice::play(U32 track)
{
if(!mAcquired)
{
setLastError("Device has not been acquired");
return(false);
}
U32 numTracks;
if(!getTrackCount(&numTracks))
return(false);
if(track >= numTracks)
{
setLastError("Track index is out of range");
return(false);
}
MCI_STATUS_PARMS statusParms;
// get track start time
statusParms.dwItem = MCI_STATUS_POSITION;
statusParms.dwTrack = track + 1;
U32 error;
error = mciSendCommand(mDeviceId, MCI_STATUS, MCI_STATUS_ITEM|MCI_TRACK|MCI_WAIT,
(DWORD)(LPMCI_STATUS_PARMS)&statusParms);
if(error)
{
setLastError(error);
return(false);
}
MCI_PLAY_PARMS playParms;
playParms.dwFrom = statusParms.dwReturn;
// get track end time
statusParms.dwItem = MCI_STATUS_LENGTH;
error = mciSendCommand(mDeviceId, MCI_STATUS, MCI_STATUS_ITEM|MCI_TRACK|MCI_WAIT,
(DWORD)(LPMCI_STATUS_PARMS)&statusParms);
if(error)
{
setLastError(error);
return(false);
}
playParms.dwTo = playParms.dwFrom + statusParms.dwReturn;
// play the track
playParms.dwCallback = MAKELONG(winState.appWindow, 0);
error = mciSendCommand(mDeviceId, MCI_PLAY, MCI_FROM|MCI_TO|MCI_NOTIFY,
(DWORD)(LPMCI_PLAY_PARMS)&playParms);
if(error)
{
setLastError(error);
return(false);
}
setLastError("");
return(true);
}
bool Win32RedBookDevice::stop()
{
if(!mAcquired)
{
setLastError("Device has not been acquired");
return(false);
}
MCI_GENERIC_PARMS genParms;
U32 error = mciSendCommand(mDeviceId, MCI_STOP, 0, (DWORD)(LPMCI_GENERIC_PARMS)&genParms);
if(error)
{
setLastError(error);
return(false);
}
setLastError("");
return(true);
}
bool Win32RedBookDevice::getTrackCount(U32 * numTracks)
{
if(!mAcquired)
{
setLastError("Device has not been acquired");
return(false);
}
MCI_STATUS_PARMS statusParms;
statusParms.dwItem = MCI_STATUS_NUMBER_OF_TRACKS;
U32 error = mciSendCommand(mDeviceId, MCI_STATUS, MCI_STATUS_ITEM | MCI_WAIT, (DWORD)(LPMCI_STATUS_PARMS)&statusParms);
if(error)
{
setLastError(error);
return(false);
}
*numTracks = statusParms.dwReturn;
return(true);
}
bool Win32RedBookDevice::getVolume(F32 * volume)
{
if(!mAcquired)
{
setLastError("Device has not been acquired");
return(false);
}
if(!mVolumeInitialized)
{
setLastError("Volume failed to initialize");
return(false);
}
U32 vol = 0;
if(mUsingMixer)
{
mixerGetControlDetails((HMIXEROBJ)mVolumeDeviceId, &mMixerVolumeDetails, MIXER_GETCONTROLDETAILSF_VALUE);
vol = mMixerVolumeValue.dwValue;
}
else
auxGetVolume(mVolumeDeviceId, (unsigned long *)&vol);
vol &= 0xffff;
*volume = F32(vol) / 65535.f;
setLastError("");
return(true);
}
bool Win32RedBookDevice::setVolume(F32 volume)
{
if(!mAcquired)
{
setLastError("Device has not been acquired");
return(false);
}
if(!mVolumeInitialized)
{
setLastError("Volume failed to initialize");
return(false);
}
// move into a U32 - left/right U16 volumes
U32 vol = U32(volume * 65536.f);
if(vol > 0xffff)
vol = 0xffff;
if(mUsingMixer)
{
mMixerVolumeValue.dwValue = vol;
mixerSetControlDetails((HMIXEROBJ)mVolumeDeviceId, &mMixerVolumeDetails, MIXER_SETCONTROLDETAILSF_VALUE);
}
else
{
vol |= vol << 16;
auxSetVolume(mVolumeDeviceId, vol);
}
setLastError("");
return(true);
}
//------------------------------------------------------------------------------
void Win32RedBookDevice::openVolume()
{
setLastError("");
// first attempt to get the volume control through the mixer API
S32 i;
for(i = mixerGetNumDevs() - 1; i >= 0; i--)
{
// open the mixer
if(mixerOpen((HMIXER*)&mVolumeDeviceId, i, 0, 0, 0) == MMSYSERR_NOERROR)
{
MIXERLINE lineInfo;
memset(&lineInfo, 0, sizeof(lineInfo));
lineInfo.cbStruct = sizeof(lineInfo);
lineInfo.dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_COMPACTDISC;
// get the cdaudio line
if(mixerGetLineInfo((HMIXEROBJ)mVolumeDeviceId, &lineInfo, MIXER_GETLINEINFOF_COMPONENTTYPE) == MMSYSERR_NOERROR)
{
MIXERLINECONTROLS lineControls;
MIXERCONTROL volumeControl;
memset(&lineControls, 0, sizeof(lineControls));
lineControls.cbStruct = sizeof(lineControls);
lineControls.dwLineID = lineInfo.dwLineID;
lineControls.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME;
lineControls.cControls = 1;
lineControls.cbmxctrl = sizeof(volumeControl);
lineControls.pamxctrl = &volumeControl;
memset(&volumeControl, 0, sizeof(volumeControl));
volumeControl.cbStruct = sizeof(volumeControl);
// get the volume control
if(mixerGetLineControls((HMIXEROBJ)mVolumeDeviceId, &lineControls, MIXER_GETLINECONTROLSF_ONEBYTYPE) == MMSYSERR_NOERROR)
{
memset(&mMixerVolumeDetails, 0, sizeof(mMixerVolumeDetails));
mMixerVolumeDetails.cbStruct = sizeof(mMixerVolumeDetails);
mMixerVolumeDetails.dwControlID = volumeControl.dwControlID;
mMixerVolumeDetails.cChannels = 1;
mMixerVolumeDetails.cbDetails = sizeof(mMixerVolumeValue);
mMixerVolumeDetails.paDetails = &mMixerVolumeValue;
memset(&mMixerVolumeValue, 0, sizeof(mMixerVolumeValue));
// query the current value
if(mixerGetControlDetails((HMIXEROBJ)mVolumeDeviceId, &mMixerVolumeDetails, MIXER_GETCONTROLDETAILSF_VALUE) == MMSYSERR_NOERROR)
{
mUsingMixer = true;
mVolumeInitialized = true;
mOriginalVolume = mMixerVolumeValue.dwValue;
return;
}
}
}
}
mixerClose((HMIXER)mVolumeDeviceId);
}
// try aux
for(i = auxGetNumDevs() - 1; i >= 0; i--)
{
AUXCAPS caps;
auxGetDevCaps(i, &caps, sizeof(AUXCAPS));
if((caps.wTechnology == AUXCAPS_CDAUDIO) && (caps.dwSupport & AUXCAPS_VOLUME))
{
mVolumeDeviceId = i;
mVolumeInitialized = true;
mUsingMixer = false;
auxGetVolume(i, (unsigned long *)&mOriginalVolume);
return;
}
}
setLastError("Volume failed to initialize");
}
void Win32RedBookDevice::closeVolume()
{
setLastError("");
if(!mVolumeInitialized)
return;
if(mUsingMixer)
{
mMixerVolumeValue.dwValue = mOriginalVolume;
mixerSetControlDetails((HMIXEROBJ)mVolumeDeviceId, &mMixerVolumeDetails, MIXER_SETCONTROLDETAILSF_VALUE);
mixerClose((HMIXER)mVolumeDeviceId);
}
else
auxSetVolume(mVolumeDeviceId, mOriginalVolume);
mVolumeInitialized = false;
}
//------------------------------------------------------------------------------
void Win32RedBookDevice::setLastError(const char * error)
{
RedBook::setLastError(error);
}
void Win32RedBookDevice::setLastError(U32 errorId)
{
char buffer[256];
if(!mciGetErrorString(errorId, buffer, sizeof(buffer) - 1))
setLastError("Failed to get MCI error string!");
else
setLastError(buffer);
}

View file

@ -0,0 +1,44 @@
//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#include "PlatformWin32/platformWin32.h"
#include "Platform/platformSemaphore.h"
void * Semaphore::createSemaphore(U32 initialCount)
{
HANDLE * semaphore = new HANDLE;
*semaphore = CreateSemaphore(0, initialCount, -1, 0);
return(semaphore);
}
void Semaphore::destroySemaphore(void * semaphore)
{
AssertFatal(semaphore, "Semaphore::destroySemaphore: invalid semaphore");
CloseHandle(*(HANDLE*)semaphore);
delete semaphore;
}
bool Semaphore::acquireSemaphore(void * semaphore, bool block)
{
AssertFatal(semaphore, "Semaphore::acquireSemaphore: invalid semaphore");
if(block)
{
WaitForSingleObject(*(HANDLE*)semaphore, INFINITE);
return(true);
}
else
{
DWORD result = WaitForSingleObject(*(HANDLE*)semaphore, 0);
return(result == WAIT_OBJECT_0);
}
}
void Semaphore::releaseSemaphore(void * semaphore)
{
AssertFatal(semaphore, "Semaphore::releaseSemaphore: invalid semaphore");
ReleaseSemaphore(*(HANDLE*)semaphore, 1, 0);
}

288
platformWin32/winStrings.cc Normal file
View file

@ -0,0 +1,288 @@
//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#include "PlatformWin32/platformWin32.h"
#ifdef HAS_VSSCANF
# undef HAS_VSSCANF
#endif
#if defined(__MWERKS__) && __MWERKS__ >= 0x2400
# define HAS_VSSCANF
# define __vsscanf vsscanf
#endif
#ifdef __BORLANDC__
# define _stricmp stricmp
# define _strnicmp strnicmp
# define _strupr strupr
# define _strlwr strlwr
# define __vsscanf vsscanf
#endif
char *dStrdup_r(const char *src, const char *fileName, U32 lineNumber)
{
char *buffer = (char *) dMalloc_r(dStrlen(src) + 1, fileName, lineNumber);
dStrcpy(buffer, src);
return buffer;
}
char* dStrcat(char *dst, const char *src)
{
return strcat(dst,src);
}
S32 dStrcmp(const char *str1, const char *str2)
{
return strcmp(str1, str2);
}
S32 dStricmp(const char *str1, const char *str2)
{
return _stricmp(str1, str2);
}
S32 dStrncmp(const char *str1, const char *str2, U32 len)
{
return strncmp(str1, str2, len);
}
S32 dStrnicmp(const char *str1, const char *str2, U32 len)
{
return _strnicmp(str1, str2, len);
}
char* dStrcpy(char *dst, const char *src)
{
return strcpy(dst,src);
}
char* dStrncpy(char *dst, const char *src, U32 len)
{
return strncpy(dst,src,len);
}
U32 dStrlen(const char *str)
{
return strlen(str);
}
char* dStrupr(char *str)
{
#ifdef __MWERKS__ // metrowerks strupr is broken
_strupr(str);
return str;
#else
return _strupr(str);
#endif
}
char* dStrlwr(char *str)
{
return _strlwr(str);
}
char* dStrchr(char *str, S32 c)
{
return strchr(str,c);
}
const char* dStrchr(const char *str, S32 c)
{
return strchr(str,c);
}
const char* dStrrchr(const char *str, S32 c)
{
return strrchr(str,c);
}
char* dStrrchr(char *str, S32 c)
{
return strrchr(str,c);
}
U32 dStrspn(const char *str, const char *set)
{
return(strspn(str, set));
}
U32 dStrcspn(const char *str, const char *set)
{
return strcspn(str, set);
}
char* dStrstr(char *str1, char *str2)
{
return strstr(str1,str2);
}
const char* dStrstr(const char *str1, const char *str2)
{
return strstr(str1,str2);
}
char* dStrtok(char *str, const char *sep)
{
return strtok(str, sep);
}
S32 dAtoi(const char *str)
{
return atoi(str);
}
F32 dAtof(const char *str)
{
return atof(str);
}
bool dAtob(const char *str)
{
return !dStricmp(str, "true") || dAtof(str);
}
bool dIsalnum(const char c)
{
return isalnum(c);
}
bool dIsalpha(const char c)
{
return(isalpha(c));
}
bool dIsspace(const char c)
{
return(isspace(c));
}
bool dIsdigit(const char c)
{
return(isdigit(c));
}
void dPrintf(const char *format, ...)
{
va_list args;
va_start(args, format);
vprintf(format, args);
}
S32 dVprintf(const char *format, void *arglist)
{
S32 len = vprintf(format, (char*)arglist);
return (len);
}
S32 dSprintf(char *buffer, U32 bufferSize, const char *format, ...)
{
va_list args;
va_start(args, format);
#ifdef __MWERKS__
S32 len = vsnprintf(buffer, bufferSize, format, args);
#else
bufferSize;
S32 len = vsprintf(buffer, format, args);
#endif
return (len);
}
S32 dVsprintf(char *buffer, U32 bufferSize, const char *format, void *arglist)
{
#ifdef __MWERKS__
S32 len = vsnprintf(buffer, bufferSize, format, (char*)arglist);
#else
bufferSize;
S32 len = vsprintf(buffer, format, (char*)arglist);
#endif
// S32 len = vsnprintf(buffer, bufferSize, format, (char*)arglist);
return (len);
}
S32 dSscanf(const char *buffer, const char *format, ...)
{
va_list args;
#if defined(HAS_VSSCANF)
va_start(args, format);
return __vsscanf(buffer, format, args);
#else
va_start(args, format);
// Boy is this lame. We have to scan through the format string, and find out how many
// arguments there are. We'll store them off as void*, and pass them to the sscanf
// function through specialized calls. We're going to have to put a cap on the number of args that
// can be passed, 8 for the moment. Sigh.
static void* sVarArgs[20];
U32 numArgs = 0;
for (const char* search = format; *search != '\0'; search++) {
if (search[0] == '%' && search[1] != '%')
numArgs++;
}
AssertFatal(numArgs <= 20, "Error, too many arguments to lame implementation of dSscanf. Fix implmentation");
// Ok, we have the number of arguments...
for (U32 i = 0; i < numArgs; i++)
sVarArgs[i] = va_arg(args, void*);
va_end(args);
switch (numArgs) {
case 0: return 0;
case 1: return sscanf(buffer, format, sVarArgs[0]);
case 2: return sscanf(buffer, format, sVarArgs[0], sVarArgs[1]);
case 3: return sscanf(buffer, format, sVarArgs[0], sVarArgs[1], sVarArgs[2]);
case 4: return sscanf(buffer, format, sVarArgs[0], sVarArgs[1], sVarArgs[2], sVarArgs[3]);
case 5: return sscanf(buffer, format, sVarArgs[0], sVarArgs[1], sVarArgs[2], sVarArgs[3], sVarArgs[4]);
case 6: return sscanf(buffer, format, sVarArgs[0], sVarArgs[1], sVarArgs[2], sVarArgs[3], sVarArgs[4], sVarArgs[5]);
case 7: return sscanf(buffer, format, sVarArgs[0], sVarArgs[1], sVarArgs[2], sVarArgs[3], sVarArgs[4], sVarArgs[5], sVarArgs[6]);
case 8: return sscanf(buffer, format, sVarArgs[0], sVarArgs[1], sVarArgs[2], sVarArgs[3], sVarArgs[4], sVarArgs[5], sVarArgs[6], sVarArgs[7]);
case 9: return sscanf(buffer, format, sVarArgs[0], sVarArgs[1], sVarArgs[2], sVarArgs[3], sVarArgs[4], sVarArgs[5], sVarArgs[6], sVarArgs[7], sVarArgs[8]);
case 10: return sscanf(buffer, format, sVarArgs[0], sVarArgs[1], sVarArgs[2], sVarArgs[3], sVarArgs[4], sVarArgs[5], sVarArgs[6], sVarArgs[7], sVarArgs[8], sVarArgs[9]);
case 11: return sscanf(buffer, format, sVarArgs[0], sVarArgs[1], sVarArgs[2], sVarArgs[3], sVarArgs[4], sVarArgs[5], sVarArgs[6], sVarArgs[7], sVarArgs[8], sVarArgs[9], sVarArgs[10]);
case 12: return sscanf(buffer, format, sVarArgs[0], sVarArgs[1], sVarArgs[2], sVarArgs[3], sVarArgs[4], sVarArgs[5], sVarArgs[6], sVarArgs[7], sVarArgs[8], sVarArgs[9], sVarArgs[10], sVarArgs[11]);
case 13: return sscanf(buffer, format, sVarArgs[0], sVarArgs[1], sVarArgs[2], sVarArgs[3], sVarArgs[4], sVarArgs[5], sVarArgs[6], sVarArgs[7], sVarArgs[8], sVarArgs[9], sVarArgs[10], sVarArgs[11], sVarArgs[12]);
case 14: return sscanf(buffer, format, sVarArgs[0], sVarArgs[1], sVarArgs[2], sVarArgs[3], sVarArgs[4], sVarArgs[5], sVarArgs[6], sVarArgs[7], sVarArgs[8], sVarArgs[9], sVarArgs[10], sVarArgs[11], sVarArgs[12], sVarArgs[13]);
case 15: return sscanf(buffer, format, sVarArgs[0], sVarArgs[1], sVarArgs[2], sVarArgs[3], sVarArgs[4], sVarArgs[5], sVarArgs[6], sVarArgs[7], sVarArgs[8], sVarArgs[9], sVarArgs[10], sVarArgs[11], sVarArgs[12], sVarArgs[13], sVarArgs[14]);
case 16: return sscanf(buffer, format, sVarArgs[0], sVarArgs[1], sVarArgs[2], sVarArgs[3], sVarArgs[4], sVarArgs[5], sVarArgs[6], sVarArgs[7], sVarArgs[8], sVarArgs[9], sVarArgs[10], sVarArgs[11], sVarArgs[12], sVarArgs[13], sVarArgs[14], sVarArgs[15]);
case 17: return sscanf(buffer, format, sVarArgs[0], sVarArgs[1], sVarArgs[2], sVarArgs[3], sVarArgs[4], sVarArgs[5], sVarArgs[6], sVarArgs[7], sVarArgs[8], sVarArgs[9], sVarArgs[10], sVarArgs[11], sVarArgs[12], sVarArgs[13], sVarArgs[14], sVarArgs[15], sVarArgs[16]);
case 18: return sscanf(buffer, format, sVarArgs[0], sVarArgs[1], sVarArgs[2], sVarArgs[3], sVarArgs[4], sVarArgs[5], sVarArgs[6], sVarArgs[7], sVarArgs[8], sVarArgs[9], sVarArgs[10], sVarArgs[11], sVarArgs[12], sVarArgs[13], sVarArgs[14], sVarArgs[15], sVarArgs[16], sVarArgs[17]);
case 19: return sscanf(buffer, format, sVarArgs[0], sVarArgs[1], sVarArgs[2], sVarArgs[3], sVarArgs[4], sVarArgs[5], sVarArgs[6], sVarArgs[7], sVarArgs[8], sVarArgs[9], sVarArgs[10], sVarArgs[11], sVarArgs[12], sVarArgs[13], sVarArgs[14], sVarArgs[15], sVarArgs[16], sVarArgs[17], sVarArgs[18]);
case 20: return sscanf(buffer, format, sVarArgs[0], sVarArgs[1], sVarArgs[2], sVarArgs[3], sVarArgs[4], sVarArgs[5], sVarArgs[6], sVarArgs[7], sVarArgs[8], sVarArgs[9], sVarArgs[10], sVarArgs[11], sVarArgs[12], sVarArgs[13], sVarArgs[14], sVarArgs[15], sVarArgs[16], sVarArgs[17], sVarArgs[18], sVarArgs[19]);
}
return 0;
#endif
}
S32 dFflushStdout()
{
return fflush(stdout);
}
S32 dFflushStderr()
{
return fflush(stderr);
}
void dQsort(void *base, U32 nelem, U32 width, S32 (QSORT_CALLBACK *fcmp)(const void *, const void *))
{
qsort(base, nelem, width, fcmp);
}

View file

@ -0,0 +1,98 @@
//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#include "Platform/platformThread.h"
#include "PlatformWin32/platformWin32.h"
#include "Platform/platformSemaphore.h"
//--------------------------------------------------------------------------
struct WinThreadData
{
ThreadRunFunction mRunFunc;
S32 mRunArg;
Thread * mThread;
void * mSemaphore;
WinThreadData()
{
mRunFunc = 0;
mRunArg = 0;
mThread = 0;
mSemaphore = 0;
};
};
//--------------------------------------------------------------------------
Thread::Thread(ThreadRunFunction func, S32 arg, bool start_thread)
{
WinThreadData * threadData = new WinThreadData();
threadData->mRunFunc = func;
threadData->mRunArg = arg;
threadData->mThread = this;
threadData->mSemaphore = Semaphore::createSemaphore();
mData = reinterpret_cast<void*>(threadData);
if (start_thread)
start();
}
Thread::~Thread()
{
join();
WinThreadData * threadData = reinterpret_cast<WinThreadData*>(mData);
Semaphore::destroySemaphore(threadData->mSemaphore);
delete threadData;
}
static DWORD WINAPI ThreadRunHandler(void * arg)
{
WinThreadData * threadData = reinterpret_cast<WinThreadData*>(arg);
threadData->mThread->run(threadData->mRunArg);
Semaphore::releaseSemaphore(threadData->mSemaphore);
return(0);
}
void Thread::start()
{
if(isAlive())
return;
WinThreadData * threadData = reinterpret_cast<WinThreadData*>(mData);
Semaphore::acquireSemaphore(threadData->mSemaphore);
DWORD threadID;
CreateThread(0, 0, ThreadRunHandler, mData, 0, &threadID);
}
bool Thread::join()
{
if(!isAlive())
return(false);
WinThreadData * threadData = reinterpret_cast<WinThreadData*>(mData);
return(Semaphore::acquireSemaphore(threadData->mSemaphore));
}
void Thread::run(S32 arg)
{
WinThreadData * threadData = reinterpret_cast<WinThreadData*>(mData);
if(threadData->mRunFunc)
threadData->mRunFunc(arg);
}
bool Thread::isAlive()
{
WinThreadData * threadData = reinterpret_cast<WinThreadData*>(mData);
bool signal = Semaphore::acquireSemaphore(threadData->mSemaphore, false);
if(signal)
Semaphore::releaseSemaphore(threadData->mSemaphore);
return(!signal);
}

87
platformWin32/winTime.cc Normal file
View file

@ -0,0 +1,87 @@
//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#include "PlatformWin32/platformWin32.h"
#include "time.h"
//--------------------------------------
void Platform::getLocalTime(LocalTime &lt)
{
struct tm *systime;
time_t long_time;
time( &long_time ); // Get time as long integer.
systime = localtime( &long_time ); // Convert to local time.
lt.sec = systime->tm_sec;
lt.min = systime->tm_min;
lt.hour = systime->tm_hour;
lt.month = systime->tm_mon;
lt.monthday = systime->tm_mday;
lt.weekday = systime->tm_wday;
lt.year = systime->tm_year;
lt.yearday = systime->tm_yday;
lt.isdst = systime->tm_isdst;
}
U32 Platform::getTime()
{
time_t long_time;
time( &long_time );
return long_time;
}
U32 Platform::getRealMilliseconds()
{
return GetTickCount();
}
U32 Platform::getVirtualMilliseconds()
{
return winState.currentTime;
}
void Platform::advanceTime(U32 delta)
{
winState.currentTime += delta;
}
//------------------------------------------------------------------------------
//-------------------------------------- Linux Implementation
//
//
// static bool sg_initialized = false;
// static U32 sg_secsOffset = 0;
//
// //--------------------------------------
// U32
// Platform::getTickCount()
// {
// // TODO: What happens when crossing a day boundary?
// //
// timeval t;
//
// if (sg_initialized == false) {
// sg_initialized = true;
//
// gettimeofday(&t, NULL);
// sg_secsOffset = t.tv_sec;
// }
//
// gettimeofday(&t, NULL);
//
// U32 secs = t.tv_sec - sg_secsOffset;
// U32 uSecs = t.tv_usec;
//
// // Make granularity 1 ms
// return (secs * 1000) + (uSecs / 1000);
// }

668
platformWin32/winV2Video.cc Normal file
View file

@ -0,0 +1,668 @@
//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#include "platformWIN32/platformGL.h"
#include "platformWIN32/platformWin32.h"
#include "platform/platformAudio.h"
#include "platformWIN32/winV2Video.h"
#include "platform/3dfx.h"
#include "console/console.h"
#include "math/mPoint.h"
#include "platform/event.h"
#include "platform/gameInterface.h"
#include "console/consoleInternal.h"
#include "console/ast.h"
#include "core/fileStream.h"
static U8 sResCode; // Used for initializing the resolution list only
static void execScript(const char *scriptFile)
{
// execute the script
FileStream str;
if (!str.open(scriptFile, FileStream::Read))
return;
U32 size = str.getStreamSize();
char *script = new char[size + 1];
str.read(size, script);
str.close();
script[size] = 0;
Con::executef(2, "eval", script);
delete[] script;
}
//------------------------------------------------------------------------------
Voodoo2Device::Voodoo2Device()
{
initDevice();
}
//------------------------------------------------------------------------------
void Voodoo2Device::initDevice()
{
// Set the device name:
mDeviceName = "Voodoo2";
// Set some initial conditions:
mResolutionList.clear();
mFullScreenOnly = true;
// Enumerate all available resolutions:
Resolution newRes;
newRes = Resolution( 640, 480, 16 );
mResolutionList.push_back( newRes );
if ( sResCode & 1 )
{
newRes = Resolution( 800, 600, 16 );
mResolutionList.push_back( newRes );
}
if ( sResCode & 2 )
{
Con::printf( "SLI detected." );
newRes = Resolution( 960, 720, 16 );
mResolutionList.push_back( newRes );
newRes = Resolution( 1024, 768, 16 );
mResolutionList.push_back( newRes );
}
}
//------------------------------------------------------------------------------
bool Voodoo2Device::activate( U32 width, U32 height, U32 /*bpp*/, bool /*fullScreen*/ )
{
bool needResurrect = false;
// If the rendering context exists, delete it:
if ( winState.hGLRC )
{
Con::printf( "Killing the texture manager..." );
Game->textureKill();
needResurrect = true;
Con::printf( "Making the rendering context not current..." );
if ( !qwglMakeCurrent( NULL, NULL ) )
{
AssertFatal( false, "Voodoo2Device::activate\nqwglMakeCurrent( NULL, NULL ) failed!" );
return false;
}
Con::printf( "Deleting the rendering context..." );
if ( !qwglDeleteContext( winState.hGLRC ) )
{
AssertFatal( false, "Voodoo2Device::activate\nqwglDeleteContext failed!" );
return false;
}
winState.hGLRC = NULL;
}
// If window already exists, kill it so we can start fresh:
if ( winState.appWindow )
{
Con::printf( "Releasing the device context..." );
ReleaseDC( winState.appWindow, winState.appDC );
winState.appDC = NULL;
Con::printf( "Destroying the window..." );
DestroyWindow( winState.appWindow );
winState.appWindow = NULL;
}
// If OpenGL library already loaded, shut it down and reload the 3Dfx standalone driver:
if ( winState.hinstOpenGL )
QGL_Shutdown();
QGL_Init( "3dfxvgl", "glu32" );
// This device only supports full-screen, so force it:
smIsFullScreen = true;
Con::setVariable( "$pref::Video::fullScreen", "true" );
// Create the new window:
Con::printf( "Creating a new full-screen window..." );
winState.appWindow = CreateOpenGLWindow( width, height, true );
if ( !winState.appWindow )
{
AssertFatal( false, "Voodoo2Device::activate\nFailed to create a window!" );
return false;
}
// Get a device context from the new window:
HDC tempDC = GetDC( winState.appWindow );
if ( !tempDC )
{
AssertFatal( false, "Voodoo2Device::activate\nFailed to get a device context!" );
return false;
}
// Set the pixel format of the new window:
PIXELFORMATDESCRIPTOR pfd;
CreatePixelFormat( &pfd, 16, 16, 8, false );
S32 chosenFormat = ChooseBestPixelFormat( tempDC, &pfd );
qwglDescribePixelFormat( tempDC, chosenFormat, sizeof( pfd ), &pfd );
bool test = qwglSetPixelFormat( tempDC, chosenFormat, &pfd );
ReleaseDC( winState.appWindow, tempDC );
if ( !test )
{
AssertFatal( false, "Voodoo2Device::activate\nFailed to set the pixel format of the device context!" );
return false;
}
Con::printf( "Pixel format set:" );
Con::printf( " %d color bits, %d depth bits, %d stencil bits", pfd.cColorBits, pfd.cDepthBits, pfd.cStencilBits );
// Set the resolution:
smCurrentRes.bpp = 16; // Force 16-bit color.
if ( !setScreenMode( width, height, 16, true, true, false ) )
return false;
// Output some driver info to the console:
const char* vendorString = (const char*) glGetString( GL_VENDOR );
const char* rendererString = (const char*) glGetString( GL_RENDERER );
const char* versionString = (const char*) glGetString( GL_VERSION );
Con::printf( "OpenGL driver information:" );
if ( vendorString )
Con::printf( " Vendor: %s", vendorString );
if ( rendererString )
Con::printf( " Renderer: %s", rendererString );
if ( versionString )
Con::printf( " Version: %s", versionString );
// Set a few variables:
if ( Con::getIntVariable( "$pref::OpenGL::mipReduction" ) < 1 )
Con::setIntVariable( "$pref::OpenGL::mipReduction", 1 );
if ( Con::getIntVariable( "$pref::OpenGL::interiorMipReduction" ) < 1 )
Con::setIntVariable( "$pref::OpenGL::interiorMipReduction", 1 );
if ( Con::getIntVariable( "$pref::OpenGL::skyMipReduction" ) < 1 )
Con::setIntVariable( "$pref::OpenGL::skyMipReduction", 1 );
if (dStrcmp(vendorString, Con::getVariable("$pref::Video::profiledVendor")) ||
dStrcmp(rendererString, Con::getVariable("$pref::Video::profiledRenderer")))
{
// Voodoo2 defaults
Con::setBoolVariable("$pref::OpenGL::disableEXTCompiledVertexArray", false);
Con::setBoolVariable("$pref::OpenGL::disableSubImage", false);
Con::setBoolVariable("$pref::OpenGL::noEnvColor", true);
Con::setBoolVariable("$pref::OpenGL::disableARBTextureCompression", false);
Con::setBoolVariable("$pref::Interior::lockArrays", true);
Con::setBoolVariable("$pref::TS::skipFirstFog", false);
Con::setBoolVariable("$pref::OpenGL::noDrawArraysAlpha", true);
//Con::executef(2, "exec", "scripts/V2Profile.cs");
execScript("V2Profile.cs");
Con::setVariable("$pref::Video::profiledVendor", vendorString);
Con::setVariable("$pref::Video::profiledRenderer", rendererString);
// write out prefs
gEvalState.globalVars.exportVariables("$pref::*", "prefs/ClientPrefs.cs", false);
}
if ( needResurrect )
{
// Reload the textures:
Con::printf( "Resurrecting the texture manager..." );
Game->textureResurrect();
}
// Set the new window to the foreground:
ShowWindow( winState.appWindow, SW_SHOW );
SetForegroundWindow( winState.appWindow );
SetFocus( winState.appWindow );
QGL_EXT_Init();
Con::setBoolVariable( "$SwapIntervalSupported", false );
Con::setVariable( "$pref::Video::displayDevice", mDeviceName );
Con::setBoolVariable("$pref::OpenGL::allowTexGen", true);
return true;
}
//------------------------------------------------------------------------------
void Voodoo2Device::shutdown()
{
if ( winState.hGLRC )
{
qwglMakeCurrent( NULL, NULL );
qwglDeleteContext( winState.hGLRC );
winState.hGLRC = NULL;
}
if ( winState.appDC )
{
ReleaseDC( winState.appWindow, winState.appDC );
winState.appDC = NULL;
}
ChangeDisplaySettings( NULL, 0 );
}
//------------------------------------------------------------------------------
bool Voodoo2Device::setScreenMode( U32 width, U32 height, U32 bpp, bool fullScreen, bool forceIt, bool repaint )
{
HWND curtain = NULL;
bool needResurrect = false;
Resolution newRes( width, height, bpp );
if ( !fullScreen )
{
// The 3Dfx Voodoo2 OpenGL driver only runs in full-screen, so ignore:
Con::warnf( ConsoleLogEntry::General, "Sorry, the Voodoo 2 display device only supports full-screen!" );
}
// Force the res to be one of the ones in the supported list:
U32 resIndex = 0;
U32 bestScore = 0, thisScore = 0;
for ( U32 i = 0; i < mResolutionList.size(); i++ )
{
if ( newRes == mResolutionList[i] )
{
resIndex = i;
break;
}
else
{
thisScore = abs( S32( newRes.w ) - S32( mResolutionList[i].w ) ) + abs( S32( newRes.h ) - S32( mResolutionList[i].h ) );
if ( !bestScore || thisScore < bestScore )
{
bestScore = thisScore;
resIndex = i;
}
}
}
newRes = mResolutionList[resIndex];
// Return if we aren't forcing it and we are already in the desired resolution:
if ( !forceIt && newRes == smCurrentRes )
return true;
Con::printf( "Setting screen mode to %dx%dx16 (fs)...", newRes.w, newRes.h );
// Delete the rendering context:
if ( winState.hGLRC )
{
Con::printf( "Killing the texture manager..." );
Game->textureKill();
needResurrect = true;
Con::printf( "Making the rendering context not current..." );
if ( !qwglMakeCurrent( NULL, NULL ) )
{
AssertFatal( false, "Voodoo2Device::setScreenMode\nqwglMakeCurrent( NULL, NULL ) failed!" );
return false;
}
Con::printf( "Deleting the rendering context..." );
if ( !qwglDeleteContext( winState.hGLRC ) )
{
AssertFatal( false, "Voodoo2Device::setScreenMode\nqwglDeleteContext failed!" );
return false;
}
winState.hGLRC = NULL;
}
// Release the device context:
if ( winState.appDC )
{
Con::printf( "Releasing the device context..." );
ReleaseDC( winState.appWindow, winState.appDC );
winState.appDC = NULL;
}
// Change the display settings (shouldn't really be necessary, but is):
U32 test;
DEVMODE devMode;
dMemset( &devMode, 0, sizeof( devMode ) );
devMode.dmSize = sizeof( devMode );
devMode.dmPelsWidth = newRes.w;
devMode.dmPelsHeight = newRes.h;
devMode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
Con::printf( "Changing the display settings to %dx%dx16...", newRes.w, newRes.h );
curtain = CreateCurtain( newRes.w, newRes.h );
test = ChangeDisplaySettings( &devMode, CDS_FULLSCREEN );
if ( test != DISP_CHANGE_SUCCESSFUL )
{
ChangeDisplaySettings( NULL, 0 );
switch( test )
{
case DISP_CHANGE_RESTART:
Platform::AlertOK( "Display Change Failed", "You must restart your machine to get the specified mode." );
break;
case DISP_CHANGE_BADMODE:
Platform::AlertOK( "Display Change Failed", "The specified mode is not supported by this device." );
break;
default:
Platform::AlertOK( "Display Change Failed", "Hardware failed to switch to the specified mode." );
break;
};
return false;
}
// Resize the window:
if ( !SetWindowPos( winState.appWindow, NULL, 0, 0, newRes.w, newRes.h, SWP_NOZORDER | SWP_NOMOVE ) )
{
Con::printf( "Voodoo2Device::setScreenMode - SetWindowPos sizing to %dx%d failed.", newRes.w, newRes.h );
return false;
}
// Get a new device context:
Con::printf( "Acquiring a new device context..." );
winState.appDC = GetDC( winState.appWindow );
if ( !winState.appDC )
{
AssertFatal( false, "Voodoo2Device::setScreenMode\nFailed to get a valid device context!" );
return false;
}
// Create a new rendering context:
Con::printf( "Creating a new rendering context..." );
winState.hGLRC = qwglCreateContext( winState.appDC );
if ( !winState.hGLRC )
{
AssertFatal( false, "Voodoo2Device::setScreenMode\nFailed to create a GL rendering context!" );
return false;
}
// Make the new rendering context current:
Con::printf( "Making the new rendering context current..." );
if ( !qwglMakeCurrent( winState.appDC, winState.hGLRC ) )
{
AssertFatal( false, "Voodoo2Device::setScreenMode\nFailed to make the rendering context current!" );
return false;
}
if ( needResurrect )
{
// Reload the textures:
Con::printf( "Resurrecting the texture manager..." );
Game->textureResurrect();
}
smCurrentRes = newRes;
Platform::setWindowSize( newRes.w, newRes.h );
char tempBuf[15];
dSprintf( tempBuf, sizeof( tempBuf ), "%d %d %d", smCurrentRes.w, smCurrentRes.h, smCurrentRes.bpp );
Con::setVariable( "$pref::Video::resolution", tempBuf );
if ( curtain )
DestroyWindow( curtain );
if ( repaint )
Con::evaluate( "resetCanvas();" );
return true;
}
//------------------------------------------------------------------------------
void Voodoo2Device::swapBuffers()
{
qwglSwapBuffers( winState.appDC );
}
//------------------------------------------------------------------------------
const char* Voodoo2Device::getDriverInfo()
{
// Output some driver info to the console:
const char* vendorString = (const char*) glGetString( GL_VENDOR );
const char* rendererString = (const char*) glGetString( GL_RENDERER );
const char* versionString = (const char*) glGetString( GL_VERSION );
const char* extensionsString = (const char*) glGetString( GL_EXTENSIONS );
// TODO - move strings out of code and into script...
U32 bufferLen = ( vendorString ? dStrlen( vendorString ) : 0 )
+ ( rendererString ? dStrlen( rendererString ) : 0 )
+ ( versionString ? dStrlen( versionString ) : 0 )
+ ( extensionsString ? dStrlen( extensionsString ) : 0 )
+ 4;
char* returnString = Con::getReturnBuffer( bufferLen );
dSprintf( returnString, bufferLen, "%s\t%s\t%s\t%s",
( vendorString ? vendorString : "" ),
( rendererString ? rendererString : "" ),
( versionString ? versionString : "" ),
( extensionsString ? extensionsString : "" ) );
return( returnString );
}
//------------------------------------------------------------------------------
bool Voodoo2Device::getGammaCorrection(F32 &g)
{
// apparently the qwlGetDeviceGammaRamp3DFX doesn't actually work. So, this
// is a good default. We don't need to worry about restoring the original
// gamma. Anything we do is wiped out once we destroy the Voodoo2 window.
g = 0.8;
return true;
U16 ramp[256*3];
if (!qwglGetDeviceGammaRamp3DFX(winState.appDC, ramp))
return false;
F32 csum = 0.0;
U32 ccount = 0;
for (U16 i = 0; i < 256; ++i)
{
if (i != 0 && ramp[i] != 0 && ramp[i] != 65535)
{
F64 b = (F64) i/256.0;
F64 a = (F64) ramp[i]/65535.0;
F32 c = (F32) (mLog(a)/mLog(b));
csum += c;
++ccount;
}
}
g = csum/ccount;
return true;
}
//------------------------------------------------------------------------------
bool Voodoo2Device::setGammaCorrection(F32 g)
{
U16 ramp[256*3];
for (U16 i = 0; i < 256; ++i)
ramp[i] = mPow((F32) i/256.0f, g) * 65535.0f;
dMemcpy(&ramp[256],ramp,256*sizeof(U16));
dMemcpy(&ramp[512],ramp,256*sizeof(U16));
return qwglSetDeviceGammaRamp3DFX(winState.appDC, ramp);
}
//------------------------------------------------------------------------------
bool Voodoo2Device::setVerticalSync( bool on )
{
on;
return( false );
}
//------------------------------------------------------------------------------
// Stuff for Voodoo 2 detection:
#ifndef GR_HARDWARE
#define GR_HARDWARE 0xa1
#endif
#define GLIDE_NUM_TMU 2
#define MAX_NUM_SST 4
typedef S32 GrSstType;
#define GR_SSTTYPE_VOODOO 0
#define GR_SSTTYPE_SST96 1
#define GR_SSTTYPE_AT3D 2
typedef struct GrTMUConfig_St
{
S32 tmuRev; /* Rev of Texelfx chip */
S32 tmuRam; /* 1, 2, or 4 MB */
} GrTMUConfig_t;
typedef struct GrVoodooConfig_St
{
S32 fbRam; /* 1, 2, or 4 MB */
S32 fbiRev; /* Rev of Pixelfx chip */
S32 nTexelfx; /* How many texelFX chips are there? */
FxBool sliDetect; /* Is it a scan-line interleaved board? */
GrTMUConfig_t tmuConfig[GLIDE_NUM_TMU]; /* Configuration of the Texelfx chips */
} GrVoodooConfig_t;
typedef struct GrSst96Config_St
{
S32 fbRam; /* How much? */
S32 nTexelfx;
GrTMUConfig_t tmuConfig;
} GrSst96Config_t;
typedef struct GrAT3DConfig_St
{
S32 rev;
} GrAT3DConfig_t;
typedef struct
{
S32 num_sst; /* # of HW units in the system */
struct
{
GrSstType type; /* Which hardware is it? */
union SstBoard_u
{
GrVoodooConfig_t VoodooConfig;
GrSst96Config_t SST96Config;
GrAT3DConfig_t AT3DConfig;
} sstBoard;
} SSTs[MAX_NUM_SST]; /* configuration for each board */
} GrHwConfiguration;
typedef FxBool( FX_CALL *grSstQueryBoards_fpt )( GrHwConfiguration *hwconfig );
typedef FxBool( FX_CALL *grSstQueryHardware_fpt )( GrHwConfiguration *hwconfig );
typedef void ( FX_CALL *grGlideInit_fpt )( void );
typedef const char* ( FX_CALL *grGetString_fpt )( FxU32 pName );
typedef void( FX_CALL *grGlideShutdown_fpt )( void );
//------------------------------------------------------------------------------
DisplayDevice* Voodoo2Device::create()
{
// Detect the Voodoo2 OpenGL driver:
GrHwConfiguration hwConfig;
bool result = true;
// Reset the available resolution specifier code:
sResCode = 0;
grGlideInit_fpt grGlideInit = NULL;
grGlideShutdown_fpt grGlideShutdown = NULL;
grSstQueryBoards_fpt grSstQueryBoards = NULL;
grSstQueryHardware_fpt grSstQueryHardware = NULL;
grGetString_fpt grGetString = NULL;
// Let the Glide 2 stuff go first:
HINSTANCE glide2DLL = LoadLibrary( "glide2x" );
if ( !glide2DLL )
return NULL;
grSstQueryBoards = (grSstQueryBoards_fpt) GetProcAddress( glide2DLL, "_grSstQueryBoards@4" );
if ( grSstQueryBoards )
{
grSstQueryBoards( &hwConfig );
if ( hwConfig.num_sst == 0 )
result = false;
else
{
grGlideInit = (grGlideInit_fpt) GetProcAddress( glide2DLL, "_grGlideInit@0" );
grSstQueryHardware = (grSstQueryHardware_fpt) GetProcAddress( glide2DLL, "_grSstQueryHardware@4" );
grGlideShutdown = (grGlideShutdown_fpt) GetProcAddress( glide2DLL, "_grGlideShutdown@0" );
if ( grGlideInit && grSstQueryHardware && grGlideShutdown )
{
grGlideInit();
grSstQueryHardware( &hwConfig );
// Find out what resolutions are available:
if ( hwConfig.SSTs[0].sstBoard.VoodooConfig.sliDetect == 0 ) // SLI not detected.
{
if ( hwConfig.SSTs[0].sstBoard.VoodooConfig.fbRam >= 4 )
sResCode = 1; // low bit indicates 800x600
}
else // SLI detected.
{
sResCode = 1;
if ( hwConfig.SSTs[0].sstBoard.VoodooConfig.fbRam >= 4 )
sResCode += 2;
}
grGlideShutdown();
}
grGlideInit = NULL;
grGlideShutdown = NULL;
}
}
else
result = false;
FreeLibrary( glide2DLL );
if ( result )
{
// Glide 3's turn:
HINSTANCE glide3DLL = LoadLibrary( "glide3x" );
if ( !glide3DLL )
return NULL;
grGlideInit = (grGlideInit_fpt) GetProcAddress( glide3DLL, "_grGlideInit@0" );
grGetString = (grGetString_fpt) GetProcAddress( glide3DLL, "_grGetString@4" );
grGlideShutdown = (grGlideShutdown_fpt) GetProcAddress( glide3DLL, "_grGlideShutdown@0" );
if ( grGlideInit && grGetString && grGlideShutdown )
{
grGlideInit();
const char* hardware = grGetString( GR_HARDWARE );
if ( dStrcmp( hardware, "Voodoo2" ) != 0 )
result = false;
grGlideShutdown();
}
else
result = false;
FreeLibrary( glide3DLL );
}
if ( result )
return new Voodoo2Device();
else
return NULL;
}

View file

@ -0,0 +1,35 @@
//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#ifndef _WINV2VIDEO_H_
#define _WINV2VIDEO_H_
#ifndef _PLATFORMVIDEO_H_
#include "Platform/platformVideo.h"
#endif
class Voodoo2Device : public DisplayDevice
{
public:
Voodoo2Device();
void initDevice();
bool activate( U32 width, U32 height, U32 bpp, bool fullScreen );
void shutdown();
void destroy();
bool setScreenMode( U32 width, U32 height, U32 bpp, bool fullScreen, bool forceIt = false, bool repaint = true );
void swapBuffers();
const char* getDriverInfo();
bool getGammaCorrection(F32 &g);
bool setGammaCorrection(F32 g);
bool setVerticalSync( bool on );
static DisplayDevice* create();
};
#endif // _H_WINV2VIDEO

1385
platformWin32/winWindow.cc Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,18 @@
//win_common_prefix.h
// define our platform
#define TARG_WIN32 1
#define WIN32 1
// normally, this should be on for a PC build
#define USEASSEMBLYTERRBLEND 1
// we turn this on to use inlined CW6-safe ASM in CWProject builds.
// ... and thus not require NASM for CWProject building ...
#define TARG_INLINED_ASM 1
// these are general build flags V12 uses.
#define PNG_NO_READ_tIME 1
#define PNG_NO_WRITE_TIME 1
#define NO_MILES_OPENAL 1

View file

@ -0,0 +1,9 @@
//win_debug_prefix.h
#include "win_common_prefix.h"
#define V12_DEBUG 1
#define BUILD_SUFFIX "_DEBUG"
//OPENGL2D3D=glFOO
//GLU2D3D=gluFOO

View file

@ -0,0 +1,23 @@
//win_debug_prefix.h
#include "win_common_prefix.h"
// our defines
#define TARG_RELEASE 1
#define V12_NO_ASSERTS 1
#define BUILD_SUFFIX ""
// turn these off for now.
//#define DEBUG 1
//#define ENABLE_ASSERTS 1
// the PC doesn't need this. just the mac...
//#define ITFDUMP_NOASM 1
//#define USEASSEMBLYTERRBLEND 1
#define PNG_NO_READ_tIME 1
#define PNG_NO_WRITE_TIME 1
#define NO_MILES_OPENAL 1