--- /dev/null
+/*
+* Glide64 - Glide video plugin for Nintendo 64 emulators.
+* Copyright (c) 2002 Dave2001
+* Copyright (c) 2003-2009 Sergey 'Gonetz' Lipski
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#define SAVE_CBUFFER
+
+#ifdef _WIN32
+#include <windows.h>
+#include <commctrl.h>
+#else
+#include <stdint.h>
+#include <stdarg.h>
+#include <string.h>
+#include <SDL.h>
+#endif // _WIN32
+#include <stdlib.h>
+#include <stdio.h>
+#include <iostream>
+#include <fstream>
+#include <math.h>
+#include "glide.h"
+#include "g3ext.h"
+#include "main.h"
+#include "m64p.h"
+
+#define OPENGL_CHECK_ERRORS { const GLenum errcode = glGetError(); if (errcode != GL_NO_ERROR) LOG("OpenGL Error code %i in '%s' line %i\n", errcode, __FILE__, __LINE__-1); }
+
+#ifdef VPDEBUG
+#include <IL/il.h>
+#endif
+
+#include "../Glide64/ticks.h" //*SEB*
+
+extern void (*renderCallback)(int);
+
+wrapper_config config = {0, 0, 0, 0};
+int screen_width, screen_height;
+
+/*
+static inline void opt_glCopyTexImage2D( GLenum target,
+ GLint level,
+ GLenum internalFormat,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLint border )
+
+{
+ int w, h, fmt;
+ glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &w);
+ glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &h);
+ glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &fmt);
+ //printf("copyteximage %dx%d fmt %x oldfmt %x\n", width, height, internalFormat, fmt);
+ if (w == (int) width && h == (int) height && fmt == (int) internalFormat) {
+ if (x+width >= screen_width) {
+ width = screen_width - x;
+ //printf("resizing w --> %d\n", width);
+ }
+ if (y+height >= screen_height+viewport_offset) {
+ height = screen_height+viewport_offset - y;
+ //printf("resizing h --> %d\n", height);
+ }
+ glCopyTexSubImage2D(target, level, 0, 0, x, y, width, height);
+ } else {
+ //printf("copyteximage %dx%d fmt %x old %dx%d oldfmt %x\n", width, height, internalFormat, w, h, fmt);
+ // glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height, 0, internalFormat, GL_UNSIGNED_BYTE, 0);
+ // glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &fmt);
+ // printf("--> %dx%d newfmt %x\n", width, height, fmt);
+ glCopyTexImage2D(target, level, internalFormat, x, y, width, height, border);
+ }
+}
+#define glCopyTexImage2D opt_glCopyTexImage2D
+*/
+
+
+#ifdef _WIN32
+PFNGLACTIVETEXTUREARBPROC glActiveTextureARB;
+PFNGLBLENDFUNCSEPARATEEXTPROC glBlendFuncSeparateEXT;
+PFNGLMULTITEXCOORD2FARBPROC glMultiTexCoord2fARB;
+PFNGLFOGCOORDFPROC glFogCoordfEXT;
+
+PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB;
+
+PFNGLBINDFRAMEBUFFEREXTPROC glBindFramebufferEXT;
+PFNGLFRAMEBUFFERTEXTURE2DEXTPROC glFramebufferTexture2DEXT;
+PFNGLGENFRAMEBUFFERSEXTPROC glGenFramebuffersEXT;
+PFNGLBINDRENDERBUFFEREXTPROC glBindRenderbufferEXT = NULL;
+PFNGLDELETERENDERBUFFERSEXTPROC glDeleteRenderbuffersEXT = NULL;
+PFNGLGENRENDERBUFFERSEXTPROC glGenRenderbuffersEXT = NULL;
+PFNGLRENDERBUFFERSTORAGEEXTPROC glRenderbufferStorageEXT = NULL;
+PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glFramebufferRenderbufferEXT = NULL;
+PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC glCheckFramebufferStatusEXT;
+PFNGLDELETEFRAMEBUFFERSEXTPROC glDeleteFramebuffersEXT;
+
+PFNGLCREATESHADEROBJECTARBPROC glCreateShaderObjectARB;
+PFNGLSHADERSOURCEARBPROC glShaderSourceARB;
+PFNGLCOMPILESHADERARBPROC glCompileShaderARB;
+PFNGLCREATEPROGRAMOBJECTARBPROC glCreateProgramObjectARB;
+PFNGLATTACHOBJECTARBPROC glAttachObjectARB;
+PFNGLLINKPROGRAMARBPROC glLinkProgramARB;
+PFNGLUSEPROGRAMOBJECTARBPROC glUseProgramObjectARB;
+PFNGLGETUNIFORMLOCATIONARBPROC glGetUniformLocationARB;
+PFNGLUNIFORM1IARBPROC glUniform1iARB;
+PFNGLUNIFORM4IARBPROC glUniform4iARB;
+PFNGLUNIFORM4FARBPROC glUniform4fARB;
+PFNGLUNIFORM1FARBPROC glUniform1fARB;
+PFNGLDELETEOBJECTARBPROC glDeleteObjectARB;
+PFNGLGETINFOLOGARBPROC glGetInfoLogARB;
+PFNGLGETOBJECTPARAMETERIVARBPROC glGetObjectParameterivARB;
+PFNGLSECONDARYCOLOR3FPROC glSecondaryColor3f;
+
+// FXT1,DXT1,DXT5 support - Hiroshi Morii <koolsmoky(at)users.sourceforge.net>
+// NOTE: Glide64 + GlideHQ use the following formats
+// GL_COMPRESSED_RGB_S3TC_DXT1_EXT
+// GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
+// GL_COMPRESSED_RGB_FXT1_3DFX
+// GL_COMPRESSED_RGBA_FXT1_3DFX
+PFNGLCOMPRESSEDTEXIMAGE2DPROC glCompressedTexImage2DARB;
+#endif // _WIN32
+
+
+
+typedef struct
+{
+ unsigned int address;
+ int width;
+ int height;
+ int fb_width;
+ int fb_height;
+ unsigned int fbid;
+ unsigned int zbid;
+ unsigned int texid;
+ int buff_clear;
+} fb;
+
+int nbTextureUnits;
+int nbAuxBuffers, current_buffer;
+int width, widtho, heighto, height;
+int saved_width, saved_height;
+int blend_func_separate_support;
+int npot_support;
+int fog_coord_support;
+int render_to_texture = 0;
+int texture_unit;
+int use_fbo;
+int buffer_cleared;
+// ZIGGY
+// to allocate a new static texture name, take the value (free_texture++)
+int free_texture;
+int default_texture; // the infamous "32*1024*1024" is now configurable
+int current_texture;
+int depth_texture, color_texture;
+int glsl_support = 1;
+int viewport_width, viewport_height, viewport_offset = 0, nvidia_viewport_hack = 0;
+int save_w, save_h;
+int lfb_color_fmt;
+float invtex[2];
+//Gonetz
+int UMAmode = 0; //support for VSA-100 UMA mode;
+
+#ifdef _WIN32
+static HDC hDC = NULL;
+static HGLRC hGLRC = NULL;
+static HWND hToolBar = NULL;
+static HWND hwnd_win = NULL;
+static unsigned long windowedExStyle, windowedStyle;
+#endif // _WIN32
+static unsigned long fullscreen;
+#ifdef _WIN32
+static RECT windowedRect;
+static HMENU windowedMenu;
+#endif // _WIN32
+
+static int savedWidtho, savedHeighto;
+static int savedWidth, savedHeight;
+unsigned int pBufferAddress;
+static int pBufferFmt;
+static int pBufferWidth, pBufferHeight;
+static fb fbs[100];
+static int nb_fb = 0;
+static unsigned int curBufferAddr = 0;
+
+struct TMU_USAGE { int min, max; } tmu_usage[2] = { {0xfffffff, 0}, {0xfffffff, 0} };
+
+struct texbuf_t {
+ FxU32 start, end;
+ int fmt;
+};
+#define NB_TEXBUFS 128 // MUST be a power of two
+static texbuf_t texbufs[NB_TEXBUFS];
+static int texbuf_i;
+
+unsigned short frameBuffer[2048*2048];
+unsigned short depthBuffer[2048*2048];
+
+//#define VOODOO1
+
+void display_warning(const char *text, ...)
+{
+ static int first_message = 100;
+ if (first_message)
+ {
+ char buf[4096];
+
+ va_list ap;
+
+ va_start(ap, text);
+ vsprintf(buf, text, ap);
+ va_end(ap);
+ first_message--;
+ LOGINFO(buf);
+ }
+}
+
+#ifdef _WIN32
+void display_error()
+{
+ LPVOID lpMsgBuf;
+ if (!FormatMessage(
+ FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL,
+ GetLastError(),
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
+ (LPTSTR) &lpMsgBuf,
+ 0,
+ NULL ))
+ {
+ // Handle the error.
+ return;
+ }
+ // Process any inserts in lpMsgBuf.
+ // ...
+ // Display the string.
+ MessageBox( NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION );
+
+ // Free the buffer.
+ LocalFree( lpMsgBuf );
+}
+#endif // _WIN32
+
+#ifdef LOGGING
+char out_buf[256];
+bool log_open = false;
+std::ofstream log_file;
+
+void OPEN_LOG()
+{
+ if (!log_open)
+ {
+ log_file.open ("wrapper_log.txt", std::ios_base::out|std::ios_base::app);
+ log_open = true;
+ }
+}
+
+void CLOSE_LOG()
+{
+ if (log_open)
+ {
+ log_file.close();
+ log_open = false;
+ }
+}
+
+void LOG(const char *text, ...)
+{
+#ifdef VPDEBUG
+ if (!dumping) return;
+#endif
+ if (!log_open)
+ return;
+ va_list ap;
+ va_start(ap, text);
+ vsprintf(out_buf, text, ap);
+ log_file << out_buf;
+ log_file.flush();
+ va_end(ap);
+}
+
+class LogManager {
+public:
+ LogManager() {
+ OPEN_LOG();
+ }
+ ~LogManager() {
+ CLOSE_LOG();
+ }
+};
+
+LogManager logManager;
+
+#else // LOGGING
+#define OPEN_LOG()
+#define CLOSE_LOG()
+//#define LOG
+#endif // LOGGING
+
+FX_ENTRY void FX_CALL
+grSstOrigin(GrOriginLocation_t origin)
+{
+ LOG("grSstOrigin(%d)\r\n", origin);
+ if (origin != GR_ORIGIN_UPPER_LEFT)
+ display_warning("grSstOrigin : %x", origin);
+}
+
+FX_ENTRY void FX_CALL
+grClipWindow( FxU32 minx, FxU32 miny, FxU32 maxx, FxU32 maxy )
+{
+ LOG("grClipWindow(%d,%d,%d,%d)\r\n", minx, miny, maxx, maxy);
+
+ if (use_fbo && render_to_texture) {
+ if (int(minx) < 0) minx = 0;
+ if (int(miny) < 0) miny = 0;
+ if (maxx < minx) maxx = minx;
+ if (maxy < miny) maxy = miny;
+ glScissor(minx, miny, maxx - minx, maxy - miny);
+ glEnable(GL_SCISSOR_TEST);
+ return;
+ }
+
+ if (!use_fbo) {
+ int th = height;
+ if (th > screen_height)
+ th = screen_height;
+ maxy = th - maxy;
+ miny = th - miny;
+ FxU32 tmp = maxy; maxy = miny; miny = tmp;
+ if (maxx > (FxU32) width) maxx = width;
+ if (maxy > (FxU32) height) maxy = height;
+ if (int(minx) < 0) minx = 0;
+ if (int(miny) < 0) miny = 0;
+ if (maxx < minx) maxx = minx;
+ if (maxy < miny) maxy = miny;
+ glScissor(minx, miny+viewport_offset, maxx - minx, maxy - miny);
+ //printf("gl scissor %d %d %d %d\n", minx, miny, maxx, maxy);
+ } else {
+ glScissor(minx, (viewport_offset)+height-maxy, maxx - minx, maxy - miny);
+ }
+ glEnable(GL_SCISSOR_TEST);
+}
+
+FX_ENTRY void FX_CALL
+grColorMask( FxBool rgb, FxBool a )
+{
+ LOG("grColorMask(%d, %d)\r\n", rgb, a);
+ glColorMask(rgb, rgb, rgb, a);
+}
+
+FX_ENTRY void FX_CALL
+grGlideInit( void )
+{
+ LOG("grGlideInit()\r\n");
+}
+
+FX_ENTRY void FX_CALL
+grSstSelect( int which_sst )
+{
+ LOG("grSstSelect(%d)\r\n", which_sst);
+}
+
+int isExtensionSupported(const char *extension)
+{
+ return 0;
+ const GLubyte *extensions = NULL;
+ const GLubyte *start;
+ GLubyte *where, *terminator;
+
+ where = (GLubyte *)strchr(extension, ' ');
+ if (where || *extension == '\0')
+ return 0;
+
+ extensions = glGetString(GL_EXTENSIONS);
+
+ start = extensions;
+ for (;;)
+ {
+ where = (GLubyte *) strstr((const char *) start, extension);
+ if (!where)
+ break;
+
+ terminator = where + strlen(extension);
+ if (where == start || *(where - 1) == ' ')
+ if (*terminator == ' ' || *terminator == '\0')
+ return 1;
+
+ start = terminator;
+ }
+
+ return 0;
+}
+
+#ifdef _WIN32
+int isWglExtensionSupported(const char *extension)
+{
+ const GLubyte *extensions = NULL;
+ const GLubyte *start;
+ GLubyte *where, *terminator;
+
+ where = (GLubyte *)strchr(extension, ' ');
+ if (where || *extension == '\0')
+ return 0;
+
+ extensions = (GLubyte*)wglGetExtensionsStringARB(wglGetCurrentDC());
+
+ start = extensions;
+ for (;;)
+ {
+ where = (GLubyte *) strstr((const char *) start, extension);
+ if (!where)
+ break;
+
+ terminator = where + strlen(extension);
+ if (where == start || *(where - 1) == ' ')
+ if (*terminator == ' ' || *terminator == '\0')
+ return 1;
+
+ start = terminator;
+ }
+
+ return 0;
+}
+#endif // _WIN32
+
+#define GrPixelFormat_t int
+
+FX_ENTRY GrContext_t FX_CALL
+grSstWinOpenExt(
+ HWND hWnd,
+ GrScreenResolution_t screen_resolution,
+ GrScreenRefresh_t refresh_rate,
+ GrColorFormat_t color_format,
+ GrOriginLocation_t origin_location,
+ GrPixelFormat_t pixelformat,
+ int nColBuffers,
+ int nAuxBuffers)
+{
+ LOG("grSstWinOpenExt(%d, %d, %d, %d, %d, %d %d)\r\n", hWnd, screen_resolution, refresh_rate, color_format, origin_location, nColBuffers, nAuxBuffers);
+ return grSstWinOpen(hWnd, screen_resolution, refresh_rate, color_format,
+ origin_location, nColBuffers, nAuxBuffers);
+}
+
+#ifdef WIN32
+# include <fcntl.h>
+# ifndef ATTACH_PARENT_PROCESS
+# define ATTACH_PARENT_PROCESS ((FxU32)-1)
+# endif
+#endif
+
+FX_ENTRY GrContext_t FX_CALL
+grSstWinOpen(
+ HWND hWnd,
+ GrScreenResolution_t screen_resolution,
+ GrScreenRefresh_t refresh_rate,
+ GrColorFormat_t color_format,
+ GrOriginLocation_t origin_location,
+ int nColBuffers,
+ int nAuxBuffers)
+{
+ static int show_warning = 1;
+
+ // ZIGGY
+ // allocate static texture names
+ // the initial value should be big enough to support the maximal resolution
+ free_texture = 32*2048*2048;
+ default_texture = free_texture++;
+ color_texture = free_texture++;
+ depth_texture = free_texture++;
+
+ LOG("grSstWinOpen(%08lx, %d, %d, %d, %d, %d %d)\r\n", hWnd, screen_resolution&~0x80000000, refresh_rate, color_format, origin_location, nColBuffers, nAuxBuffers);
+
+#ifdef _WIN32
+ if ((HWND)hWnd == NULL) hWnd = GetActiveWindow();
+ hwnd_win = (HWND)hWnd;
+#endif // _WIN32
+ width = height = 0;
+
+ m64p_handle video_general_section;
+ printf("&ConfigOpenSection is %p\n", &ConfigOpenSection);
+ if (ConfigOpenSection("Video-General", &video_general_section) != M64ERR_SUCCESS)
+ {
+ printf("Could not open video settings");
+ return false;
+ }
+ width = ConfigGetParamInt(video_general_section, "ScreenWidth");
+ height = ConfigGetParamInt(video_general_section, "ScreenHeight");
+ fullscreen = ConfigGetParamBool(video_general_section, "Fullscreen");
+ int vsync = ConfigGetParamBool(video_general_section, "VerticalSync");
+ //viewport_offset = ((screen_resolution>>2) > 20) ? screen_resolution >> 2 : 20;
+ // ZIGGY viewport_offset is WIN32 specific, with SDL just set it to zero
+ viewport_offset = 0; //-10 //-20;
+
+ // ZIGGY not sure, but it might be better to let the system choose
+ CoreVideo_GL_SetAttribute(M64P_GL_DOUBLEBUFFER, 1);
+ CoreVideo_GL_SetAttribute(M64P_GL_SWAP_CONTROL, vsync);
+ CoreVideo_GL_SetAttribute(M64P_GL_BUFFER_SIZE, 16);
+ // SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE, 32);
+ // SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
+ // SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
+ // SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
+ // SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
+ CoreVideo_GL_SetAttribute(M64P_GL_DEPTH_SIZE, 16);
+
+ printf("(II) Setting video mode %dx%d...\n", width, height);
+ if(CoreVideo_SetVideoMode(width, height, 0, fullscreen ? M64VIDEO_FULLSCREEN : M64VIDEO_WINDOWED, (m64p_video_flags) 0) != M64ERR_SUCCESS)
+ {
+ printf("(EE) Error setting videomode %dx%d\n", width, height);
+ return false;
+ }
+
+ char caption[500];
+# ifdef _DEBUG
+ sprintf(caption, "Glide64mk2 debug");
+# else // _DEBUG
+ sprintf(caption, "Glide64mk2");
+# endif // _DEBUG
+ CoreVideo_SetCaption(caption);
+
+ glViewport(0, viewport_offset, width, height);
+ lfb_color_fmt = color_format;
+ if (origin_location != GR_ORIGIN_UPPER_LEFT) display_warning("origin must be in upper left corner");
+ if (nColBuffers != 2) display_warning("number of color buffer is not 2");
+ if (nAuxBuffers != 1) display_warning("number of auxiliary buffer is not 1");
+
+ if (isExtensionSupported("GL_ARB_texture_env_combine") == 0 &&
+ isExtensionSupported("GL_EXT_texture_env_combine") == 0 &&
+ show_warning)
+ display_warning("Your video card doesn't support GL_ARB_texture_env_combine extension");
+ if (isExtensionSupported("GL_ARB_multitexture") == 0 && show_warning)
+ display_warning("Your video card doesn't support GL_ARB_multitexture extension");
+ if (isExtensionSupported("GL_ARB_texture_mirrored_repeat") == 0 && show_warning)
+ display_warning("Your video card doesn't support GL_ARB_texture_mirrored_repeat extension");
+ show_warning = 0;
+
+#ifdef _WIN32
+ glActiveTextureARB = (PFNGLACTIVETEXTUREARBPROC)wglGetProcAddress("glActiveTextureARB");
+ glMultiTexCoord2fARB = (PFNGLMULTITEXCOORD2FARBPROC)wglGetProcAddress("glMultiTexCoord2fARB");
+#endif // _WIN32
+
+ nbTextureUnits = 4;
+ //glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &nbTextureUnits);
+ if (nbTextureUnits == 1) display_warning("You need a video card that has at least 2 texture units");
+
+ nbAuxBuffers = 4;
+ //glGetIntegerv(GL_AUX_BUFFERS, &nbAuxBuffers);
+ if (nbAuxBuffers > 0)
+ printf("Congratulations, you have %d auxilliary buffers, we'll use them wisely !\n", nbAuxBuffers);
+#ifdef VOODOO1
+ nbTextureUnits = 2;
+#endif
+
+ blend_func_separate_support = 1;
+ packed_pixels_support = 0;
+/*
+ if (isExtensionSupported("GL_EXT_blend_func_separate") == 0)
+ blend_func_separate_support = 0;
+ else
+ blend_func_separate_support = 1;
+
+ if (isExtensionSupported("GL_EXT_packed_pixels") == 0)
+ packed_pixels_support = 0;
+ else {
+ printf("packed pixels extension used\n");
+ packed_pixels_support = 1;
+ }
+*/
+
+ if (isExtensionSupported("GL_ARB_texture_non_power_of_two") == 0)
+ npot_support = 0;
+ else {
+ printf("NPOT extension used\n");
+ npot_support = 1;
+ }
+
+#ifdef _WIN32
+ glBlendFuncSeparateEXT = (PFNGLBLENDFUNCSEPARATEEXTPROC)wglGetProcAddress("glBlendFuncSeparateEXT");
+#endif // _WIN32
+
+ if (isExtensionSupported("GL_EXT_fog_coord") == 0)
+ fog_coord_support = 0;
+ else
+ fog_coord_support = 1;
+
+#ifdef _WIN32
+ glFogCoordfEXT = (PFNGLFOGCOORDFPROC)wglGetProcAddress("glFogCoordfEXT");
+#endif // _WIN32
+
+#ifdef _WIN32
+ wglGetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC)wglGetProcAddress("wglGetExtensionsStringARB");
+#endif // _WIN32
+
+#ifdef _WIN32
+ glBindFramebufferEXT = (PFNGLBINDFRAMEBUFFEREXTPROC)wglGetProcAddress("glBindFramebufferEXT");
+ glFramebufferTexture2DEXT = (PFNGLFRAMEBUFFERTEXTURE2DEXTPROC)wglGetProcAddress("glFramebufferTexture2DEXT");
+ glGenFramebuffersEXT = (PFNGLGENFRAMEBUFFERSEXTPROC)wglGetProcAddress("glGenFramebuffersEXT");
+ glCheckFramebufferStatusEXT = (PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC)wglGetProcAddress("glCheckFramebufferStatusEXT");
+ glDeleteFramebuffersEXT = (PFNGLDELETEFRAMEBUFFERSEXTPROC)wglGetProcAddress("glDeleteFramebuffersEXT");
+
+ glBindRenderbufferEXT = (PFNGLBINDRENDERBUFFEREXTPROC)wglGetProcAddress("glBindRenderbufferEXT");
+ glDeleteRenderbuffersEXT = (PFNGLDELETERENDERBUFFERSEXTPROC)wglGetProcAddress("glDeleteRenderbuffersEXT");
+ glGenRenderbuffersEXT = (PFNGLGENRENDERBUFFERSEXTPROC)wglGetProcAddress("glGenRenderbuffersEXT");
+ glRenderbufferStorageEXT = (PFNGLRENDERBUFFERSTORAGEEXTPROC)wglGetProcAddress("glRenderbufferStorageEXT");
+ glFramebufferRenderbufferEXT = (PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC)wglGetProcAddress("glFramebufferRenderbufferEXT");
+ use_fbo = config.fbo && (glFramebufferRenderbufferEXT != NULL);
+#else
+ use_fbo = config.fbo;
+#endif // _WIN32
+
+ LOGINFO("use_fbo %d\n", use_fbo);
+
+ if (isExtensionSupported("GL_ARB_shading_language_100") &&
+ isExtensionSupported("GL_ARB_shader_objects") &&
+ isExtensionSupported("GL_ARB_fragment_shader") &&
+ isExtensionSupported("GL_ARB_vertex_shader"))
+ {
+
+#ifdef _WIN32
+ glCreateShaderObjectARB = (PFNGLCREATESHADEROBJECTARBPROC)wglGetProcAddress("glCreateShaderObjectARB");
+ glShaderSourceARB = (PFNGLSHADERSOURCEARBPROC)wglGetProcAddress("glShaderSourceARB");
+ glCompileShaderARB = (PFNGLCOMPILESHADERARBPROC)wglGetProcAddress("glCompileShaderARB");
+ glCreateProgramObjectARB = (PFNGLCREATEPROGRAMOBJECTARBPROC)wglGetProcAddress("glCreateProgramObjectARB");
+ glAttachObjectARB = (PFNGLATTACHOBJECTARBPROC)wglGetProcAddress("glAttachObjectARB");
+ glLinkProgramARB = (PFNGLLINKPROGRAMARBPROC)wglGetProcAddress("glLinkProgramARB");
+ glUseProgramObjectARB = (PFNGLUSEPROGRAMOBJECTARBPROC)wglGetProcAddress("glUseProgramObjectARB");
+ glGetUniformLocationARB = (PFNGLGETUNIFORMLOCATIONARBPROC)wglGetProcAddress("glGetUniformLocationARB");
+ glUniform1iARB = (PFNGLUNIFORM1IARBPROC)wglGetProcAddress("glUniform1iARB");
+ glUniform4iARB = (PFNGLUNIFORM4IARBPROC)wglGetProcAddress("glUniform4iARB");
+ glUniform4fARB = (PFNGLUNIFORM4FARBPROC)wglGetProcAddress("glUniform4fARB");
+ glUniform1fARB = (PFNGLUNIFORM1FARBPROC)wglGetProcAddress("glUniform1fARB");
+ glDeleteObjectARB = (PFNGLDELETEOBJECTARBPROC)wglGetProcAddress("glDeleteObjectARB");
+ glGetInfoLogARB = (PFNGLGETINFOLOGARBPROC)wglGetProcAddress("glGetInfoLogARB");
+ glGetObjectParameterivARB = (PFNGLGETOBJECTPARAMETERIVARBPROC)wglGetProcAddress("glGetObjectParameterivARB");
+
+ glSecondaryColor3f = (PFNGLSECONDARYCOLOR3FPROC)wglGetProcAddress("glSecondaryColor3f");
+#endif // _WIN32
+ }
+
+ if (isExtensionSupported("GL_EXT_texture_compression_s3tc") == 0 && show_warning)
+ display_warning("Your video card doesn't support GL_EXT_texture_compression_s3tc extension");
+ if (isExtensionSupported("GL_3DFX_texture_compression_FXT1") == 0 && show_warning)
+ display_warning("Your video card doesn't support GL_3DFX_texture_compression_FXT1 extension");
+
+#ifdef _WIN32
+ glCompressedTexImage2DARB = (PFNGLCOMPRESSEDTEXIMAGE2DPROC)wglGetProcAddress("glCompressedTexImage2DARB");
+#endif
+/*SEB*/
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+ glPixelStorei(GL_PACK_ALIGNMENT, 1);
+
+
+#ifdef _WIN32
+ glViewport(0, viewport_offset, width, height);
+ viewport_width = width;
+ viewport_height = height;
+ nvidia_viewport_hack = 1;
+#else
+ glViewport(0, viewport_offset, width, height);
+ viewport_width = width;
+ viewport_height = height;
+#endif // _WIN32
+
+ // void do_benchmarks();
+ // do_benchmarks();
+
+ // VP try to resolve z precision issues
+// glMatrixMode(GL_MODELVIEW);
+// glLoadIdentity();
+// glTranslatef(0, 0, 1-zscale);
+// glScalef(1, 1, zscale);
+
+ widtho = width/2;
+ heighto = height/2;
+
+ pBufferWidth = pBufferHeight = -1;
+
+ current_buffer = GL_BACK;
+
+ texture_unit = GL_TEXTURE0;
+
+ {
+ int i;
+ for (i=0; i<NB_TEXBUFS; i++)
+ texbufs[i].start = texbufs[i].end = 0xffffffff;
+ }
+
+ if (!use_fbo && nbAuxBuffers == 0) {
+ // create the framebuffer saving texture
+ int w = width, h = height;
+ glBindTexture(GL_TEXTURE_2D, color_texture);
+ if (!npot_support) {
+ w = h = 1;
+ while (w<width) w*=2;
+ while (h<height) h*=2;
+ }
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
+ glBindTexture(GL_TEXTURE_2D, 0);
+ save_w = save_h = 0;
+ }
+
+ void FindBestDepthBias();
+ FindBestDepthBias();
+
+ init_geometry();
+ init_textures();
+ init_combiner();
+
+/*
+ // Aniso filter check
+ if (config.anisofilter > 0 )
+ glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &largest_supported_anisotropy);
+
+ // ATI hack - certain texture formats are slow on ATI?
+ // Hmm, perhaps the internal format need to be specified explicitly...
+ {
+ GLint ifmt;
+ glTexImage2D(GL_PROXY_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, NULL);
+ glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &ifmt);
+ if (ifmt != GL_RGB5_A1) {
+ display_warning("ATI SUCKS %x\n", ifmt);
+ ati_sucks = 1;
+ } else
+ ati_sucks = 0;
+ }
+*/
+
+ return 1;
+}
+
+FX_ENTRY void FX_CALL
+grGlideShutdown( void )
+{
+ LOG("grGlideShutdown\r\n");
+}
+
+FX_ENTRY FxBool FX_CALL
+grSstWinClose( GrContext_t context )
+{
+ int i, clear_texbuff = use_fbo;
+ LOG("grSstWinClose(%d)\r\n", context);
+
+ for (i=0; i<2; i++) {
+ tmu_usage[i].min = 0xfffffff;
+ tmu_usage[i].max = 0;
+ invtex[i] = 0;
+ }
+
+ free_combiners();
+#ifndef WIN32
+ try // I don't know why, but opengl can be killed before this function call when emulator is closed (Gonetz).
+ // ZIGGY : I found the problem : it is a function pointer, when the extension isn't supported , it is then zero, so just need to check the pointer prior to do the call.
+ {
+ if (use_fbo)
+ glBindFramebuffer( GL_FRAMEBUFFER, 0 );
+ }
+ catch (...)
+ {
+ clear_texbuff = 0;
+ }
+
+ if (clear_texbuff)
+ {
+ for (i=0; i<nb_fb; i++)
+ {
+ glDeleteTextures( 1, &(fbs[i].texid) );
+ glDeleteFramebuffers( 1, &(fbs[i].fbid) );
+ glDeleteRenderbuffers( 1, &(fbs[i].zbid) );
+ }
+ }
+#endif
+ nb_fb = 0;
+
+ free_textures();
+#ifndef WIN32
+ // ZIGGY for some reasons, Pj64 doesn't like remove_tex on exit
+ remove_tex(0, 0xfffffff);
+#endif
+
+ //*/
+#ifdef _WIN32
+ if (hGLRC)
+ {
+ wglMakeCurrent(hDC,NULL);
+ wglDeleteContext(hGLRC);
+ hGLRC = NULL;
+ }
+ if (fullscreen)
+ {
+ ChangeDisplaySettings(NULL, 0);
+ SetWindowPos(hwnd_win, NULL,
+ windowedRect.left, windowedRect.top,
+ 0, 0,
+ SWP_NOZORDER | SWP_NOSIZE);
+ SetWindowLong(hwnd_win, GWL_STYLE, windowedStyle);
+ SetWindowLong(hwnd_win, GWL_EXSTYLE, windowedExStyle);
+ if (windowedMenu) SetMenu(hwnd_win, windowedMenu);
+ fullscreen = 0;
+ }
+#else
+ CoreVideo_Quit();
+ //SDL_QuitSubSystem(SDL_INIT_VIDEO);
+ //sleep(2);
+#endif
+ return FXTRUE;
+}
+
+FX_ENTRY void FX_CALL grTextureBufferExt( GrChipID_t tmu,
+ FxU32 startAddress,
+ GrLOD_t lodmin,
+ GrLOD_t lodmax,
+ GrAspectRatio_t aspect,
+ GrTextureFormat_t fmt,
+ FxU32 evenOdd)
+{
+ int i;
+ static int fbs_init = 0;
+
+ LOG("grTextureBufferExt(%d, %d, %d, %d %d, %d, %d)\r\n", tmu, startAddress, lodmin, lodmax, aspect, fmt, evenOdd);
+ if (lodmin != lodmax) display_warning("grTextureBufferExt : loading more than one LOD");
+ if (!use_fbo) {
+
+ if (!render_to_texture) { //initialization
+ return;
+ }
+
+ render_to_texture = 2;
+
+ if (aspect < 0)
+ {
+ pBufferHeight = 1 << lodmin;
+ pBufferWidth = pBufferHeight >> -aspect;
+ }
+ else
+ {
+ pBufferWidth = 1 << lodmin;
+ pBufferHeight = pBufferWidth >> aspect;
+ }
+
+ if (curBufferAddr && startAddress+1 != curBufferAddr)
+ updateTexture();
+#ifdef SAVE_CBUFFER
+ //printf("saving %dx%d\n", pBufferWidth, pBufferHeight);
+ // save color buffer
+ if (nbAuxBuffers > 0) {
+ //glDrawBuffer(GL_AUX0);
+ //current_buffer = GL_AUX0;
+ } else {
+ int tw, th;
+ if (pBufferWidth < screen_width)
+ tw = pBufferWidth;
+ else
+ tw = screen_width;
+ if (pBufferHeight < screen_height)
+ th = pBufferHeight;
+ else
+ th = screen_height;
+ //glReadBuffer(GL_BACK);
+ glActiveTexture(texture_unit);
+ glBindTexture(GL_TEXTURE_2D, color_texture);
+ // save incrementally the framebuffer
+ if (save_w) {
+ if (tw > save_w && th > save_h) {
+ glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, save_h,
+ 0, viewport_offset+save_h, tw, th-save_h);
+ glCopyTexSubImage2D(GL_TEXTURE_2D, 0, save_w, 0,
+ save_w, viewport_offset, tw-save_w, save_h);
+ save_w = tw;
+ save_h = th;
+ } else if (tw > save_w) {
+ glCopyTexSubImage2D(GL_TEXTURE_2D, 0, save_w, 0,
+ save_w, viewport_offset, tw-save_w, save_h);
+ save_w = tw;
+ } else if (th > save_h) {
+ glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, save_h,
+ 0, viewport_offset+save_h, save_w, th-save_h);
+ save_h = th;
+ }
+ } else {
+ glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0,
+ 0, viewport_offset, tw, th);
+ save_w = tw;
+ save_h = th;
+ }
+ glBindTexture(GL_TEXTURE_2D, default_texture);
+ }
+#endif
+
+ if (startAddress+1 != curBufferAddr ||
+ (curBufferAddr == 0L && nbAuxBuffers == 0))
+ buffer_cleared = 0;
+
+ curBufferAddr = pBufferAddress = startAddress+1;
+ pBufferFmt = fmt;
+
+ int rtmu = startAddress < grTexMinAddress(GR_TMU1)? 0 : 1;
+ int size = pBufferWidth*pBufferHeight*2; //grTexFormatSize(fmt);
+ if ((unsigned int) tmu_usage[rtmu].min > pBufferAddress)
+ tmu_usage[rtmu].min = pBufferAddress;
+ if ((unsigned int) tmu_usage[rtmu].max < pBufferAddress+size)
+ tmu_usage[rtmu].max = pBufferAddress+size;
+ //printf("tmu %d usage now %gMb - %gMb\n",
+ // rtmu, tmu_usage[rtmu].min/1024.0f, tmu_usage[rtmu].max/1024.0f);
+
+
+ width = pBufferWidth;
+ height = pBufferHeight;
+
+ widtho = width/2;
+ heighto = height/2;
+
+ // this could be improved, but might be enough as long as the set of
+ // texture buffer addresses stay small
+ for (i=(texbuf_i-1)&(NB_TEXBUFS-1) ; i!=texbuf_i; i=(i-1)&(NB_TEXBUFS-1))
+ if (texbufs[i].start == pBufferAddress)
+ break;
+ texbufs[i].start = pBufferAddress;
+ texbufs[i].end = pBufferAddress + size;
+ texbufs[i].fmt = fmt;
+ if (i == texbuf_i)
+ texbuf_i = (texbuf_i+1)&(NB_TEXBUFS-1);
+ //printf("texbuf %x fmt %x\n", pBufferAddress, fmt);
+
+ // ZIGGY it speeds things up to not delete the buffers
+ // a better thing would be to delete them *sometimes*
+ // remove_tex(pBufferAddress+1, pBufferAddress + size);
+ add_tex(pBufferAddress);
+
+ //printf("viewport %dx%d\n", width, height);
+ if (height > screen_height) {
+ glViewport( 0, viewport_offset + screen_height - height, width, height);
+ } else
+ glViewport( 0, viewport_offset, width, height);
+
+ glScissor(0, viewport_offset, width, height);
+
+
+ } else {
+ if (!render_to_texture) //initialization
+ {
+ if(!fbs_init)
+ {
+ for(i=0; i<100; i++) fbs[i].address = 0;
+ fbs_init = 1;
+ nb_fb = 0;
+ }
+ return; //no need to allocate FBO if render buffer is not texture buffer
+ }
+
+ render_to_texture = 2;
+
+ if (aspect < 0)
+ {
+ pBufferHeight = 1 << lodmin;
+ pBufferWidth = pBufferHeight >> -aspect;
+ }
+ else
+ {
+ pBufferWidth = 1 << lodmin;
+ pBufferHeight = pBufferWidth >> aspect;
+ }
+ pBufferAddress = startAddress+1;
+
+ width = pBufferWidth;
+ height = pBufferHeight;
+
+ widtho = width/2;
+ heighto = height/2;
+
+ for (i=0; i<nb_fb; i++)
+ {
+ if (fbs[i].address == pBufferAddress)
+ {
+// if (fbs[i].width == width && fbs[i].height == height) //select already allocated FBO
+ if (fbs[i].width >= width && fbs[i].height >= height) //select already allocated FBO, or large enough
+ {
+//unsigned int tticks = ticksGetTicks();
+ glBindFramebuffer( GL_FRAMEBUFFER, 0 );
+ glBindFramebuffer( GL_FRAMEBUFFER, fbs[i].fbid );
+ glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbs[i].texid, 0 );
+ glBindRenderbuffer( GL_RENDERBUFFER, fbs[i].zbid );
+ glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbs[i].zbid );
+ glViewport( 0, 0, width, height);
+ glScissor( 0, 0, width, height);
+ fbs[i].fb_width=width;
+ fbs[i].fb_height=height;
+ if (fbs[i].buff_clear)
+ {
+ glDepthMask(1);
+ glClear( GL_DEPTH_BUFFER_BIT ); //clear z-buffer only. we may need content, stored in the frame buffer
+ fbs[i].buff_clear = 0;
+ }
+ CHECK_FRAMEBUFFER_STATUS();
+ curBufferAddr = pBufferAddress;
+//printf("select existing fbo (%u ms)\n", ticksGetTicks()-tticks);
+ return;
+ }
+ else //create new FBO at the same address, delete old one
+ {
+//unsigned int tticks = ticksGetTicks();
+ glDeleteFramebuffers( 1, &(fbs[i].fbid) );
+ glDeleteRenderbuffers( 1, &(fbs[i].zbid) );
+ if (nb_fb > 1)
+ memmove(&(fbs[i]), &(fbs[i+1]), sizeof(fb)*(nb_fb-i));
+ nb_fb--;
+//printf("delete existing fbo (%u ms)\n", ticksGetTicks()-tticks);
+ break;
+ }
+ }
+ }
+//unsigned int tticks = ticksGetTicks();
+ remove_tex(pBufferAddress, pBufferAddress + width*height*2/*grTexFormatSize(fmt)*/);
+//printf("delete texture (%u ms)\n", ticksGetTicks()-tticks);
+ //create new FBO
+ glGenFramebuffers( 1, &(fbs[nb_fb].fbid) );
+ glGenRenderbuffers( 1, &(fbs[nb_fb].zbid) );
+ glBindRenderbuffer( GL_RENDERBUFFER, fbs[nb_fb].zbid );
+ glRenderbufferStorage( GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height);
+ fbs[nb_fb].address = pBufferAddress;
+ fbs[nb_fb].width = width;
+ fbs[nb_fb].height = height;
+ fbs[nb_fb].fb_width = width;
+ fbs[nb_fb].fb_height = height;
+ fbs[nb_fb].texid = pBufferAddress;
+ fbs[nb_fb].buff_clear = 0;
+ add_tex(fbs[nb_fb].texid);
+ glBindTexture(GL_TEXTURE_2D, fbs[nb_fb].texid);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0,
+ GL_RGB, GL_UNSIGNED_BYTE, NULL);
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+
+ glBindFramebuffer( GL_FRAMEBUFFER, fbs[nb_fb].fbid);
+ glFramebufferTexture2D(GL_FRAMEBUFFER,
+ GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbs[nb_fb].texid, 0);
+ glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbs[nb_fb].zbid );
+ glViewport(0,0,width,height);
+ glScissor(0,0,width,height);
+ glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
+ glDepthMask(1);
+ glClear( GL_DEPTH_BUFFER_BIT );
+ CHECK_FRAMEBUFFER_STATUS();
+ curBufferAddr = pBufferAddress;
+ nb_fb++;
+//printf("create new fbo=fb[%i] (%u ms)\n", nb_fb-1, ticksGetTicks()-tticks);
+ }
+}
+
+int CheckTextureBufferFormat(GrChipID_t tmu, FxU32 startAddress, GrTexInfo *info )
+{
+ int found, i;
+ if (!use_fbo) {
+ for (found=i=0; i<2; i++)
+ if ((FxU32) tmu_usage[i].min <= startAddress && (FxU32) tmu_usage[i].max > startAddress) {
+ //printf("tmu %d == framebuffer %x\n", tmu, startAddress);
+ found = 1;
+ break;
+ }
+ } else {
+ found = i = 0;
+ while (i < nb_fb)
+ {
+ unsigned int end = fbs[i].address + fbs[i].fb_width*fbs[i].fb_height*2;
+ if (startAddress >= fbs[i].address && startAddress < end)
+ {
+ found = 1;
+ break;
+ }
+ i++;
+ }
+ }
+
+ if (!use_fbo && found) {
+ int tw, th, rh, cw, ch;
+ if (info->aspectRatioLog2 < 0)
+ {
+ th = 1 << info->largeLodLog2;
+ tw = th >> -info->aspectRatioLog2;
+ }
+ else
+ {
+ tw = 1 << info->largeLodLog2;
+ th = tw >> info->aspectRatioLog2;
+ }
+
+ if (info->aspectRatioLog2 < 0)
+ {
+ ch = 256;
+ cw = ch >> -info->aspectRatioLog2;
+ }
+ else
+ {
+ cw = 256;
+ ch = cw >> info->aspectRatioLog2;
+ }
+
+ if (use_fbo || th < screen_height)
+ rh = th;
+ else
+ rh = screen_height;
+
+ //printf("th %d rh %d ch %d\n", th, rh, ch);
+
+ invtex[tmu] = 1.0f - (th - rh) / (float)th;
+ } else
+ invtex[tmu] = 0;
+
+ if (info->format == GR_TEXFMT_ALPHA_INTENSITY_88 ) {
+ if (!found) {
+ return 0;
+ }
+ if(tmu == 0)
+ {
+ if(blackandwhite1 != found)
+ {
+ blackandwhite1 = found;
+ need_to_compile = 1;
+ }
+ }
+ else
+ {
+ if(blackandwhite0 != found)
+ {
+ blackandwhite0 = found;
+ need_to_compile = 1;
+ }
+ }
+ return 1;
+ }
+ return 0;
+
+}
+
+
+FX_ENTRY void FX_CALL
+grTextureAuxBufferExt( GrChipID_t tmu,
+ FxU32 startAddress,
+ GrLOD_t thisLOD,
+ GrLOD_t largeLOD,
+ GrAspectRatio_t aspectRatio,
+ GrTextureFormat_t format,
+ FxU32 odd_even_mask )
+{
+ LOG("grTextureAuxBufferExt(%d, %d, %d, %d %d, %d, %d)\r\n", tmu, startAddress, thisLOD, largeLOD, aspectRatio, format, odd_even_mask);
+ //display_warning("grTextureAuxBufferExt");
+}
+
+FX_ENTRY void FX_CALL grAuxBufferExt( GrBuffer_t buffer );
+
+FX_ENTRY GrProc FX_CALL
+grGetProcAddress( char *procName )
+{
+ LOG("grGetProcAddress(%s)\r\n", procName);
+ if(!strcmp(procName, "grSstWinOpenExt"))
+ return (GrProc)grSstWinOpenExt;
+ if(!strcmp(procName, "grTextureBufferExt"))
+ return (GrProc)grTextureBufferExt;
+ if(!strcmp(procName, "grChromaRangeExt"))
+ return (GrProc)grChromaRangeExt;
+ if(!strcmp(procName, "grChromaRangeModeExt"))
+ return (GrProc)grChromaRangeModeExt;
+ if(!strcmp(procName, "grTexChromaRangeExt"))
+ return (GrProc)grTexChromaRangeExt;
+ if(!strcmp(procName, "grTexChromaModeExt"))
+ return (GrProc)grTexChromaModeExt;
+ // ZIGGY framebuffer copy extension
+ if(!strcmp(procName, "grFramebufferCopyExt"))
+ return (GrProc)grFramebufferCopyExt;
+ if(!strcmp(procName, "grColorCombineExt"))
+ return (GrProc)grColorCombineExt;
+ if(!strcmp(procName, "grAlphaCombineExt"))
+ return (GrProc)grAlphaCombineExt;
+ if(!strcmp(procName, "grTexColorCombineExt"))
+ return (GrProc)grTexColorCombineExt;
+ if(!strcmp(procName, "grTexAlphaCombineExt"))
+ return (GrProc)grTexAlphaCombineExt;
+ if(!strcmp(procName, "grConstantColorValueExt"))
+ return (GrProc)grConstantColorValueExt;
+ if(!strcmp(procName, "grTextureAuxBufferExt"))
+ return (GrProc)grTextureAuxBufferExt;
+ if(!strcmp(procName, "grAuxBufferExt"))
+ return (GrProc)grAuxBufferExt;
+ if(!strcmp(procName, "grWrapperFullScreenResolutionExt"))
+ return (GrProc)grWrapperFullScreenResolutionExt;
+ if(!strcmp(procName, "grConfigWrapperExt"))
+ return (GrProc)grConfigWrapperExt;
+ if(!strcmp(procName, "grKeyPressedExt"))
+ return (GrProc)grKeyPressedExt;
+ if(!strcmp(procName, "grQueryResolutionsExt"))
+ return (GrProc)grQueryResolutionsExt;
+ if(!strcmp(procName, "grGetGammaTableExt"))
+ return (GrProc)grGetGammaTableExt;
+ display_warning("grGetProcAddress : %s", procName);
+ return 0;
+}
+
+FX_ENTRY FxU32 FX_CALL
+grGet( FxU32 pname, FxU32 plength, FxI32 *params )
+{
+ LOG("grGet(%d,%d)\r\n", pname, plength);
+ switch(pname)
+ {
+ case GR_MAX_TEXTURE_SIZE:
+ if (plength < 4 || params == NULL) return 0;
+ params[0] = 2048;
+ return 4;
+ break;
+ case GR_NUM_TMU:
+ if (plength < 4 || params == NULL) return 0;
+ if (!nbTextureUnits)
+ {
+ grSstWinOpen((unsigned long)NULL, GR_RESOLUTION_640x480 | 0x80000000, 0, GR_COLORFORMAT_ARGB,
+ GR_ORIGIN_UPPER_LEFT, 2, 1);
+ grSstWinClose(0);
+ }
+#ifdef VOODOO1
+ params[0] = 1;
+#else
+ if (nbTextureUnits > 2)
+ params[0] = 2;
+ else
+ params[0] = 1;
+#endif
+ return 4;
+ break;
+ case GR_NUM_BOARDS:
+ case GR_NUM_FB:
+ case GR_REVISION_FB:
+ case GR_REVISION_TMU:
+ if (plength < 4 || params == NULL) return 0;
+ params[0] = 1;
+ return 4;
+ break;
+ case GR_MEMORY_FB:
+ if (plength < 4 || params == NULL) return 0;
+ params[0] = 16*1024*1024;
+ return 4;
+ break;
+ case GR_MEMORY_TMU:
+ if (plength < 4 || params == NULL) return 0;
+ params[0] = 16*1024*1024;
+ return 4;
+ break;
+ case GR_MEMORY_UMA:
+ if (plength < 4 || params == NULL) return 0;
+ params[0] = 16*1024*1024*nbTextureUnits;
+ return 4;
+ break;
+ case GR_BITS_RGBA:
+ if (plength < 16 || params == NULL) return 0;
+ params[0] = 8;
+ params[1] = 8;
+ params[2] = 8;
+ params[3] = 8;
+ return 16;
+ break;
+ case GR_BITS_DEPTH:
+ if (plength < 4 || params == NULL) return 0;
+ params[0] = 16;
+ return 4;
+ break;
+ case GR_BITS_GAMMA:
+ if (plength < 4 || params == NULL) return 0;
+ params[0] = 8;
+ return 4;
+ break;
+ case GR_GAMMA_TABLE_ENTRIES:
+ if (plength < 4 || params == NULL) return 0;
+ params[0] = 256;
+ return 4;
+ break;
+ case GR_FOG_TABLE_ENTRIES:
+ if (plength < 4 || params == NULL) return 0;
+ params[0] = 64;
+ return 4;
+ break;
+ case GR_WDEPTH_MIN_MAX:
+ if (plength < 8 || params == NULL) return 0;
+ params[0] = 0;
+ params[1] = 65528;
+ return 8;
+ break;
+ case GR_ZDEPTH_MIN_MAX:
+ if (plength < 8 || params == NULL) return 0;
+ params[0] = 0;
+ params[1] = 65535;
+ return 8;
+ break;
+ case GR_LFB_PIXEL_PIPE:
+ if (plength < 4 || params == NULL) return 0;
+ params[0] = FXFALSE;
+ return 4;
+ break;
+ case GR_MAX_TEXTURE_ASPECT_RATIO:
+ if (plength < 4 || params == NULL) return 0;
+ params[0] = 3;
+ return 4;
+ break;
+ case GR_NON_POWER_OF_TWO_TEXTURES:
+ if (plength < 4 || params == NULL) return 0;
+ params[0] = FXFALSE;
+ return 4;
+ break;
+ case GR_TEXTURE_ALIGN:
+ if (plength < 4 || params == NULL) return 0;
+ params[0] = 0;
+ return 4;
+ break;
+ default:
+ display_warning("unknown pname in grGet : %x", pname);
+ }
+ return 0;
+}
+
+FX_ENTRY const char * FX_CALL
+grGetString( FxU32 pname )
+{
+ LOG("grGetString(%d)\r\n", pname);
+ switch(pname)
+ {
+ case GR_EXTENSION:
+ {
+ static char extension[] = "CHROMARANGE TEXCHROMA TEXMIRROR PALETTE6666 FOGCOORD EVOODOO TEXTUREBUFFER TEXUMA TEXFMT COMBINE GETGAMMA";
+ return extension;
+ }
+ break;
+ case GR_HARDWARE:
+ {
+ static char hardware[] = "Voodoo5 (tm)";
+ return hardware;
+ }
+ break;
+ case GR_VENDOR:
+ {
+ static char vendor[] = "3Dfx Interactive";
+ return vendor;
+ }
+ break;
+ case GR_RENDERER:
+ {
+ static char renderer[] = "Glide";
+ return renderer;
+ }
+ break;
+ case GR_VERSION:
+ {
+ static char version[] = "3.0";
+ return version;
+ }
+ break;
+ default:
+ display_warning("unknown grGetString selector : %x", pname);
+ }
+ return NULL;
+}
+
+static void render_rectangle(int texture_number,
+ int dst_x, int dst_y,
+ int src_width, int src_height,
+ int tex_width, int tex_height, int invert)
+{
+ LOGINFO("render_rectangle(%d,%d,%d,%d,%d,%d,%d,%d)",texture_number,dst_x,dst_y,src_width,src_height,tex_width,tex_height,invert);
+ int vertexOffset_location;
+ int textureSizes_location;
+ static float data[] = {
+ ((int)dst_x), //X 0
+ invert*-((int)dst_y), //Y 0
+ 0.0f, //U 0
+ 0.0f, //V 0
+
+ ((int)dst_x), //X 1
+ invert*-((int)dst_y + (int)src_height), //Y 1
+ 0.0f, //U 1
+ (float)src_height / (float)tex_height, //V 1
+
+ ((int)dst_x + (int)src_width),
+ invert*-((int)dst_y + (int)src_height),
+ (float)src_width / (float)tex_width,
+ (float)src_height / (float)tex_height,
+
+ ((int)dst_x),
+ invert*-((int)dst_y),
+ 0.0f,
+ 0.0f
+ };
+
+ vbo_disable();
+ glDisableVertexAttribArray(COLOUR_ATTR);
+ glDisableVertexAttribArray(TEXCOORD_1_ATTR);
+ glDisableVertexAttribArray(FOG_ATTR);
+
+ glVertexAttribPointer(POSITION_ATTR,2,GL_FLOAT,false,2,data); //Position
+ glVertexAttribPointer(TEXCOORD_0_ATTR,2,GL_FLOAT,false,2,&data[2]); //Tex
+
+ glEnableVertexAttribArray(COLOUR_ATTR);
+ glEnableVertexAttribArray(TEXCOORD_1_ATTR);
+ glEnableVertexAttribArray(FOG_ATTR);
+
+
+ disable_textureSizes();
+
+ glDrawArrays(GL_TRIANGLE_STRIP,0,4);
+ vbo_enable();
+
+
+/*
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glBegin(GL_QUADS);
+ glMultiTexCoord2fARB(texture_number, 0.0f, 0.0f);
+ glVertex2f(((int)dst_x - widtho) / (float)(width/2),
+ invert*-((int)dst_y - heighto) / (float)(height/2));
+ glMultiTexCoord2fARB(texture_number, 0.0f, (float)src_height / (float)tex_height);
+ glVertex2f(((int)dst_x - widtho) / (float)(width/2),
+ invert*-((int)dst_y + (int)src_height - heighto) / (float)(height/2));
+ glMultiTexCoord2fARB(texture_number, (float)src_width / (float)tex_width, (float)src_height / (float)tex_height);
+ glVertex2f(((int)dst_x + (int)src_width - widtho) / (float)(width/2),
+ invert*-((int)dst_y + (int)src_height - heighto) / (float)(height/2));
+ glMultiTexCoord2fARB(texture_number, (float)src_width / (float)tex_width, 0.0f);
+ glVertex2f(((int)dst_x + (int)src_width - widtho) / (float)(width/2),
+ invert*-((int)dst_y - heighto) / (float)(height/2));
+ glMultiTexCoord2fARB(texture_number, 0.0f, 0.0f);
+ glVertex2f(((int)dst_x - widtho) / (float)(width/2),
+ invert*-((int)dst_y - heighto) / (float)(height/2));
+ glEnd();
+*/
+
+ compile_shader();
+
+ glEnable(GL_DEPTH_TEST);
+ glEnable(GL_BLEND);
+}
+
+void reloadTexture()
+{
+ if (use_fbo || !render_to_texture || buffer_cleared)
+ return;
+
+ LOG("reload texture %dx%d\n", width, height);
+ //printf("reload texture %dx%d\n", width, height);
+
+ buffer_cleared = 1;
+
+ //glPushAttrib(GL_ALL_ATTRIB_BITS);
+ glActiveTexture(texture_unit);
+ glBindTexture(GL_TEXTURE_2D, pBufferAddress);
+ //glDisable(GL_ALPHA_TEST);
+ //glDrawBuffer(current_buffer);
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ set_copy_shader();
+ glDisable(GL_DEPTH_TEST);
+ glDisable(GL_CULL_FACE);
+ int w = 0, h = 0;
+ if (height > screen_height) h = screen_height - height;
+ render_rectangle(texture_unit,
+ -w, -h,
+ width, height,
+ width, height, -1);
+ glBindTexture(GL_TEXTURE_2D, default_texture);
+ //glPopAttrib();
+}
+
+void updateTexture()
+{
+ if (!use_fbo && render_to_texture == 2) {
+ LOG("update texture %x\n", pBufferAddress);
+ //printf("update texture %x\n", pBufferAddress);
+
+ // nothing changed, don't update the texture
+ if (!buffer_cleared) {
+ LOG("update cancelled\n", pBufferAddress);
+ return;
+ }
+
+ //glPushAttrib(GL_ALL_ATTRIB_BITS);
+
+ // save result of render to texture into actual texture
+ //glReadBuffer(current_buffer);
+ glActiveTexture(texture_unit);
+ // ZIGGY
+ // deleting the texture before resampling it increases speed on certain old
+ // nvidia cards (geforce 2 for example), unfortunatly it slows down a lot
+ // on newer cards.
+ //glDeleteTextures( 1, &pBufferAddress );
+ glBindTexture(GL_TEXTURE_2D, pBufferAddress);
+ glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
+ 0, viewport_offset, width, height, 0);
+
+ glBindTexture(GL_TEXTURE_2D, default_texture);
+ //glPopAttrib();
+ }
+}
+
+FX_ENTRY void FX_CALL grFramebufferCopyExt(int x, int y, int w, int h,
+ int from, int to, int mode)
+{
+ if (mode == GR_FBCOPY_MODE_DEPTH) {
+
+ int tw = 1, th = 1;
+ if (npot_support) {
+ tw = width; th = height;
+ } else {
+ while (tw < width) tw <<= 1;
+ while (th < height) th <<= 1;
+ }
+
+ if (from == GR_FBCOPY_BUFFER_BACK && to == GR_FBCOPY_BUFFER_FRONT) {
+ //printf("save depth buffer %d\n", render_to_texture);
+ // save the depth image in a texture
+ //glReadBuffer(current_buffer);
+ glBindTexture(GL_TEXTURE_2D, depth_texture);
+ glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT,
+ 0, viewport_offset, tw, th, 0);
+ glBindTexture(GL_TEXTURE_2D, default_texture);
+ return;
+ }
+ if (from == GR_FBCOPY_BUFFER_FRONT && to == GR_FBCOPY_BUFFER_BACK) {
+ //printf("writing to depth buffer %d\n", render_to_texture);
+ //glPushAttrib(GL_ALL_ATTRIB_BITS);
+ //glDisable(GL_ALPHA_TEST);
+ //glDrawBuffer(current_buffer);
+ glActiveTexture(texture_unit);
+ glBindTexture(GL_TEXTURE_2D, depth_texture);
+ glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
+ set_depth_shader();
+ glEnable(GL_DEPTH_TEST);
+ glDepthFunc(GL_ALWAYS);
+ glDisable(GL_CULL_FACE);
+ render_rectangle(texture_unit,
+ 0, 0,
+ width, height,
+ tw, th, -1);
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ glBindTexture(GL_TEXTURE_2D, default_texture);
+ //glPopAttrib();
+ return;
+ }
+
+ }
+}
+
+FX_ENTRY void FX_CALL
+grRenderBuffer( GrBuffer_t buffer )
+{
+#ifdef _WIN32
+ static HANDLE region = NULL;
+ int realWidth = pBufferWidth, realHeight = pBufferHeight;
+#endif // _WIN32
+ LOG("grRenderBuffer(%d)\r\n", buffer);
+ //printf("grRenderBuffer(%d)\n", buffer);
+
+ switch(buffer)
+ {
+ case GR_BUFFER_BACKBUFFER:
+ if(render_to_texture)
+ {
+ updateTexture();
+
+ // VP z fix
+ //glMatrixMode(GL_MODELVIEW);
+ //glLoadIdentity();
+ //glTranslatef(0, 0, 1-zscale);
+ //glScalef(1, 1, zscale);
+ inverted_culling = 0;
+ grCullMode(culling_mode);
+
+ width = savedWidth;
+ height = savedHeight;
+ widtho = savedWidtho;
+ heighto = savedHeighto;
+ if (use_fbo) {
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ glBindRenderbuffer( GL_RENDERBUFFER, 0 );
+ }
+ curBufferAddr = 0;
+
+ glViewport(0, viewport_offset, width, viewport_height);
+ glScissor(0, viewport_offset, width, height);
+
+#ifdef SAVE_CBUFFER
+ if (!use_fbo && render_to_texture == 2) {
+ // restore color buffer
+ if (nbAuxBuffers > 0) {
+ //glDrawBuffer(GL_BACK);
+ current_buffer = GL_BACK;
+ } else if (save_w) {
+ int tw = 1, th = 1;
+ //printf("restore %dx%d\n", save_w, save_h);
+ if (npot_support) {
+ tw = screen_width;
+ th = screen_height;
+ } else {
+ while (tw < screen_width) tw <<= 1;
+ while (th < screen_height) th <<= 1;
+ }
+
+ //glPushAttrib(GL_ALL_ATTRIB_BITS);
+ //glDisable(GL_ALPHA_TEST);
+ //glDrawBuffer(GL_BACK);
+ glActiveTexture(texture_unit);
+ glBindTexture(GL_TEXTURE_2D, color_texture);
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ set_copy_shader();
+ glDisable(GL_DEPTH_TEST);
+ glDisable(GL_CULL_FACE);
+ render_rectangle(texture_unit,
+ 0, 0,
+ save_w, save_h,
+ tw, th, -1);
+ glBindTexture(GL_TEXTURE_2D, default_texture);
+ //glPopAttrib();
+
+ save_w = save_h = 0;
+ }
+ }
+#endif
+ render_to_texture = 0;
+ }
+ //glDrawBuffer(GL_BACK);
+ break;
+ case 6: // RENDER TO TEXTURE
+ if(!render_to_texture)
+ {
+ savedWidth = width;
+ savedHeight = height;
+ savedWidtho = widtho;
+ savedHeighto = heighto;
+ }
+
+ {
+ if (!use_fbo) {
+ //glMatrixMode(GL_MODELVIEW);
+ //glLoadIdentity();
+ //glTranslatef(0, 0, 1-zscale);
+ //glScalef(1, 1, zscale);
+ inverted_culling = 0;
+ } else {
+/*
+ float m[4*4] = {1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f,-1.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f};
+ glMatrixMode(GL_MODELVIEW);
+ glLoadMatrixf(m);
+ // VP z fix
+ glTranslatef(0, 0, 1-zscale);
+ glScalef(1, 1*1, zscale);
+*/
+ inverted_culling = 1;
+ grCullMode(culling_mode);
+ }
+ }
+ render_to_texture = 1;
+ break;
+ default:
+ display_warning("grRenderBuffer : unknown buffer : %x", buffer);
+ }
+}
+
+FX_ENTRY void FX_CALL
+grAuxBufferExt( GrBuffer_t buffer )
+{
+ LOG("grAuxBufferExt(%d)\r\n", buffer);
+ //display_warning("grAuxBufferExt");
+
+ if (buffer == GR_BUFFER_AUXBUFFER) {
+ invtex[0] = 0;
+ invtex[1] = 0;
+ need_to_compile = 0;
+ set_depth_shader();
+ glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
+ glEnable(GL_DEPTH_TEST);
+ glDepthFunc(GL_ALWAYS);
+ glDisable(GL_CULL_FACE);
+ //glDisable(GL_ALPHA_TEST);
+ glDepthMask(GL_TRUE);
+ grTexFilterMode(GR_TMU1, GR_TEXTUREFILTER_POINT_SAMPLED, GR_TEXTUREFILTER_POINT_SAMPLED);
+ } else {
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ need_to_compile = 1;
+ }
+}
+
+FX_ENTRY void FX_CALL
+grBufferClear( GrColor_t color, GrAlpha_t alpha, FxU32 depth )
+{
+ vbo_draw();
+ LOG("grBufferClear(%d,%d,%d)\r\n", color, alpha, depth);
+ switch(lfb_color_fmt)
+ {
+ case GR_COLORFORMAT_ARGB:
+ glClearColor(((color >> 16) & 0xFF) / 255.0f,
+ ((color >> 8) & 0xFF) / 255.0f,
+ ( color & 0xFF) / 255.0f,
+ alpha / 255.0f);
+ break;
+ case GR_COLORFORMAT_RGBA:
+ glClearColor(((color >> 24) & 0xFF) / 255.0f,
+ ((color >> 16) & 0xFF) / 255.0f,
+ (color & 0xFF) / 255.0f,
+ alpha / 255.0f);
+ break;
+ default:
+ display_warning("grBufferClear: unknown color format : %x", lfb_color_fmt);
+ }
+
+ if (w_buffer_mode)
+ glClearDepthf(1.0f - ((1.0f + (depth >> 4) / 4096.0f) * (1 << (depth & 0xF))) / 65528.0);
+ else
+ glClearDepthf(depth / 65535.0f);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ // ZIGGY TODO check that color mask is on
+ buffer_cleared = 1;
+
+}
+
+// #include <unistd.h>
+FX_ENTRY void FX_CALL
+grBufferSwap( FxU32 swap_interval )
+{
+ vbo_draw();
+// glFinish();
+// printf("rendercallback is %p\n", renderCallback);
+ if(renderCallback)
+ (*renderCallback)(1);
+ int i;
+ LOG("grBufferSwap(%d)\r\n", swap_interval);
+ //printf("swap\n");
+ if (render_to_texture) {
+ display_warning("swap while render_to_texture\n");
+ return;
+ }
+
+ CoreVideo_GL_SwapBuffers();
+ for (i = 0; i < nb_fb; i++)
+ fbs[i].buff_clear = 1;
+
+ // VP debugging
+#ifdef VPDEBUG
+ dump_stop();
+ SDL_Event event;
+ while (SDL_PollEvent(&event)) {
+ switch (event.type) {
+case SDL_KEYDOWN:
+ switch (event.key.keysym.sym) {
+case 'd':
+ printf("Dumping !\n");
+ dump_start();
+ break;
+case 'w': {
+ static int wireframe;
+ wireframe = !wireframe;
+ glPolygonMode(GL_FRONT_AND_BACK, wireframe? GL_LINE : GL_FILL);
+ break;
+ }
+ }
+ break;
+ }
+ }
+#endif
+}
+
+// frame buffer
+
+FX_ENTRY FxBool FX_CALL
+grLfbLock( GrLock_t type, GrBuffer_t buffer, GrLfbWriteMode_t writeMode,
+ GrOriginLocation_t origin, FxBool pixelPipeline,
+ GrLfbInfo_t *info )
+{
+ LOG("grLfbLock(%d,%d,%d,%d,%d)\r\n", type, buffer, writeMode, origin, pixelPipeline);
+printf("grLfbLock(%d,%d,%d,%d,%d)\r\n", type, buffer, writeMode, origin, pixelPipeline);
+ if (type == GR_LFB_WRITE_ONLY)
+ {
+ display_warning("grLfbLock : write only");
+ }
+ else
+ {
+ unsigned char *buf;
+ int i,j;
+
+ switch(buffer)
+ {
+ case GR_BUFFER_FRONTBUFFER:
+ //glReadBuffer(GL_FRONT);
+ break;
+ case GR_BUFFER_BACKBUFFER:
+ //glReadBuffer(GL_BACK);
+ break;
+ default:
+ display_warning("grLfbLock : unknown buffer : %x", buffer);
+ }
+
+ if(buffer != GR_BUFFER_AUXBUFFER)
+ {
+ if (writeMode == GR_LFBWRITEMODE_888) {
+/*SEB*/
+ buf = (unsigned char*)malloc(width*height*4);
+ //printf("LfbLock GR_LFBWRITEMODE_888\n");
+ info->lfbPtr = frameBuffer;
+ info->strideInBytes = width*4;
+ info->writeMode = GR_LFBWRITEMODE_888;
+ info->origin = origin;
+ //glReadPixels(0, viewport_offset, width, height, GL_BGRA, GL_UNSIGNED_BYTE, frameBuffer);
+ glReadPixels(0, viewport_offset, width, height, GL_RGBA, GL_UNSIGNED_BYTE, buf);
+
+/*SEB*/
+ unsigned char *p=buf;
+ for (j=0; j<height; j++)
+ {
+ short unsigned int *f=frameBuffer+(height-j-1)*width;
+ for (i=0; i<width; i++)
+ {
+ *(f++) =
+ (*(p) <<24) |
+ (*(p+1) <<16) |
+ (*(p+2) << 8) |
+ (0xff);
+ p+=4;
+ }
+ }
+ free(buf);
+ } else {
+ buf = (unsigned char*)malloc(width*height*4);
+
+ info->lfbPtr = frameBuffer;
+ info->strideInBytes = width*2;
+ info->writeMode = GR_LFBWRITEMODE_565;
+ info->origin = origin;
+ glReadPixels(0, viewport_offset, width, height, GL_RGBA, GL_UNSIGNED_BYTE, buf);
+
+/*SEB*/
+ unsigned char *p=buf;
+ for (j=0; j<height; j++)
+ {
+ short unsigned int *f=frameBuffer+(height-j-1)*width;
+ for (i=0; i<width; i++)
+ {
+/* frameBuffer[(height-j-1)*width+i] =
+ ((buf[j*width*4+i*4+0] >> 3) << 11) |
+ ((buf[j*width*4+i*4+1] >> 2) << 5) |
+ (buf[j*width*4+i*4+2] >> 3);*/
+ *(f++) =
+ ((*(p) >> 3) << 11) |
+ ((*(p+1) >> 2) << 5) |
+ (*(p+2) >> 3);
+ p+=4;
+ }
+ }
+ free(buf);
+ }
+ }
+ else
+ {
+ info->lfbPtr = depthBuffer;
+ info->strideInBytes = width*2;
+ info->writeMode = GR_LFBWRITEMODE_ZA16;
+ info->origin = origin;
+ //*SEB* *TODO* check alignment
+ glReadPixels(0, viewport_offset, width, height, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, depthBuffer);
+ }
+ }
+
+ return FXTRUE;
+}
+
+FX_ENTRY FxBool FX_CALL
+grLfbUnlock( GrLock_t type, GrBuffer_t buffer )
+{
+ LOG("grLfbUnlock(%d,%d)\r\n", type, buffer);
+ if (type == GR_LFB_WRITE_ONLY)
+ {
+ display_warning("grLfbUnlock : write only");
+ }
+ return FXTRUE;
+}
+
+FX_ENTRY FxBool FX_CALL
+grLfbReadRegion( GrBuffer_t src_buffer,
+ FxU32 src_x, FxU32 src_y,
+ FxU32 src_width, FxU32 src_height,
+ FxU32 dst_stride, void *dst_data )
+{
+ unsigned char *buf;
+ unsigned int i,j;
+ unsigned short *frameBuffer = (unsigned short*)dst_data;
+ unsigned short *depthBuffer = (unsigned short*)dst_data;
+ LOG("grLfbReadRegion(%d,%d,%d,%d,%d,%d)\r\n", src_buffer, src_x, src_y, src_width, src_height, dst_stride);
+//printf("grLfbReadRegion(%d,%d,%d,%d,%d,%d)\r\n", src_buffer, src_x, src_y, src_width, src_height, dst_stride);
+
+ switch(src_buffer)
+ {
+ case GR_BUFFER_FRONTBUFFER:
+ //glReadBuffer(GL_FRONT);
+ break;
+ case GR_BUFFER_BACKBUFFER:
+ //glReadBuffer(GL_BACK);
+ break;
+ /*case GR_BUFFER_AUXBUFFER:
+ glReadBuffer(current_buffer);
+ break;*/
+ default:
+ display_warning("grReadRegion : unknown buffer : %x", src_buffer);
+ }
+
+ if(src_buffer != GR_BUFFER_AUXBUFFER)
+ {
+ buf = (unsigned char*)malloc(src_width*src_height*4);
+
+ glReadPixels(src_x, (viewport_offset)+height-src_y-src_height, src_width, src_height, GL_RGBA, GL_UNSIGNED_BYTE, buf);
+ for (j=0; j<src_height; j++)
+ {
+/*SEB*/
+ unsigned char *p=buf+(src_height-j-1)*src_width*4;
+ unsigned short *f=frameBuffer+(j*dst_stride/2);
+ for (i=0; i<src_width; i++)
+ {
+/* frameBuffer[j*(dst_stride/2)+i] =
+ ((buf[(src_height-j-1)*src_width*4+i*4+0] >> 3) << 11) |
+ ((buf[(src_height-j-1)*src_width*4+i*4+1] >> 2) << 5) |
+ (buf[(src_height-j-1)*src_width*4+i*4+2] >> 3);*/
+ *(f++) =
+ ((*(p) >> 3) << 11) |
+ ((*(p+1) >> 2) << 5) |
+ (*(p+2) >> 3);
+ p+=4;
+ }
+ }
+ free(buf);
+ }
+ else
+ {
+ buf = (unsigned char*)malloc(src_width*src_height*2);
+//*SEB read in buf, not depthBuffer.
+ glReadPixels(src_x, (viewport_offset)+height-src_y-src_height, src_width, src_height, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, buf);
+
+ for (j=0;j<src_height; j++)
+ {
+//*SEB*
+ unsigned short *d=depthBuffer+j*dst_stride/2;
+ unsigned short *p=(unsigned short*)buf+(src_height-j-1)*src_width; //orignal look fishy. why *4???
+ for (i=0; i<src_width; i++)
+ {
+/* depthBuffer[j*(dst_stride/2)+i] =
+ ((unsigned short*)buf)[(src_height-j-1)*src_width*4+i*4];*/
+ *(d++) = *(p++); //why *4 (prob. GL_PACK was=4), plus transcoding to short, that make *8 ???
+ }
+ }
+ free(buf);
+ }
+
+ return FXTRUE;
+}
+
+FX_ENTRY FxBool FX_CALL
+grLfbWriteRegion( GrBuffer_t dst_buffer,
+ FxU32 dst_x, FxU32 dst_y,
+ GrLfbSrcFmt_t src_format,
+ FxU32 src_width, FxU32 src_height,
+ FxBool pixelPipeline,
+ FxI32 src_stride, void *src_data )
+{
+ unsigned char *buf;
+ unsigned int i,j;
+ unsigned short *frameBuffer = (unsigned short*)src_data;
+ int texture_number;
+ unsigned int tex_width = 1, tex_height = 1;
+ LOG("grLfbWriteRegion(%d,%d,%d,%d,%d,%d,%d,%d)\r\n",dst_buffer, dst_x, dst_y, src_format, src_width, src_height, pixelPipeline, src_stride);
+//printf("grLfbWriteRegion(%d,%d,%d,%d,%d,%d,%d,%d)\r\n",dst_buffer, dst_x, dst_y, src_format, src_width, src_height, pixelPipeline, src_stride);
+
+ //glPushAttrib(GL_ALL_ATTRIB_BITS);
+
+ while (tex_width < src_width) tex_width <<= 1;
+ while (tex_height < src_height) tex_height <<= 1;
+
+ switch(dst_buffer)
+ {
+ case GR_BUFFER_BACKBUFFER:
+ //glDrawBuffer(GL_BACK);
+ break;
+ case GR_BUFFER_AUXBUFFER:
+ //glDrawBuffer(current_buffer);
+ break;
+ default:
+ display_warning("grLfbWriteRegion : unknown buffer : %x", dst_buffer);
+ }
+
+ if(dst_buffer != GR_BUFFER_AUXBUFFER)
+ {
+ buf = (unsigned char*)malloc(tex_width*tex_height*4);
+
+ texture_number = GL_TEXTURE0;
+ glActiveTexture(texture_number);
+
+ const unsigned int half_stride = src_stride / 2;
+
+ const int comp_stride = half_stride - src_width;
+ const int comp_tex = (tex_width - src_width)*4;
+ unsigned short *f=frameBuffer;
+ unsigned char *p=buf;
+
+ switch(src_format)
+ {
+ case GR_LFB_SRC_FMT_1555:
+ for (j=0; j<src_height; j++)
+ {
+ for (i=0; i<src_width; i++)
+ {
+/* const unsigned int col = frameBuffer[j*half_stride+i];
+ buf[j*tex_width*4+i*4+0]=((col>>10)&0x1F)<<3;
+ buf[j*tex_width*4+i*4+1]=((col>>5)&0x1F)<<3;
+ buf[j*tex_width*4+i*4+2]=((col>>0)&0x1F)<<3;
+ buf[j*tex_width*4+i*4+3]= (col>>15) ? 0xFF : 0;*/
+ const unsigned int col = *(f++);
+ *(p)=((col>>10)&0x1F)<<3;
+ *(p+1)=((col>>5)&0x1F)<<3;
+ *(p+2)=((col>>0)&0x1F)<<3;
+ *(p+3)= (col>>15) ? 0xFF : 0;
+ p+=4;
+ }
+ p+=comp_tex;
+ f+=comp_stride;
+ }
+ break;
+ case GR_LFBWRITEMODE_555:
+ for (j=0; j<src_height; j++)
+ {
+ for (i=0; i<src_width; i++)
+ {
+/* const unsigned int col = frameBuffer[j*half_stride+i];
+ buf[j*tex_width*4+i*4+0]=((col>>10)&0x1F)<<3;
+ buf[j*tex_width*4+i*4+1]=((col>>5)&0x1F)<<3;
+ buf[j*tex_width*4+i*4+2]=((col>>0)&0x1F)<<3;
+ buf[j*tex_width*4+i*4+3]=0xFF;*/
+ const unsigned int col = *(f++);
+ *(p)=((col>>10)&0x1F)<<3;
+ *(p+1)=((col>>5)&0x1F)<<3;
+ *(p+2)=((col>>0)&0x1F)<<3;
+ *(p+3)=0xFF;
+ p+=4;
+ }
+ p+=comp_tex;
+ f+=comp_stride;
+ }
+ break;
+ case GR_LFBWRITEMODE_565:
+ for (j=0; j<src_height; j++)
+ {
+ for (i=0; i<src_width; i++)
+ {
+/* const unsigned int col = frameBuffer[j*half_stride+i];
+ buf[j*tex_width*4+i*4+0]=((col>>11)&0x1F)<<3;
+ buf[j*tex_width*4+i*4+1]=((col>>5)&0x3F)<<2;
+ buf[j*tex_width*4+i*4+2]=((col>>0)&0x1F)<<3;
+ buf[j*tex_width*4+i*4+3]=0xFF;*/
+ const unsigned int col = *(f++);
+ *(p)=((col>>11)&0x1F)<<3;
+ *(p+1)=((col>>5)&0x3F)<<2;
+ *(p+2)=((col>>0)&0x1F)<<3;
+ *(p+3)=0xFF;
+ p+=4;
+ }
+ p+=comp_tex;
+ f+=comp_stride;
+ }
+ break;
+ default:
+ display_warning("grLfbWriteRegion : unknown format : %d", src_format);
+ }
+
+#ifdef VPDEBUG
+ if (dumping) {
+ ilTexImage(tex_width, tex_height, 1, 4, IL_RGBA, IL_UNSIGNED_BYTE, buf);
+ char name[128];
+ static int id;
+ sprintf(name, "dump/writecolor%d.png", id++);
+ ilSaveImage(name);
+ //printf("dumped gdLfbWriteRegion %s\n", name);
+ }
+#endif
+
+ glBindTexture(GL_TEXTURE_2D, default_texture);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex_width, tex_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, buf);
+ free(buf);
+
+ set_copy_shader();
+
+ glDisable(GL_DEPTH_TEST);
+ glDisable(GL_BLEND);
+ render_rectangle(texture_number,
+ dst_x, dst_y,
+ src_width, src_height,
+ tex_width, tex_height, +1);
+
+ }
+ else
+ {
+ float *buf = (float*)malloc(src_width*(src_height+(viewport_offset))*sizeof(float));
+
+ if (src_format != GR_LFBWRITEMODE_ZA16)
+ display_warning("unknown depth buffer write format:%x", src_format);
+
+ if(dst_x || dst_y)
+ display_warning("dst_x:%d, dst_y:%d\n",dst_x, dst_y);
+
+ for (j=0; j<src_height; j++)
+ {
+ for (i=0; i<src_width; i++)
+ {
+ buf[(j+(viewport_offset))*src_width+i] =
+ (frameBuffer[(src_height-j-1)*(src_stride/2)+i]/(65536.0f*(2.0f/zscale)))+1-zscale/2.0f;
+ }
+ }
+
+#ifdef VPDEBUG
+ if (dumping) {
+ unsigned char * buf2 = (unsigned char *)malloc(src_width*(src_height+(viewport_offset)));
+ for (i=0; i<src_width*src_height ; i++)
+ buf2[i] = buf[i]*255.0f;
+ ilTexImage(src_width, src_height, 1, 1, IL_LUMINANCE, IL_UNSIGNED_BYTE, buf2);
+ char name[128];
+ static int id;
+ sprintf(name, "dump/writedepth%d.png", id++);
+ ilSaveImage(name);
+ //printf("dumped gdLfbWriteRegion %s\n", name);
+ free(buf2);
+ }
+#endif
+
+ glEnable(GL_DEPTH_TEST);
+ glDepthFunc(GL_ALWAYS);
+
+ //glDrawBuffer(GL_BACK);
+ glClear( GL_DEPTH_BUFFER_BIT );
+ glDepthMask(1);
+ //glDrawPixels(src_width, src_height+(viewport_offset), GL_DEPTH_COMPONENT, GL_FLOAT, buf);
+
+ free(buf);
+ }
+ //glDrawBuffer(current_buffer);
+ //glPopAttrib();
+ return FXTRUE;
+}
+
+/* wrapper-specific glide extensions */
+
+FX_ENTRY char ** FX_CALL
+grQueryResolutionsExt(FxI32 * Size)
+{
+ return 0;
+/*
+ LOG("grQueryResolutionsExt\r\n");
+ return g_FullScreenResolutions.getResolutionsList(Size);
+*/
+}
+
+FX_ENTRY GrScreenResolution_t FX_CALL grWrapperFullScreenResolutionExt(FxU32* width, FxU32* height)
+{
+ return 0;
+/*
+ LOG("grWrapperFullScreenResolutionExt\r\n");
+ g_FullScreenResolutions.getResolution(config.res, width, height);
+ return config.res;
+*/
+}
+
+FX_ENTRY FxBool FX_CALL grKeyPressedExt(FxU32 key)
+{
+ return 0;
+/*
+#ifdef _WIN32
+ return (GetAsyncKeyState(key) & 0x8000);
+#else
+ if (key == 1) //LBUTTON
+ {
+ Uint8 mstate = SDL_GetMouseState(NULL, NULL);
+ return (mstate & SDL_BUTTON_LMASK);
+ }
+ else
+ {
+ Uint8 *keystates = SDL_GetKeyState( NULL );
+ if( keystates[ key ] )
+ {
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+ }
+#endif
+*/
+}
+
+FX_ENTRY void FX_CALL grConfigWrapperExt(FxI32 resolution, FxI32 vram, FxBool fbo, FxBool aniso)
+{
+ LOG("grConfigWrapperExt\r\n");
+ config.res = resolution;
+ config.vram_size = vram;
+ config.fbo = fbo;
+ config.anisofilter = aniso;
+}
+
+// unused by glide64
+
+FX_ENTRY FxI32 FX_CALL
+grQueryResolutions( const GrResolution *resTemplate, GrResolution *output )
+{
+ int res_inf = 0;
+ int res_sup = 0xf;
+ int i;
+ int n=0;
+ LOG("grQueryResolutions\r\n");
+ display_warning("grQueryResolutions");
+ if ((unsigned int)resTemplate->resolution != GR_QUERY_ANY)
+ {
+ res_inf = res_sup = resTemplate->resolution;
+ }
+ if ((unsigned int)resTemplate->refresh == GR_QUERY_ANY) display_warning("querying any refresh rate");
+ if ((unsigned int)resTemplate->numAuxBuffers == GR_QUERY_ANY) display_warning("querying any numAuxBuffers");
+ if ((unsigned int)resTemplate->numColorBuffers == GR_QUERY_ANY) display_warning("querying any numColorBuffers");
+
+ if (output == NULL) return res_sup - res_inf + 1;
+ for (i=res_inf; i<=res_sup; i++)
+ {
+ output[n].resolution = i;
+ output[n].refresh = resTemplate->refresh;
+ output[n].numAuxBuffers = resTemplate->numAuxBuffers;
+ output[n].numColorBuffers = resTemplate->numColorBuffers;
+ n++;
+ }
+ return res_sup - res_inf + 1;
+}
+
+FX_ENTRY FxBool FX_CALL
+grReset( FxU32 what )
+{
+ display_warning("grReset");
+ return 1;
+}
+
+FX_ENTRY void FX_CALL
+grEnable( GrEnableMode_t mode )
+{
+ LOG("grEnable(%d)\r\n", mode);
+ if (mode == GR_TEXTURE_UMA_EXT)
+ UMAmode = 1;
+}
+
+FX_ENTRY void FX_CALL
+grDisable( GrEnableMode_t mode )
+{
+ LOG("grDisable(%d)\r\n", mode);
+ if (mode == GR_TEXTURE_UMA_EXT)
+ UMAmode = 0;
+}
+
+FX_ENTRY void FX_CALL
+grDisableAllEffects( void )
+{
+ display_warning("grDisableAllEffects");
+}
+
+FX_ENTRY void FX_CALL
+grErrorSetCallback( GrErrorCallbackFnc_t fnc )
+{
+ display_warning("grErrorSetCallback");
+}
+
+FX_ENTRY void FX_CALL
+grFinish(void)
+{
+ display_warning("grFinish");
+}
+
+FX_ENTRY void FX_CALL
+grFlush(void)
+{
+ display_warning("grFlush");
+}
+
+FX_ENTRY void FX_CALL
+grTexMultibase( GrChipID_t tmu,
+ FxBool enable )
+{
+ display_warning("grTexMultibase");
+}
+
+FX_ENTRY void FX_CALL
+grTexMipMapMode( GrChipID_t tmu,
+ GrMipMapMode_t mode,
+ FxBool lodBlend )
+{
+ display_warning("grTexMipMapMode");
+}
+
+FX_ENTRY void FX_CALL
+grTexDownloadTablePartial( GrTexTable_t type,
+ void *data,
+ int start,
+ int end )
+{
+ display_warning("grTexDownloadTablePartial");
+}
+
+FX_ENTRY void FX_CALL
+grTexDownloadTable( GrTexTable_t type,
+ void *data )
+{
+ display_warning("grTexDownloadTable");
+}
+
+FX_ENTRY FxBool FX_CALL
+grTexDownloadMipMapLevelPartial( GrChipID_t tmu,
+ FxU32 startAddress,
+ GrLOD_t thisLod,
+ GrLOD_t largeLod,
+ GrAspectRatio_t aspectRatio,
+ GrTextureFormat_t format,
+ FxU32 evenOdd,
+ void *data,
+ int start,
+ int end )
+{
+ display_warning("grTexDownloadMipMapLevelPartial");
+ return 1;
+}
+
+FX_ENTRY void FX_CALL
+grTexDownloadMipMapLevel( GrChipID_t tmu,
+ FxU32 startAddress,
+ GrLOD_t thisLod,
+ GrLOD_t largeLod,
+ GrAspectRatio_t aspectRatio,
+ GrTextureFormat_t format,
+ FxU32 evenOdd,
+ void *data )
+{
+ display_warning("grTexDownloadMipMapLevel");
+}
+
+FX_ENTRY void FX_CALL
+grTexNCCTable( GrNCCTable_t table )
+{
+ display_warning("grTexNCCTable");
+}
+
+FX_ENTRY void FX_CALL
+grViewport( FxI32 x, FxI32 y, FxI32 width, FxI32 height )
+{
+ display_warning("grViewport");
+}
+
+FX_ENTRY void FX_CALL
+grDepthRange( FxFloat n, FxFloat f )
+{
+ display_warning("grDepthRange");
+}
+
+FX_ENTRY void FX_CALL
+grSplash(float x, float y, float width, float height, FxU32 frame)
+{
+ display_warning("grSplash");
+}
+
+FX_ENTRY FxBool FX_CALL
+grSelectContext( GrContext_t context )
+{
+ display_warning("grSelectContext");
+ return 1;
+}
+
+FX_ENTRY void FX_CALL
+grAADrawTriangle(
+ const void *a, const void *b, const void *c,
+ FxBool ab_antialias, FxBool bc_antialias, FxBool ca_antialias
+ )
+{
+ display_warning("grAADrawTriangle");
+}
+
+FX_ENTRY void FX_CALL
+grAlphaControlsITRGBLighting( FxBool enable )
+{
+ display_warning("grAlphaControlsITRGBLighting");
+}
+
+FX_ENTRY void FX_CALL
+grGlideSetVertexLayout( const void *layout )
+{
+ display_warning("grGlideSetVertexLayout");
+}
+
+FX_ENTRY void FX_CALL
+grGlideGetVertexLayout( void *layout )
+{
+ display_warning("grGlideGetVertexLayout");
+}
+
+FX_ENTRY void FX_CALL
+grGlideSetState( const void *state )
+{
+ display_warning("grGlideSetState");
+}
+
+FX_ENTRY void FX_CALL
+grGlideGetState( void *state )
+{
+ display_warning("grGlideGetState");
+}
+
+FX_ENTRY void FX_CALL
+grLfbWriteColorFormat(GrColorFormat_t colorFormat)
+{
+ display_warning("grLfbWriteColorFormat");
+}
+
+FX_ENTRY void FX_CALL
+grLfbWriteColorSwizzle(FxBool swizzleBytes, FxBool swapWords)
+{
+ display_warning("grLfbWriteColorSwizzle");
+}
+
+FX_ENTRY void FX_CALL
+grLfbConstantDepth( FxU32 depth )
+{
+ display_warning("grLfbConstantDepth");
+}
+
+FX_ENTRY void FX_CALL
+grLfbConstantAlpha( GrAlpha_t alpha )
+{
+ display_warning("grLfbConstantAlpha");
+}
+
+FX_ENTRY void FX_CALL
+grTexMultibaseAddress( GrChipID_t tmu,
+ GrTexBaseRange_t range,
+ FxU32 startAddress,
+ FxU32 evenOdd,
+ GrTexInfo *info )
+{
+ display_warning("grTexMultibaseAddress");
+}
+
+/*
+inline void MySleep(FxU32 ms)
+{
+#ifdef _WIN32
+ Sleep(ms);
+#else
+ SDL_Delay(ms);
+#endif
+}
+*/
+
+#ifdef _WIN32
+static void CorrectGamma(LPVOID apGammaRamp)
+{
+ HDC hdc = GetDC(NULL);
+ if (hdc != NULL)
+ {
+ SetDeviceGammaRamp(hdc, apGammaRamp);
+ ReleaseDC(NULL, hdc);
+ }
+}
+#else
+static void CorrectGamma(const FxU16 aGammaRamp[3][256])
+{
+ //TODO?
+ //int res = SDL_SetGammaRamp(aGammaRamp[0], aGammaRamp[1], aGammaRamp[2]);
+ //LOG("SDL_SetGammaRamp returned %d\r\n", res);
+}
+#endif
+
+FX_ENTRY void FX_CALL
+grLoadGammaTable( FxU32 nentries, FxU32 *red, FxU32 *green, FxU32 *blue)
+{
+ LOG("grLoadGammaTable\r\n");
+ if (!fullscreen)
+ return;
+ FxU16 aGammaRamp[3][256];
+ for (int i = 0; i < 256; i++)
+ {
+ aGammaRamp[0][i] = (FxU16)((red[i] << 8) & 0xFFFF);
+ aGammaRamp[1][i] = (FxU16)((green[i] << 8) & 0xFFFF);
+ aGammaRamp[2][i] = (FxU16)((blue[i] << 8) & 0xFFFF);
+ }
+ CorrectGamma(aGammaRamp);
+ //MySleep(1000); //workaround for Mupen64
+}
+
+FX_ENTRY void FX_CALL
+grGetGammaTableExt(FxU32 nentries, FxU32 *red, FxU32 *green, FxU32 *blue)
+{
+ return;
+ //TODO?
+ /*
+ LOG("grGetGammaTableExt()\r\n");
+ FxU16 aGammaRamp[3][256];
+#ifdef _WIN32
+ HDC hdc = GetDC(NULL);
+ if (hdc == NULL)
+ return;
+ if (GetDeviceGammaRamp(hdc, aGammaRamp) == TRUE)
+ {
+ ReleaseDC(NULL, hdc);
+#else
+ if (SDL_GetGammaRamp(aGammaRamp[0], aGammaRamp[1], aGammaRamp[2]) != -1)
+ {
+#endif
+ for (int i = 0; i < 256; i++)
+ {
+ red[i] = aGammaRamp[0][i] >> 8;
+ green[i] = aGammaRamp[1][i] >> 8;
+ blue[i] = aGammaRamp[2][i] >> 8;
+ }
+ }
+ */
+}
+
+FX_ENTRY void FX_CALL
+guGammaCorrectionRGB( FxFloat gammaR, FxFloat gammaG, FxFloat gammaB )
+{
+ LOG("guGammaCorrectionRGB()\r\n");
+ if (!fullscreen)
+ return;
+ FxU16 aGammaRamp[3][256];
+ for (int i = 0; i < 256; i++)
+ {
+ aGammaRamp[0][i] = (((FxU16)((pow(i/255.0F, 1.0F/gammaR)) * 255.0F + 0.5F)) << 8) & 0xFFFF;
+ aGammaRamp[1][i] = (((FxU16)((pow(i/255.0F, 1.0F/gammaG)) * 255.0F + 0.5F)) << 8) & 0xFFFF;
+ aGammaRamp[2][i] = (((FxU16)((pow(i/255.0F, 1.0F/gammaB)) * 255.0F + 0.5F)) << 8) & 0xFFFF;
+ }
+ CorrectGamma(aGammaRamp);
+}
+
+FX_ENTRY void FX_CALL
+grDitherMode( GrDitherMode_t mode )
+{
+ display_warning("grDitherMode");
+}
+
+void grChromaRangeExt(GrColor_t color0, GrColor_t color1, FxU32 mode)
+{
+ display_warning("grChromaRangeExt");
+}
+
+void grChromaRangeModeExt(GrChromakeyMode_t mode)
+{
+ display_warning("grChromaRangeModeExt");
+}
+
+void grTexChromaRangeExt(GrChipID_t tmu, GrColor_t color0, GrColor_t color1, GrTexChromakeyMode_t mode)
+{
+ display_warning("grTexChromaRangeExt");
+}
+
+void grTexChromaModeExt(GrChipID_t tmu, GrChromakeyMode_t mode)
+{
+ display_warning("grTexChromaRangeModeExt");
+}
+
+// VP debug
+#ifdef VPDEBUG
+int dumping = 0;
+static int tl_i;
+static int tl[10240];
+
+void dump_start()
+{
+ static int init;
+ if (!init) {
+ init = 1;
+ ilInit();
+ ilEnable(IL_FILE_OVERWRITE);
+ }
+ dumping = 1;
+ tl_i = 0;
+}
+
+void dump_stop()
+{
+ if (!dumping) return;
+
+ int i, j;
+ for (i=0; i<nb_fb; i++) {
+ dump_tex(fbs[i].texid);
+ }
+ dump_tex(default_texture);
+ dump_tex(depth_texture);
+
+ dumping = 0;
+
+ glReadBuffer(GL_FRONT);
+ glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, frameBuffer);
+ ilTexImage(width, height, 1, 4, IL_RGBA, IL_UNSIGNED_BYTE, frameBuffer);
+ ilSaveImage("dump/framecolor.png");
+ glReadPixels(0, 0, width, height, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, depthBuffer);
+ // FILE * fp = fopen("glide_depth1.bin", "rb");
+ // fread(depthBuffer, 2, width*height, fp);
+ // fclose(fp);
+ for (j=0; j<height; j++) {
+ for (i=0; i<width; i++) {
+ //uint16_t d = ( (uint16_t *)depthBuffer )[i+(height-1-j)*width]/2 + 0x8000;
+ uint16_t d = ( (uint16_t *)depthBuffer )[i+j*width];
+ uint32_t c = ( (uint32_t *)frameBuffer )[i+j*width];
+ ( (unsigned char *)frameBuffer )[(i+j*width)*3] = d&0xff;
+ ( (unsigned char *)frameBuffer )[(i+j*width)*3+1] = d>>8;
+ ( (unsigned char *)frameBuffer )[(i+j*width)*3+2] = c&0xff;
+ }
+ }
+ ilTexImage(width, height, 1, 3, IL_RGB, IL_UNSIGNED_BYTE, frameBuffer);
+ ilSaveImage("dump/framedepth.png");
+
+ for (i=0; i<tl_i; i++) {
+ glBindTexture(GL_TEXTURE_2D, tl[i]);
+ GLint w, h, fmt;
+ glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &w);
+ glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &h);
+ glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &fmt);
+ fprintf(stderr, "Texture %d %dx%d fmt %x\n", tl[i], (int)w, (int)h, (int) fmt);
+
+ uint32_t * pixels = (uint32_t *) malloc(w*h*4);
+ // 0x1902 is another constant meaning GL_DEPTH_COMPONENT
+ // (but isn't defined in gl's headers !!)
+ if (fmt != GL_DEPTH_COMPONENT && fmt != 0x1902) {
+ glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
+ ilTexImage(w, h, 1, 4, IL_RGBA, IL_UNSIGNED_BYTE, pixels);
+ } else {
+ glGetTexImage(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, pixels);
+ int i;
+ for (i=0; i<w*h; i++)
+ ((unsigned char *)frameBuffer)[i] = ((unsigned short *)pixels)[i]/256;
+ ilTexImage(w, h, 1, 1, IL_LUMINANCE, IL_UNSIGNED_BYTE, frameBuffer);
+ }
+ char name[128];
+ // sprintf(name, "mkdir -p dump ; rm -f dump/tex%04d.png", i);
+ // system(name);
+ sprintf(name, "dump/tex%04d.png", i);
+ fprintf(stderr, "Writing '%s'\n", name);
+ ilSaveImage(name);
+
+ // SDL_FreeSurface(surf);
+ free(pixels);
+ }
+ glBindTexture(GL_TEXTURE_2D, default_texture);
+}
+
+void dump_tex(int id)
+{
+ if (!dumping) return;
+
+ int n;
+ // yes, it's inefficient
+ for (n=0; n<tl_i; n++)
+ if (tl[n] == id)
+ return;
+
+ tl[tl_i++] = id;
+
+ int i = tl_i-1;
+}
+
+#endif