2006-05-26 19:42:13 +00:00
//**************************************************************
//* OpenGLide - Glide to OpenGL Wrapper
//* http://openglide.sourceforge.net
//*
//* Main File
//*
//* OpenGLide is OpenSource under LGPL license
//* Originaly made by Fabio Barros
//* Modified by Paul for Glidos (http://www.glidos.net)
//* Mac version and additional features by Jens-Olaf Hemprich
//**************************************************************
# include "Glide.h"
# include "GlideApplication.h"
# include "GlideDisplay.h"
# include "GlideFramebuffer.h"
# include "GlideSettings.h"
# include "GLextensions.h"
# include "GLUtil.h"
# include "PGTexture.h"
# include "PGUTexture.h"
///////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////// Version numbers ///////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////
2007-11-16 19:33:32 +00:00
const char * OpenGLideVersion = " 0.13 " ;
2006-05-26 19:42:13 +00:00
///////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////
// Structs
GlideStruct Glide ;
OpenGLStruct OpenGL ;
GlideSettingsImpl UserConfig ;
GlideSettingsImpl InternalConfig ;
PGTexture * Textures = NULL ;
PGUTexture UTextures ;
GlideFramebuffer s_Framebuffer ;
// Number of Errors
unsigned long NumberOfErrors ;
OSErr InitMainVariables ( void )
{
OpenGL . WinOpen = false ;
OpenGL . GlideInit = false ;
NumberOfErrors = 0 ;
OSErr err = UserConfig . load ( ) ;
if ( err = = noErr )
{
// The following values must be updated right away, because the client application
// might call grSstQueryHardware() before opening a window
if ( ( UserConfig . TextureMemorySize > = OGL_MIN_TEXTURE_BUFFER ) & &
( UserConfig . TextureMemorySize < = OGL_MAX_TEXTURE_BUFFER ) )
{
UserConfig . TextureMemorySize = UserConfig . TextureMemorySize ;
}
if ( ( UserConfig . FrameBufferMemorySize > = OGL_MIN_FRAME_BUFFER ) & &
( UserConfig . FrameBufferMemorySize < = OGL_MAX_FRAME_BUFFER ) )
{
UserConfig . FrameBufferMemorySize = UserConfig . FrameBufferMemorySize ;
}
if ( UserConfig . BoardType < OpenGLideBoardType_Voodoo )
{
UserConfig . BoardType = OpenGLideBoardType_Voodoo ;
}
else if ( UserConfig . BoardType > OpenGLideBoardType_Voodoo2 )
{
UserConfig . BoardType = OpenGLideBoardType_Voodoo2 ;
}
if ( UserConfig . GlideTextureUnits < 1 )
{
UserConfig . GlideTextureUnits = 1 ;
}
else if ( UserConfig . GlideTextureUnits > 3 )
{
UserConfig . GlideTextureUnits = 3 ;
}
2006-07-06 21:21:07 +00:00
// Detect vector unit (Altivec, SSE, etc.)
UserConfig . VectorUnitType = GetVectorUnitType ( ) ;
if ( UserConfig . VectorUnitType > OpenGLideVectorUnitType_None )
{
GlideMsg ( " Using %s vector unit \n " , OpenGLideVectorUnitNames [ UserConfig . VectorUnitType - 1 ] ) ;
}
2006-05-26 19:42:13 +00:00
// Apply mandatory application dependent settings/patches
GlideApplication : : Type application = s_GlideApplication . GetType ( ) ;
switch ( application )
{
case GlideApplication : : Quake :
{
// Quake would not display anything without fixing the memory
unsigned int megabytes = 4 ;
if ( UserConfig . FrameBufferMemorySize > megabytes )
{
UserConfig . FrameBufferMemorySize = megabytes ;
GlideMsg ( " Decreased frmaebuffer memory size to %d megabytes to make Quake 3Dfx happy \n " ) ;
}
}
break ;
}
// Apply optional game specific settings
if ( UserConfig . AutoEnableGameSpecificSettings )
{
bool texturesmoothing = false ;
bool subtextures = false ;
bool gapfix = false ;
switch ( application )
{
case GlideApplication : : Carmageddon :
texturesmoothing = true ;
break ;
case GlideApplication : : MythTFL :
texturesmoothing = true ;
break ;
case GlideApplication : : Falcon40 :
texturesmoothing = true ;
break ;
case GlideApplication : : TombRaiderI :
texturesmoothing = true ;
subtextures = true ;
gapfix = true ;
break ;
case GlideApplication : : TombRaiderII :
// subtextures = true; // works but slow
gapfix = true ;
break ;
default :
break ;
}
if ( texturesmoothing | | subtextures | | gapfix )
{
GlideMsg ( " Auto-enabling game specific settings for %s: \n " , s_GlideApplication . GetName ( ) ) ;
}
// Suppress artefacts in main menu
if ( texturesmoothing )
{
UserConfig . TextureSmoothing = true ;
2006-08-14 15:46:09 +00:00
GlideMsg ( " - TextureSmoothing \n " ) ;
2006-05-26 19:42:13 +00:00
}
if ( subtextures )
{
UserConfig . GenerateSubTextures = 8 ; // Good for TR1 and TR2
2006-08-14 15:46:09 +00:00
GlideMsg ( " - Subtexture generation \n " ) ;
2006-05-26 19:42:13 +00:00
}
if ( gapfix )
{
UserConfig . GapFix = static_cast < OpenGLideGapFixFlags > ( UserConfig . GapFix | ( OpenGLideGapFixFlag_Enabled ) ) ;
2006-08-14 15:46:09 +00:00
GlideMsg ( " - GapFix \n " ) ;
2006-05-26 19:42:13 +00:00
}
}
}
if ( err ! = noErr ) GlideError ( " Failed to load user config file: Error code %d " , err ) ;
return err ;
}
bool InitWindow ( FxU32 hwnd )
{
if ( InitialiseOpenGLWindow ( hwnd , 0 , 0 , OpenGL . WindowWidth , OpenGL . WindowHeight ) = = false )
{
return FXFALSE ;
}
// Initialise some basic OpenGL() settings
InitOpenGL ( ) ;
// Continue initialising OpenGL with processing
// the user config and setup OpenGL extensions
ValidateUserConfig ( ) ;
GlideMsg ( OGL_LOG_SEPARATE ) ;
2006-08-14 15:46:09 +00:00
GlideMsg ( " 3Dfx/Glide Configuration: \n " ) ;
2006-05-26 19:42:13 +00:00
GlideMsg ( OGL_LOG_SEPARATE ) ;
char sEnabled [ ] = " enabled " ;
char sDisabled [ ] = " disabled " ;
const char * boardnames [ 4 ] = { " Voodoo " , " Voodoo Rush " , " AT3D " , " Voodoo 2 " } ;
GlideMsg ( " Board type = %s \n " , boardnames [ InternalConfig . BoardType ] ) ;
2006-08-14 15:46:09 +00:00
GlideMsg ( " Number of emulated 3Dfx/Glide Texture Units = %d \n " , InternalConfig . GlideTextureUnits ) ;
2006-05-26 19:42:13 +00:00
GlideMsg ( " Texture Memory Size = %d Mb \n " , InternalConfig . TextureMemorySize ) ;
GlideMsg ( " Frame Buffer Memory Size = %d Mb \n " , InternalConfig . FrameBufferMemorySize ) ;
GlideMsg ( " Display method = %d \n " , InternalConfig . DisplayMode ) ;
// display resolution
GlideMsg ( " Display resolution = %dx%d \n " , OpenGL . WindowWidth , OpenGL . WindowHeight ) ;
if ( InternalConfig . MonitorRefreshRate > 0 )
{
GlideMsg ( " Monitor Refresh Rate = %d \n " , InternalConfig . MonitorRefreshRate ) ;
}
GlideMsg ( " Mipmapping %s \n " , InternalConfig . Mipmapping ? sEnabled : sDisabled ) ;
if ( InternalConfig . AnisotropylLevel > = 2 & & InternalConfig . EXT_texture_filter_anisotropic )
{
GlideMsg ( " Selected level of anisotropy = %d \n " , InternalConfig . AnisotropylLevel ) ;
}
else
{
GlideMsg ( " Anisotropic texture filtering disabled \n " ) ;
}
if ( InternalConfig . FullSceneAntiAliasing = = 0 )
{
GlideMsg ( " FullSceneAntiAliasing disabled \n " ) ;
}
else
{
GlideMsg ( " FullSceneAntiAliasing enabled, using %d samples \n " , InternalConfig . FullSceneAntiAliasing ) ;
}
GlideMsg ( " TextureSmoothing = %s \n " , InternalConfig . TextureSmoothing ? sEnabled : sDisabled ) ;
GlideMsg ( " Precision Fix = %s \n " , InternalConfig . PrecisionFix ? sEnabled : sDisabled ) ;
bool gapfix_enabled = InternalConfig . GapFix & OpenGLideGapFixFlag_Enabled ;
GlideMsg ( " GapFix = %s \n " , gapfix_enabled ? sEnabled : sDisabled ) ;
if ( gapfix_enabled )
{
2006-08-14 15:46:09 +00:00
GlideMsg ( " Debug = %s \n " , InternalConfig . GapFix & OpenGLideGapFixFlag_Debug ? sEnabled : sDisabled ) ;
2006-05-26 19:42:13 +00:00
GlideMsg ( " IncircleFilterOr = %s \n " , InternalConfig . GapFix & OpenGLideGapFixFlag_IncircleOr ? sEnabled : sDisabled ) ;
GlideMsg ( " IncircleFilterAnd = %s \n " , InternalConfig . GapFix & OpenGLideGapFixFlag_IncircleAnd ? sEnabled : sDisabled ) ;
GlideMsg ( " IncircleFilterSecondRadius = %s \n " , InternalConfig . GapFix & OpenGLideGapFixFlag_IncircleSecondRadius ? sEnabled : sDisabled ) ;
GlideMsg ( " VertexLengthFilterSecondRadius = %s \n " , InternalConfig . GapFix & OpenGLideGapFixFlag_VertexLengthSecondRadius ? sEnabled : sDisabled ) ;
GlideMsg ( " 1st radius = %g \n " , InternalConfig . GapFixParam1 ) ;
if ( InternalConfig . GapFix & OpenGLideGapFixFlag_VertexLengthSecondRadius )
{
GlideMsg ( " Vertex Length = %g \n " , InternalConfig . GapFixParam2 ) ;
}
else
{
GlideMsg ( " triangle isoscelesness= %g \n " , InternalConfig . GapFixParam2 ) ;
}
if ( ( InternalConfig . GapFix & OpenGLideGapFixFlag_IncircleSecondRadius ) | | ( InternalConfig . GapFix & OpenGLideGapFixFlag_VertexLengthSecondRadius ) )
{
GlideMsg ( " 2nd radius = %g \n " , InternalConfig . GapFixParam3 ) ;
}
if ( InternalConfig . GapFix & OpenGLideGapFixFlag_DepthFactor )
{
GlideMsg ( " Depth Factor = %g \n " , InternalConfig . GapFixDepthFactor ) ;
}
}
GlideMsg ( " Generate subtextures = %s " , InternalConfig . GenerateSubTextures ? sEnabled : sDisabled ) ;
if ( InternalConfig . GenerateSubTextures ) GlideMsg ( " (gridsize = %d) " , InternalConfig . GenerateSubTextures ) ;
GlideMsg ( " \n " ) ;
2006-08-14 15:46:09 +00:00
GlideMsg ( " Framebuffer overlays = %s \n " , InternalConfig . EnableFrameBufferOverlays ? sEnabled : sDisabled ) ;
2006-05-26 19:42:13 +00:00
GlideMsg ( " Framebuffer underlays = %s \n " , InternalConfig . EnableFrameBufferUnderlays ? sEnabled : sDisabled ) ;
if ( InternalConfig . FramebufferIgnoreUnlock ) GlideMsg ( " Ignore buffer unlocks = %s \n " , InternalConfig . FramebufferIgnoreUnlock ? sEnabled : sDisabled ) ;
if ( InternalConfig . PedanticFrameBufferEmulation ) GlideMsg ( " Pedantic Framebuffer emulation = %s \n " , InternalConfig . PedanticFrameBufferEmulation ? sEnabled : sDisabled ) ;
GlideMsg ( OGL_LOG_SEPARATE ) ;
# ifdef OGL_DEBUG
GlideMsg ( " GlideState size = %d \n " , sizeof ( GlideState ) ) ;
GlideMsg ( " GrState size = %d \n " , sizeof ( GrState ) ) ;
GlideMsg ( OGL_LOG_SEPARATE ) ;
# endif
GlideMsg ( " ** Glide Calls ** \n " ) ;
GlideMsg ( OGL_LOG_SEPARATE ) ;
return true ;
}
void * AllocFrameBuffer ( long buffersize , long buffertypesize )
{
void * buffer = AllocSysPtr16ByteAligned ( buffersize * buffertypesize ) ;
if ( buffer = = NULL )
{
GlideError ( " Could NOT allocate sufficient memory for framebuffer... Sorry. " ) ;
exit ( - 1 ) ;
}
return buffer ;
}
void FreeFrameBuffer ( void * buffer )
{
Free16ByteAligned ( buffer ) ;
}
void * AllocBuffer ( long buffersize , long buffertypesize )
{
void * buffer = AllocSysPtr16ByteAligned ( buffersize * buffertypesize ) ;
if ( buffer = = NULL )
{
GlideError ( " Could NOT allocate sufficient memory for buffer... Sorry. " ) ;
exit ( - 1 ) ;
}
return buffer ;
}
void FreeBuffer ( void * buffer )
{
Free16ByteAligned ( buffer ) ;
}
void * AllocObject ( long buffersize )
{
// Causes classic to crash
void * buffer = AllocSysPtr16ByteAligned ( buffersize ) ;
if ( buffer = = NULL )
{
GlideError ( " Could NOT allocate sufficient memory for object... Sorry. " ) ;
exit ( - 1 ) ;
}
return buffer ;
}
void FreeObject ( void * buffer )
{
Free16ByteAligned ( buffer ) ;
}
// error handling
# ifdef OPENGL_DEBUG
OSStatus glReportError_impl ( const char * __glide_functionname )
{
char * errortext = NULL ;
GLenum err = glGetError ( ) ;
switch ( err )
{
case GL_NO_ERROR :
break ;
case GL_INVALID_ENUM :
errortext = " Invalid enumeration " ;
break ;
case GL_INVALID_VALUE :
errortext = " Invalid value " ;
break ;
case GL_INVALID_OPERATION :
errortext = " Invalid operation " ;
break ;
case GL_STACK_OVERFLOW :
errortext = " Stack overflow " ;
break ;
case GL_STACK_UNDERFLOW :
errortext = " Stack underflow " ;
break ;
case GL_OUT_OF_MEMORY :
errortext = " Out of memory " ;
break ;
default :
errortext = " Unknown error code " ;
break ;
}
if ( errortext )
{
GlideMsg ( " Function %s, GL Error: %s \n " , __glide_functionname , errortext ) ;
}
// ensure we are returning an OSStatus noErr if no error condition
if ( err = = GL_NO_ERROR )
return noErr ;
else
return ( OSStatus ) err ;
}
# endif
# if defined(OPTIMISE_OPENGL_STATE_CHANGES) || defined(OGL_DEBUG) || defined(OPENGL_DEBUG)
bool VerifyActiveTextureUnit_impl ( GLint x , const char * functionname )
{
glReportErrors ( " VerifyActiveTextureUnit_impl " ) ;
GLint y ;
glGetIntegerv ( GL_ACTIVE_TEXTURE_ARB , & y ) ;
glReportError ( ) ;
bool bVerified = x = = y ;
if ( ! bVerified )
{
GlideMsg ( " Warning: %s() active texture unit is GL_TEXTURE%d_ARB, but should be GL_TEXTURE%d_ARB \n " , functionname , y - GL_TEXTURE0_ARB , x - GL_TEXTURE0_ARB ) ;
}
2006-06-12 14:05:39 +00:00
glGetIntegerv ( GL_CLIENT_ACTIVE_TEXTURE_ARB , & y ) ;
glReportError ( ) ;
bVerified = x = = y ;
if ( ! bVerified )
{
GlideMsg ( " Warning: %s() client active texture unit is GL_TEXTURE%d_ARB, but should be GL_TEXTURE%d_ARB \n " , functionname , y - GL_TEXTURE0_ARB , x - GL_TEXTURE0_ARB ) ;
}
2006-05-26 19:42:13 +00:00
return bVerified ;
}
# endif
# if defined(OPTIMISE_OPENGL_STATE_CHANGES) || defined(OGL_DEBUG) || defined(OPENGL_DEBUG)
bool VerifyTextureEnabledState_impl ( const char * functionname )
{
glReportErrors ( " VerifyActiveTextureUnit_impl " ) ;
2006-08-22 21:12:28 +00:00
// remember state
GLint activeTexture ;
glGetIntegerv ( GL_ACTIVE_TEXTURE_ARB , & activeTexture ) ;
GLint activeClientTexture ;
if ( InternalConfig . EXT_compiled_vertex_array )
{
glGetIntegerv ( GL_CLIENT_ACTIVE_TEXTURE_ARB , & activeClientTexture ) ;
}
2006-05-26 19:42:13 +00:00
glReportError ( ) ;
bool bVerified = true ;
if ( OpenGL . ColorAlphaUnit2 )
{
for ( long unit_index = 1 ; unit_index > = 0 ; unit_index - - )
{
glActiveTextureARB ( OpenGL . ColorAlphaUnit1 + unit_index ) ;
bool bState = glIsEnabled ( GL_TEXTURE_2D ) ;
if ( bState ! = ( OpenGL . ColorAlphaUnitColorEnabledState [ unit_index ] | |
OpenGL . ColorAlphaUnitAlphaEnabledState [ unit_index ] ) )
{
GlideMsg ( " Warning: texture unit GL_TEXTURE%d_ARB is %s in %s() \n " , OpenGL . ColorAlphaUnit1 + unit_index - GL_TEXTURE0_ARB , bState ? " enabled " : " disabled " , functionname ) ;
2006-06-12 14:05:39 +00:00
bVerified = false ;
}
2006-08-22 21:12:28 +00:00
if ( InternalConfig . EXT_compiled_vertex_array )
2006-06-12 14:05:39 +00:00
{
2006-08-22 21:12:28 +00:00
glClientActiveTextureARB ( OpenGL . ColorAlphaUnit1 + unit_index ) ;
bState = glIsEnabled ( GL_TEXTURE_COORD_ARRAY ) ;
if ( bState ! = ( OpenGL . ColorAlphaUnitColorEnabledState [ unit_index ] | |
OpenGL . ColorAlphaUnitAlphaEnabledState [ unit_index ] ) )
{
GlideMsg ( " Warning: texcoord array for unit GL_TEXTURE%d_ARB is %s in %s() \n " , OpenGL . ColorAlphaUnit1 + unit_index - GL_TEXTURE0_ARB , bState ? " enabled " : " disabled " , functionname ) ;
bVerified = false ;
}
2006-05-26 19:42:13 +00:00
}
glReportError ( ) ;
}
}
// Restore previous state
2006-08-22 21:12:28 +00:00
glActiveTextureARB ( activeTexture ) ;
if ( InternalConfig . EXT_compiled_vertex_array )
{
glClientActiveTextureARB ( activeClientTexture ) ;
}
glReportError ( ) ;
2006-05-26 19:42:13 +00:00
return bVerified ;
}
# endif
//*************************************************
//* Initializes OpenGL
//*************************************************
void InitOpenGL ( void )
{
OpenGL . ZNear = ZBUFFERNEAR ;
OpenGL . ZFar = ZBUFFERFAR ;
OpenGL . ClipMinX = 0 ;
OpenGL . ClipMinY = 0 ;
OpenGL . ClipMaxX = OpenGL . WindowWidth ;
OpenGL . ClipMaxY = OpenGL . WindowHeight ;
// Glide texture data is aligned at 8 byte boundaries
int alignment = 8 ;
glPixelStorei ( GL_PACK_ALIGNMENT , alignment ) ;
glPixelStorei ( GL_UNPACK_ALIGNMENT , alignment ) ;
}
void GlideMsg ( const char * message , . . . )
{
va_list ( args ) ;
va_start ( args , message ) ;
char buffer [ StringBufferSize ] ;
vsnprintf ( buffer , StringBufferSize , message , args ) ;
UserConfig . write_log ( buffer ) ;
va_end ( args ) ;
}
void GlideError ( const char * message , . . . )
{
va_list ( args ) ;
va_start ( args , message ) ;
char buffer [ StringBufferSize ] ;
NumberOfErrors + + ;
vsnprintf ( buffer , StringBufferSize , message , args ) ;
GlideMsg ( buffer ) ;
va_end ( args ) ;
grGlideShutdown ( ) ;
if ( UserConfig . DisplayMode = = OpenGLideDisplayMode_DisplayManager )
{
DisplayManager_RestoreDesktopDisplay ( ) ;
}
FatalErrorMessageBox ( buffer ) ;
exit ( 0 ) ;
}
bool ClearAndGenerateLogFile ( void )
{
UserConfig . create_log ( ) ;
char buffer [ 32 ] ;
GlideMsg ( OGL_LOG_SEPARATE ) ;
GlideMsg ( " %s Log File \n " , OpenGLideProductName ) ;
GlideMsg ( OGL_LOG_SEPARATE ) ;
GlideMsg ( " ***** %s %s ***** \n " , OpenGLideProductName , OpenGLideVersion ) ;
GlideMsg ( OGL_LOG_SEPARATE ) ;
_strdate ( buffer ) ;
GlideMsg ( " Date: %s \n " , buffer ) ;
_strtime ( buffer ) ;
GlideMsg ( " Time: %s \n " , buffer ) ;
GlideMsg ( " Application: %s \n " , s_GlideApplication . GetName ( ) ) ;
return true ;
}
void CloseLogFile ( void )
{
char tmpbuf [ 128 ] ;
GlideMsg ( OGL_LOG_SEPARATE ) ;
_strtime ( tmpbuf ) ;
GlideMsg ( " Time: %s \n " , tmpbuf ) ;
GlideMsg ( OGL_LOG_SEPARATE ) ;
}