diff --git a/win32/CDirect3D.cpp b/win32/CDirect3D.cpp index 204b30c3..a68d391c 100644 --- a/win32/CDirect3D.cpp +++ b/win32/CDirect3D.cpp @@ -178,9 +178,6 @@ #pragma comment( lib, "d3dx9" ) #pragma comment( lib, "DxErr" ) -#pragma comment( lib, "cg.lib" ) -#pragma comment( lib, "cgd3d9.lib" ) - #include "cdirect3d.h" #include "win32_display.h" #include "../snes9x.h" @@ -225,6 +222,7 @@ CDirect3D::CDirect3D() shaderTimeElapsed = 0; cgContext = NULL; cgVertexProgram = cgFragmentProgram = NULL; + cgAvailable = false; } /* CDirect3D::~CDirect3D() @@ -278,10 +276,14 @@ bool CDirect3D::Initialize(HWND hWnd) return false; } - cgContext = cgCreateContext(); - hr = cgD3D9SetDevice(pDevice); - if(FAILED(hr)) { - DXTRACE_ERR_MSGBOX(TEXT("Error setting cg device"), hr); + cgAvailable = loadCgFunctions(); + + if(cgAvailable) { + cgContext = cgCreateContext(); + hr = cgD3D9SetDevice(pDevice); + if(FAILED(hr)) { + DXTRACE_ERR_MSGBOX(TEXT("Error setting cg device"), hr); + } } pDevice->SetRenderState(D3DRS_LIGHTING, FALSE); @@ -323,7 +325,8 @@ void CDirect3D::DeInitialize() cgContext = NULL; } - cgD3D9SetDevice(NULL); + if(cgAvailable) + cgD3D9SetDevice(NULL); init_done = false; afterRenderWidth = 0; @@ -331,6 +334,8 @@ void CDirect3D::DeInitialize() quadTextureSize = 0; fullscreen = false; filterScale = 0; + unloadCgLibrary(); + cgAvailable = false; } bool CDirect3D::SetShader(const TCHAR *file) @@ -382,6 +387,12 @@ bool CDirect3D::SetShaderCG(const TCHAR *file) if (file == NULL || *file==TEXT('\0')) return true; + if(!cgAvailable) { + MessageBox(NULL, TEXT("The CG runtime is unavailable, CG shaders will not run.\nConsult the snes9x readme for information on how to obtain the runtime."), TEXT("CG Error"), + MB_OK|MB_ICONEXCLAMATION); + return false; + } + CGprofile vertexProfile = cgD3D9GetLatestVertexProfile(); CGprofile pixelProfile = cgD3D9GetLatestPixelProfile(); diff --git a/win32/CDirect3D.h b/win32/CDirect3D.h index 813b4078..49795dfd 100644 --- a/win32/CDirect3D.h +++ b/win32/CDirect3D.h @@ -183,8 +183,7 @@ #include #include -#include -#include +#include "cgFunctions.h" #include "render.h" #include "wsnes9x.h" @@ -225,6 +224,7 @@ private: CGcontext cgContext; CGprogram cgVertexProgram, cgFragmentProgram; current_d3d_shader_type shader_type; + bool cgAvailable; float shaderTimer; int shaderTimeStart; diff --git a/win32/COpenGL.cpp b/win32/COpenGL.cpp index 0b14c952..0828831c 100644 --- a/win32/COpenGL.cpp +++ b/win32/COpenGL.cpp @@ -9,9 +9,6 @@ #include "../filter/hq2x.h" #include "../filter/2xsai.h" -#pragma comment( lib, "cg.lib" ) -#pragma comment( lib, "cggl.lib" ) - COpenGL::COpenGL(void) { @@ -33,6 +30,7 @@ COpenGL::COpenGL(void) fragmentShader = 0; cgContext = NULL; cgVertexProgram = cgFragmentProgram = NULL; + cgAvailable = false; } COpenGL::~COpenGL(void) @@ -104,7 +102,10 @@ bool COpenGL::Initialize(HWND hWnd) glVertexPointer(2, GL_FLOAT, 0, vertices); glTexCoordPointer(2, GL_FLOAT, 0, texcoords); - cgContext = cgCreateContext(); + cgAvailable = loadCgFunctions(); + if(cgAvailable) { + cgContext = cgCreateContext(); + } GetClientRect(hWnd,&windowRect); ChangeRenderSize(windowRect.right,windowRect.bottom); @@ -139,6 +140,8 @@ void COpenGL::DeInitialize() afterRenderHeight = 0; shaderFunctionsLoaded = false; shader_type = OGL_SHADER_NONE; + unloadCgLibrary(); + cgAvailable = false; } void COpenGL::CreateDrawSurface() @@ -284,10 +287,6 @@ void COpenGL::Render(SSurface Src) cgGLSetStateMatrixParameter(cgpModelViewProj, CG_GL_MODELVIEW_PROJECTION_MATRIX, CG_GL_MATRIX_IDENTITY); - CGparameter cgpVideoSize = cgGetNamedParameter(cgFragmentProgram, "IN.video_size"); - CGparameter cgpTextureSize = cgGetNamedParameter(cgFragmentProgram, "IN.texture_size"); - CGparameter cgpOutputSize = cgGetNamedParameter(cgFragmentProgram, "IN.output_size"); - #define setProgram2fv(program,varname,floats)\ {\ CGparameter cgp = cgGetNamedParameter(program, varname);\ @@ -521,6 +520,7 @@ bool COpenGL::SetShadersCG(const TCHAR *file) { TCHAR errorMsg[MAX_PATH + 50]; HRESULT hr; + CGprofile vertexProfile, fragmentProfile; if(cgFragmentProgram) { cgDestroyProgram(cgFragmentProgram); @@ -531,15 +531,23 @@ bool COpenGL::SetShadersCG(const TCHAR *file) cgVertexProgram = NULL; } - CGprofile vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX); - CGprofile fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT); + if(cgAvailable) { + vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX); + fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT); - cgGLDisableProfile(vertexProfile); - cgGLDisableProfile(fragmentProfile); + cgGLDisableProfile(vertexProfile); + cgGLDisableProfile(fragmentProfile); + } if (file == NULL || *file==TEXT('\0')) return true; + if(!cgAvailable) { + MessageBox(NULL, TEXT("The CG runtime is unavailable, CG shaders will not run.\nConsult the snes9x readme for information on how to obtain the runtime."), TEXT("CG Error"), + MB_OK|MB_ICONEXCLAMATION); + return false; + } + cgGLSetOptimalOptions(vertexProfile); cgGLSetOptimalOptions(fragmentProfile); diff --git a/win32/COpenGL.h b/win32/COpenGL.h index 8adb1518..adb8949a 100644 --- a/win32/COpenGL.h +++ b/win32/COpenGL.h @@ -181,8 +181,7 @@ #include #include -#include -#include +#include "cgFunctions.h" #include "glext.h" #include "wglext.h" @@ -215,6 +214,7 @@ private: CGcontext cgContext; CGprogram cgVertexProgram, cgFragmentProgram; current_ogl_shader_type shader_type; + bool cgAvailable; GLuint shaderProgram; GLuint vertexShader; diff --git a/win32/cgFunctions.cpp b/win32/cgFunctions.cpp new file mode 100644 index 00000000..a1cfa39c --- /dev/null +++ b/win32/cgFunctions.cpp @@ -0,0 +1,152 @@ +#include "cgFunctions.h" + +HMODULE hCgDll = NULL; +HMODULE hCgD3D9Dll = NULL; +HMODULE hCgGLDll = NULL; + +//cg.dll +CGCC cgCreateContext = NULL; +CGDC cgDestroyContext = NULL; +CGGNP cgGetNamedParameter = NULL; +CGGE cgGetError = NULL; +CGGES cgGetErrorString = NULL; +CGGLL cgGetLastListing = NULL; +CGCP cgCreateProgram = NULL; +CGDP cgDestroyProgram = NULL; +//cgD3D9.dll +CGD3DSD cgD3D9SetDevice = NULL; +CGD3DBP cgD3D9BindProgram = NULL; +CGD3DGLVP cgD3D9GetLatestVertexProfile = NULL; +CGD3DGLPP cgD3D9GetLatestPixelProfile = NULL; +CGD3DGOO cgD3D9GetOptimalOptions = NULL; +CGD3DLP cgD3D9LoadProgram = NULL; +CGD3DSUM cgD3D9SetUniformMatrix = NULL; +CGD3DSU cgD3D9SetUniform = NULL; +//cggl.dll +CGGLSSMP cgGLSetStateMatrixParameter = NULL; +CGGLSP2FV cgGLSetParameter2fv = NULL; +CGGLGLP cgGLGetLatestProfile = NULL; +CGGLEP cgGLEnableProfile = NULL; +CGGLDP cgGLDisableProfile = NULL; +CGGLSOO cgGLSetOptimalOptions = NULL; +CGGLLP cgGLLoadProgram = NULL; +CGGLBP cgGLBindProgram = NULL; + +bool loadCgFunctions() +{ + if(hCgDll && hCgD3D9Dll && hCgGLDll) + return true; + + hCgDll = LoadLibrary(TEXT("cg.dll")); + if(hCgDll) { + hCgD3D9Dll = LoadLibrary(TEXT("cgD3D9.dll")); + hCgGLDll = LoadLibrary(TEXT("cgGL.dll")); + } + + if(!hCgDll || !hCgD3D9Dll || !hCgGLDll) { + unloadCgLibrary(); + return false; + } + + //cg.dll + cgCreateContext = (CGCC)GetProcAddress(hCgDll,"cgCreateContext"); + cgDestroyContext = (CGDC)GetProcAddress(hCgDll,"cgDestroyContext"); + cgGetNamedParameter = (CGGNP)GetProcAddress(hCgDll,"cgGetNamedParameter"); + cgGetError = (CGGE)GetProcAddress(hCgDll,"cgGetError"); + cgGetErrorString = (CGGES)GetProcAddress(hCgDll,"cgGetErrorString"); + cgGetLastListing = (CGGLL)GetProcAddress(hCgDll,"cgGetLastListing"); + cgCreateProgram = (CGCP)GetProcAddress(hCgDll,"cgCreateProgram"); + cgDestroyProgram = (CGDP)GetProcAddress(hCgDll,"cgDestroyProgram"); + //cgD3D9.dll + cgD3D9SetDevice = (CGD3DSD)GetProcAddress(hCgD3D9Dll,"cgD3D9SetDevice"); + cgD3D9BindProgram = (CGD3DBP)GetProcAddress(hCgD3D9Dll,"cgD3D9BindProgram"); + cgD3D9GetLatestVertexProfile = (CGD3DGLVP)GetProcAddress(hCgD3D9Dll,"cgD3D9GetLatestVertexProfile"); + cgD3D9GetLatestPixelProfile = (CGD3DGLPP)GetProcAddress(hCgD3D9Dll,"cgD3D9GetLatestPixelProfile"); + cgD3D9GetOptimalOptions = (CGD3DGOO)GetProcAddress(hCgD3D9Dll,"cgD3D9GetOptimalOptions"); + cgD3D9LoadProgram = (CGD3DLP)GetProcAddress(hCgD3D9Dll,"cgD3D9LoadProgram"); + cgD3D9SetUniformMatrix = (CGD3DSUM)GetProcAddress(hCgD3D9Dll,"cgD3D9SetUniformMatrix"); + cgD3D9SetUniform = (CGD3DSU)GetProcAddress(hCgD3D9Dll,"cgD3D9SetUniform"); + //cggl.dll + cgGLSetStateMatrixParameter = (CGGLSSMP)GetProcAddress(hCgGLDll,"cgGLSetStateMatrixParameter"); + cgGLSetParameter2fv = (CGGLSP2FV)GetProcAddress(hCgGLDll,"cgGLSetParameter2fv"); + cgGLGetLatestProfile = (CGGLGLP)GetProcAddress(hCgGLDll,"cgGLGetLatestProfile"); + cgGLEnableProfile = (CGGLEP)GetProcAddress(hCgGLDll,"cgGLEnableProfile"); + cgGLDisableProfile = (CGGLDP)GetProcAddress(hCgGLDll,"cgGLDisableProfile"); + cgGLSetOptimalOptions = (CGGLSOO)GetProcAddress(hCgGLDll,"cgGLSetOptimalOptions"); + cgGLLoadProgram = (CGGLLP)GetProcAddress(hCgGLDll,"cgGLLoadProgram"); + cgGLBindProgram = (CGGLBP)GetProcAddress(hCgGLDll,"cgGLBindProgram"); + + if( + //cg.dll + !cgCreateContext || + !cgDestroyContext || + !cgGetNamedParameter || + !cgGetError || + !cgGetErrorString || + !cgGetLastListing || + !cgCreateProgram || + !cgDestroyProgram || + //cgD3D9.dll + !cgD3D9SetDevice || + !cgD3D9BindProgram || + !cgD3D9GetLatestVertexProfile || + !cgD3D9GetLatestPixelProfile || + !cgD3D9GetOptimalOptions || + !cgD3D9LoadProgram || + !cgD3D9SetUniformMatrix || + !cgD3D9SetUniform || + //cggl.dll + !cgGLSetStateMatrixParameter || + !cgGLSetParameter2fv || + !cgGLGetLatestProfile || + !cgGLEnableProfile || + !cgGLDisableProfile || + !cgGLSetOptimalOptions || + !cgGLLoadProgram || + !cgGLBindProgram) { + unloadCgLibrary(); + return false; + } + + return true; +} + +void unloadCgLibrary() +{ + if(hCgDll) + FreeLibrary(hCgDll); + if(hCgD3D9Dll) + FreeLibrary(hCgD3D9Dll); + if(hCgGLDll) + FreeLibrary(hCgGLDll); + + hCgDll = hCgD3D9Dll = hCgGLDll = NULL; + + //cg.dll + cgCreateContext = NULL; + cgDestroyContext = NULL; + cgGetNamedParameter = NULL; + cgGetError = NULL; + cgGetErrorString = NULL; + cgGetLastListing = NULL; + cgCreateProgram = NULL; + cgDestroyProgram = NULL; + //cgD3D9.dll + cgD3D9SetDevice = NULL; + cgD3D9BindProgram = NULL; + cgD3D9GetLatestVertexProfile = NULL; + cgD3D9GetLatestPixelProfile = NULL; + cgD3D9GetOptimalOptions = NULL; + cgD3D9LoadProgram = NULL; + cgD3D9SetUniformMatrix = NULL; + cgD3D9SetUniform = NULL; + //cggl.dll + cgGLSetStateMatrixParameter = NULL; + cgGLSetParameter2fv = NULL; + cgGLGetLatestProfile = NULL; + cgGLEnableProfile = NULL; + cgGLDisableProfile = NULL; + cgGLSetOptimalOptions = NULL; + cgGLLoadProgram = NULL; + cgGLBindProgram = NULL; +} diff --git a/win32/cgFunctions.h b/win32/cgFunctions.h new file mode 100644 index 00000000..27b47cdd --- /dev/null +++ b/win32/cgFunctions.h @@ -0,0 +1,72 @@ +#ifndef CGFUNCTIONS_H +#define CGFUNCTIONS_H + +#define CG_EXPLICIT +#define CGD3D9_EXPLICIT +#define CGGL_EXPLICIT + +#include +#include +#include + +//cg.dll +typedef CG_API CGcontext (CGENTRY *CGCC)(void); +extern CGCC cgCreateContext; +typedef CG_API void (CGENTRY *CGDC)(CGcontext context); +extern CGDC cgDestroyContext; +typedef CG_API CGparameter (CGENTRY *CGGNP)(CGprogram program, const char *name); +extern CGGNP cgGetNamedParameter; +typedef CG_API CGerror (CGENTRY *CGGE)(void); +extern CGGE cgGetError; +typedef CG_API const char * (CGENTRY *CGGES)(CGerror error); +extern CGGES cgGetErrorString; +typedef CG_API const char * (CGENTRY *CGGLL)(CGcontext context); +extern CGGLL cgGetLastListing; +typedef CG_API CGprogram (CGENTRY *CGCP)(CGcontext context, CGenum program_type, const char *program, CGprofile profile, const char *entry, const char **args); +extern CGCP cgCreateProgram; +typedef CG_API void (CGENTRY *CGDP)(CGprogram program); +extern CGDP cgDestroyProgram; + +//cgD3D9.dll +typedef CGD3D9DLL_API HRESULT (CGD3D9ENTRY *CGD3DSD)(IDirect3DDevice9 *pDevice); +extern CGD3DSD cgD3D9SetDevice; +typedef CGD3D9DLL_API HRESULT (CGD3D9ENTRY *CGD3DBP)(CGprogram prog); +extern CGD3DBP cgD3D9BindProgram; +typedef CGD3D9DLL_API CGprofile (CGD3D9ENTRY *CGD3DGLVP)(void); +extern CGD3DGLVP cgD3D9GetLatestVertexProfile; +typedef CGD3D9DLL_API CGprofile (CGD3D9ENTRY *CGD3DGLPP)(void); +extern CGD3DGLPP cgD3D9GetLatestPixelProfile; +typedef CGD3D9DLL_API const char ** (CGD3D9ENTRY *CGD3DGOO)(CGprofile profile); +extern CGD3DGOO cgD3D9GetOptimalOptions; +typedef CGD3D9DLL_API HRESULT (CGD3D9ENTRY *CGD3DLP)(CGprogram prog, CGbool paramShadowing, DWORD assemFlags); +extern CGD3DLP cgD3D9LoadProgram; +typedef CGD3D9DLL_API HRESULT (CGD3D9ENTRY *CGD3DSUM)(CGparameter param, const D3DMATRIX *matrix); +extern CGD3DSUM cgD3D9SetUniformMatrix; +typedef CGD3D9DLL_API HRESULT (CGD3D9ENTRY *CGD3DSU)(CGparameter param, const void *floats); +extern CGD3DSU cgD3D9SetUniform; + +//cggl.dll +typedef CGGL_API void (CGGLENTRY *CGGLSSMP)(CGparameter param, CGGLenum matrix, CGGLenum transform); +extern CGGLSSMP cgGLSetStateMatrixParameter; +typedef CGGL_API void (CGGLENTRY *CGGLSP2FV)(CGparameter param, const float *v); +extern CGGLSP2FV cgGLSetParameter2fv; +typedef CGGL_API CGprofile (CGGLENTRY *CGGLGLP)(CGGLenum profile_type); +extern CGGLGLP cgGLGetLatestProfile; +typedef CGGL_API void (CGGLENTRY *CGGLEP)(CGprofile profile); +extern CGGLEP cgGLEnableProfile; +typedef CGGL_API void (CGGLENTRY *CGGLDP)(CGprofile profile); +extern CGGLDP cgGLDisableProfile; +typedef CGGL_API void (CGGLENTRY *CGGLSOO)(CGprofile profile); +extern CGGLSOO cgGLSetOptimalOptions; +typedef CGGL_API void (CGGLENTRY *CGGLLP)(CGprogram program); +extern CGGLLP cgGLLoadProgram; +typedef CGGL_API void (CGGLENTRY *CGGLBP)(CGprogram program); +extern CGGLBP cgGLBindProgram; + + + +//cgfunctions.cpp +bool loadCgFunctions(); +void unloadCgLibrary(); + +#endif diff --git a/win32/snes9xw.vcproj b/win32/snes9xw.vcproj index 0fd8c850..0ba5f785 100644 --- a/win32/snes9xw.vcproj +++ b/win32/snes9xw.vcproj @@ -3201,6 +3201,14 @@ RelativePath=".\CDirectDraw.h" > + + + +