21e16b75d783f759d57f7c4a9e6f28ede083d208
[mupen64plus-pandora.git] / source / gles2glide64 / src / Glitch64 / glitchmain.cpp
1 /*
2 * Glide64 - Glide video plugin for Nintendo 64 emulators.
3 * Copyright (c) 2002  Dave2001
4 * Copyright (c) 2003-2009  Sergey 'Gonetz' Lipski
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 */
20
21 #define SAVE_CBUFFER
22
23 #ifdef _WIN32
24 #include <windows.h>
25 #include <commctrl.h>
26 #else
27 #include <stdint.h>
28 #include <stdarg.h>
29 #include <string.h>
30 #include <SDL.h>
31 #endif // _WIN32
32 #include <stdlib.h>
33 #include <stdio.h>
34 #include <iostream>
35 #include <fstream>
36 #include <math.h>
37 #include "glide.h"
38 #include "g3ext.h"
39 #include "main.h"
40 #include "m64p.h"
41
42 #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); }
43
44 #ifdef VPDEBUG
45 #include <IL/il.h>
46 #endif
47
48 #include "../Glide64/ticks.h"   //*SEB*
49
50 extern void (*renderCallback)(int);
51
52 wrapper_config config = {0, 0, 0, 0};
53 int screen_width, screen_height;
54
55 /*
56 static inline void opt_glCopyTexImage2D( GLenum target,
57                                         GLint level,
58                                         GLenum internalFormat,
59                                         GLint x,
60                                         GLint y,
61                                         GLsizei width,
62                                         GLsizei height,
63                                         GLint border )
64
65 {
66   int w, h, fmt;
67   glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &w);
68   glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &h);
69   glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &fmt);
70   //printf("copyteximage %dx%d fmt %x oldfmt %x\n", width, height, internalFormat, fmt);
71   if (w == (int) width && h == (int) height && fmt == (int) internalFormat) {
72     if (x+width >= screen_width) {
73       width = screen_width - x;
74       //printf("resizing w --> %d\n", width);
75     }
76     if (y+height >= screen_height+viewport_offset) {
77       height = screen_height+viewport_offset - y;
78       //printf("resizing h --> %d\n", height);
79     }
80     glCopyTexSubImage2D(target, level, 0, 0, x, y, width, height);
81   } else {
82     //printf("copyteximage %dx%d fmt %x old %dx%d oldfmt %x\n", width, height, internalFormat, w, h, fmt);
83     //       glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height, 0, internalFormat, GL_UNSIGNED_BYTE, 0);
84     //       glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &fmt);
85     //       printf("--> %dx%d newfmt %x\n", width, height, fmt);
86     glCopyTexImage2D(target, level, internalFormat, x, y, width, height, border);
87   }
88 }
89 #define glCopyTexImage2D opt_glCopyTexImage2D
90 */
91
92
93 #ifdef _WIN32
94 PFNGLACTIVETEXTUREARBPROC glActiveTextureARB;
95 PFNGLBLENDFUNCSEPARATEEXTPROC glBlendFuncSeparateEXT;
96 PFNGLMULTITEXCOORD2FARBPROC glMultiTexCoord2fARB;
97 PFNGLFOGCOORDFPROC glFogCoordfEXT;
98
99 PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB;
100
101 PFNGLBINDFRAMEBUFFEREXTPROC glBindFramebufferEXT;
102 PFNGLFRAMEBUFFERTEXTURE2DEXTPROC glFramebufferTexture2DEXT;
103 PFNGLGENFRAMEBUFFERSEXTPROC glGenFramebuffersEXT;
104 PFNGLBINDRENDERBUFFEREXTPROC glBindRenderbufferEXT = NULL;
105 PFNGLDELETERENDERBUFFERSEXTPROC glDeleteRenderbuffersEXT = NULL;
106 PFNGLGENRENDERBUFFERSEXTPROC glGenRenderbuffersEXT = NULL;
107 PFNGLRENDERBUFFERSTORAGEEXTPROC glRenderbufferStorageEXT = NULL;
108 PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glFramebufferRenderbufferEXT = NULL;
109 PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC glCheckFramebufferStatusEXT;
110 PFNGLDELETEFRAMEBUFFERSEXTPROC glDeleteFramebuffersEXT;
111
112 PFNGLCREATESHADEROBJECTARBPROC glCreateShaderObjectARB;
113 PFNGLSHADERSOURCEARBPROC glShaderSourceARB;
114 PFNGLCOMPILESHADERARBPROC glCompileShaderARB;
115 PFNGLCREATEPROGRAMOBJECTARBPROC glCreateProgramObjectARB;
116 PFNGLATTACHOBJECTARBPROC glAttachObjectARB;
117 PFNGLLINKPROGRAMARBPROC glLinkProgramARB;
118 PFNGLUSEPROGRAMOBJECTARBPROC glUseProgramObjectARB;
119 PFNGLGETUNIFORMLOCATIONARBPROC glGetUniformLocationARB;
120 PFNGLUNIFORM1IARBPROC glUniform1iARB;
121 PFNGLUNIFORM4IARBPROC glUniform4iARB;
122 PFNGLUNIFORM4FARBPROC glUniform4fARB;
123 PFNGLUNIFORM1FARBPROC glUniform1fARB;
124 PFNGLDELETEOBJECTARBPROC glDeleteObjectARB;
125 PFNGLGETINFOLOGARBPROC glGetInfoLogARB;
126 PFNGLGETOBJECTPARAMETERIVARBPROC glGetObjectParameterivARB;
127 PFNGLSECONDARYCOLOR3FPROC glSecondaryColor3f;
128
129 // FXT1,DXT1,DXT5 support - Hiroshi Morii <koolsmoky(at)users.sourceforge.net>
130 // NOTE: Glide64 + GlideHQ use the following formats
131 // GL_COMPRESSED_RGB_S3TC_DXT1_EXT
132 // GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
133 // GL_COMPRESSED_RGB_FXT1_3DFX
134 // GL_COMPRESSED_RGBA_FXT1_3DFX
135 PFNGLCOMPRESSEDTEXIMAGE2DPROC glCompressedTexImage2DARB;
136 #endif // _WIN32
137
138
139
140 typedef struct
141 {
142   unsigned int address;
143   int width;
144   int height;
145   int fb_width;
146   int fb_height;
147   unsigned int fbid;
148   unsigned int zbid;
149   unsigned int texid;
150   int buff_clear;
151 } fb;
152
153 int nbTextureUnits;
154 int nbAuxBuffers, current_buffer;
155 int width, widtho, heighto, height;
156 int saved_width, saved_height;
157 int blend_func_separate_support;
158 int npot_support;
159 int fog_coord_support;
160 int render_to_texture = 0;
161 int texture_unit;
162 int use_fbo;
163 int buffer_cleared;
164 // ZIGGY
165 // to allocate a new static texture name, take the value (free_texture++)
166 int free_texture;
167 int default_texture; // the infamous "32*1024*1024" is now configurable
168 int current_texture;
169 int depth_texture, color_texture;
170 int glsl_support = 1;
171 int viewport_width, viewport_height, viewport_offset = 0, nvidia_viewport_hack = 0;
172 int save_w, save_h;
173 int lfb_color_fmt;
174 float invtex[2];
175 //Gonetz
176 int UMAmode = 0; //support for VSA-100 UMA mode;
177
178 #ifdef _WIN32
179 static HDC hDC = NULL;
180 static HGLRC hGLRC = NULL;
181 static HWND hToolBar = NULL;
182 static HWND hwnd_win = NULL;
183 static unsigned long windowedExStyle, windowedStyle;
184 #endif // _WIN32
185 static unsigned long fullscreen;
186 #ifdef _WIN32
187 static RECT windowedRect;
188 static HMENU windowedMenu;
189 #endif // _WIN32
190
191 static int savedWidtho, savedHeighto;
192 static int savedWidth, savedHeight;
193 unsigned int pBufferAddress;
194 static int pBufferFmt;
195 static int pBufferWidth, pBufferHeight;
196 static fb fbs[100];
197 static int nb_fb = 0;
198 static unsigned int curBufferAddr = 0;
199
200 struct TMU_USAGE { int min, max; } tmu_usage[2] = { {0xfffffff, 0}, {0xfffffff, 0} };
201
202 struct texbuf_t {
203   FxU32 start, end;
204   int fmt;
205 };
206 #define NB_TEXBUFS 128 // MUST be a power of two
207 static texbuf_t texbufs[NB_TEXBUFS];
208 static int texbuf_i;
209
210 unsigned short frameBuffer[2048*2048];
211 unsigned short depthBuffer[2048*2048];
212
213 //#define VOODOO1
214
215 void display_warning(const char *text, ...)
216 {
217   static int first_message = 100;
218   if (first_message)
219   {
220     char buf[4096];
221
222     va_list ap;
223
224     va_start(ap, text);
225     vsprintf(buf, text, ap);
226     va_end(ap);
227     first_message--;
228     LOGINFO(buf);
229   }
230 }
231
232 #ifdef _WIN32
233 void display_error()
234 {
235   LPVOID lpMsgBuf;
236   if (!FormatMessage(
237     FORMAT_MESSAGE_ALLOCATE_BUFFER |
238     FORMAT_MESSAGE_FROM_SYSTEM |
239     FORMAT_MESSAGE_IGNORE_INSERTS,
240     NULL,
241     GetLastError(),
242     MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
243     (LPTSTR) &lpMsgBuf,
244     0,
245     NULL ))
246   {
247     // Handle the error.
248     return;
249   }
250   // Process any inserts in lpMsgBuf.
251   // ...
252   // Display the string.
253   MessageBox( NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION );
254
255   // Free the buffer.
256   LocalFree( lpMsgBuf );
257 }
258 #endif // _WIN32
259
260 #ifdef LOGGING
261 char out_buf[256];
262 bool log_open = false;
263 std::ofstream log_file;
264
265 void OPEN_LOG()
266 {
267   if (!log_open)
268   {
269     log_file.open ("wrapper_log.txt", std::ios_base::out|std::ios_base::app);
270     log_open = true;
271   }
272 }
273
274 void CLOSE_LOG()
275 {
276   if (log_open)
277   {
278     log_file.close();
279     log_open = false;
280   }
281 }
282
283 void LOG(const char *text, ...)
284 {
285 #ifdef VPDEBUG
286   if (!dumping) return;
287 #endif
288         if (!log_open)
289     return;
290         va_list ap;
291         va_start(ap, text);
292         vsprintf(out_buf, text, ap);
293   log_file << out_buf;
294   log_file.flush();
295         va_end(ap);
296 }
297
298 class LogManager {
299 public:
300         LogManager() {
301                 OPEN_LOG();
302         }
303         ~LogManager() {
304                 CLOSE_LOG();
305         }
306 };
307
308 LogManager logManager;
309
310 #else // LOGGING
311 #define OPEN_LOG()
312 #define CLOSE_LOG()
313 //#define LOG
314 #endif // LOGGING
315
316 FX_ENTRY void FX_CALL
317 grSstOrigin(GrOriginLocation_t  origin)
318 {
319   LOG("grSstOrigin(%d)\r\n", origin);
320   if (origin != GR_ORIGIN_UPPER_LEFT)
321     display_warning("grSstOrigin : %x", origin);
322 }
323
324 FX_ENTRY void FX_CALL
325 grClipWindow( FxU32 minx, FxU32 miny, FxU32 maxx, FxU32 maxy )
326 {
327   LOG("grClipWindow(%d,%d,%d,%d)\r\n", minx, miny, maxx, maxy);
328
329   if (use_fbo && render_to_texture) {
330     if (int(minx) < 0) minx = 0;
331     if (int(miny) < 0) miny = 0;
332     if (maxx < minx) maxx = minx;
333     if (maxy < miny) maxy = miny;
334     glScissor(minx, miny, maxx - minx, maxy - miny);
335     glEnable(GL_SCISSOR_TEST);
336     return;
337   }
338
339   if (!use_fbo) {
340     int th = height;
341     if (th > screen_height)
342       th = screen_height;
343     maxy = th - maxy;
344     miny = th - miny;
345     FxU32 tmp = maxy; maxy = miny; miny = tmp;
346     if (maxx > (FxU32) width) maxx = width;
347     if (maxy > (FxU32) height) maxy = height;
348     if (int(minx) < 0) minx = 0;
349     if (int(miny) < 0) miny = 0;
350     if (maxx < minx) maxx = minx;
351     if (maxy < miny) maxy = miny;
352     glScissor(minx, miny+viewport_offset, maxx - minx, maxy - miny);
353     //printf("gl scissor %d %d %d %d\n", minx, miny, maxx, maxy);
354   } else {
355     glScissor(minx, (viewport_offset)+height-maxy, maxx - minx, maxy - miny);
356   }
357   glEnable(GL_SCISSOR_TEST);
358 }
359
360 FX_ENTRY void FX_CALL
361 grColorMask( FxBool rgb, FxBool a )
362 {
363   LOG("grColorMask(%d, %d)\r\n", rgb, a);
364   glColorMask(rgb, rgb, rgb, a);
365 }
366
367 FX_ENTRY void FX_CALL
368 grGlideInit( void )
369 {
370   LOG("grGlideInit()\r\n");
371 }
372
373 FX_ENTRY void FX_CALL
374 grSstSelect( int which_sst )
375 {
376   LOG("grSstSelect(%d)\r\n", which_sst);
377 }
378
379 int isExtensionSupported(const char *extension)
380 {
381   return 0;
382   const GLubyte *extensions = NULL;
383   const GLubyte *start;
384   GLubyte *where, *terminator;
385
386   where = (GLubyte *)strchr(extension, ' ');
387   if (where || *extension == '\0')
388     return 0;
389
390   extensions = glGetString(GL_EXTENSIONS);
391
392   start = extensions;
393   for (;;)
394   {
395     where = (GLubyte *) strstr((const char *) start, extension);
396     if (!where)
397       break;
398
399     terminator = where + strlen(extension);
400     if (where == start || *(where - 1) == ' ')
401       if (*terminator == ' ' || *terminator == '\0')
402         return 1;
403
404     start = terminator;
405   }
406
407   return 0;
408 }
409
410 #ifdef _WIN32
411 int isWglExtensionSupported(const char *extension)
412 {
413   const GLubyte *extensions = NULL;
414   const GLubyte *start;
415   GLubyte *where, *terminator;
416
417   where = (GLubyte *)strchr(extension, ' ');
418   if (where || *extension == '\0')
419     return 0;
420
421   extensions = (GLubyte*)wglGetExtensionsStringARB(wglGetCurrentDC());
422
423   start = extensions;
424   for (;;)
425   {
426     where = (GLubyte *) strstr((const char *) start, extension);
427     if (!where)
428       break;
429
430     terminator = where + strlen(extension);
431     if (where == start || *(where - 1) == ' ')
432       if (*terminator == ' ' || *terminator == '\0')
433         return 1;
434
435     start = terminator;
436   }
437
438   return 0;
439 }
440 #endif // _WIN32
441
442 #define GrPixelFormat_t int
443
444 FX_ENTRY GrContext_t FX_CALL
445 grSstWinOpenExt(
446                 HWND                 hWnd,
447                 GrScreenResolution_t screen_resolution,
448                 GrScreenRefresh_t    refresh_rate,
449                 GrColorFormat_t      color_format,
450                 GrOriginLocation_t   origin_location,
451                 GrPixelFormat_t      pixelformat,
452                 int                  nColBuffers,
453                 int                  nAuxBuffers)
454 {
455   LOG("grSstWinOpenExt(%d, %d, %d, %d, %d, %d %d)\r\n", hWnd, screen_resolution, refresh_rate, color_format, origin_location, nColBuffers, nAuxBuffers);
456   return grSstWinOpen(hWnd, screen_resolution, refresh_rate, color_format,
457     origin_location, nColBuffers, nAuxBuffers);
458 }
459
460 #ifdef WIN32
461 # include <fcntl.h>
462 # ifndef ATTACH_PARENT_PROCESS
463 #  define ATTACH_PARENT_PROCESS ((FxU32)-1)
464 # endif
465 #endif
466
467 FX_ENTRY GrContext_t FX_CALL
468 grSstWinOpen(
469              HWND                 hWnd,
470              GrScreenResolution_t screen_resolution,
471              GrScreenRefresh_t    refresh_rate,
472              GrColorFormat_t      color_format,
473              GrOriginLocation_t   origin_location,
474              int                  nColBuffers,
475              int                  nAuxBuffers)
476 {
477   static int show_warning = 1;
478
479   // ZIGGY
480   // allocate static texture names
481   // the initial value should be big enough to support the maximal resolution
482   free_texture = 32*2048*2048;
483   default_texture = free_texture++;
484   color_texture = free_texture++;
485   depth_texture = free_texture++;
486
487   LOG("grSstWinOpen(%08lx, %d, %d, %d, %d, %d %d)\r\n", hWnd, screen_resolution&~0x80000000, refresh_rate, color_format, origin_location, nColBuffers, nAuxBuffers);
488
489 #ifdef _WIN32
490   if ((HWND)hWnd == NULL) hWnd = GetActiveWindow();
491   hwnd_win = (HWND)hWnd;
492 #endif // _WIN32
493   width = height = 0;
494
495   m64p_handle video_general_section;
496   printf("&ConfigOpenSection is %p\n", &ConfigOpenSection);
497   if (ConfigOpenSection("Video-General", &video_general_section) != M64ERR_SUCCESS)
498   {
499     printf("Could not open video settings");
500     return false;
501   }
502   width = ConfigGetParamInt(video_general_section, "ScreenWidth");
503   height = ConfigGetParamInt(video_general_section, "ScreenHeight");
504   fullscreen = ConfigGetParamBool(video_general_section, "Fullscreen");
505   int vsync = ConfigGetParamBool(video_general_section, "VerticalSync");
506   //viewport_offset = ((screen_resolution>>2) > 20) ? screen_resolution >> 2 : 20;
507   // ZIGGY viewport_offset is WIN32 specific, with SDL just set it to zero
508   viewport_offset = 0; //-10 //-20;
509
510   // ZIGGY not sure, but it might be better to let the system choose
511   CoreVideo_GL_SetAttribute(M64P_GL_DOUBLEBUFFER, 1);
512   CoreVideo_GL_SetAttribute(M64P_GL_SWAP_CONTROL, vsync);
513   CoreVideo_GL_SetAttribute(M64P_GL_BUFFER_SIZE, 16);
514   //   SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE, 32);
515   //   SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
516   //   SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
517   //   SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
518   //   SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
519   CoreVideo_GL_SetAttribute(M64P_GL_DEPTH_SIZE, 16);
520
521   printf("(II) Setting video mode %dx%d...\n", width, height);
522   if(CoreVideo_SetVideoMode(width, height, 0, fullscreen ? M64VIDEO_FULLSCREEN : M64VIDEO_WINDOWED, (m64p_video_flags) 0) != M64ERR_SUCCESS)
523   {
524     printf("(EE) Error setting videomode %dx%d\n", width, height);
525     return false;
526   }
527
528   char caption[500];
529 # ifdef _DEBUG
530   sprintf(caption, "Glide64mk2 debug");
531 # else // _DEBUG
532   sprintf(caption, "Glide64mk2");
533 # endif // _DEBUG
534   CoreVideo_SetCaption(caption);
535
536   glViewport(0, viewport_offset, width, height);
537   lfb_color_fmt = color_format;
538   if (origin_location != GR_ORIGIN_UPPER_LEFT) display_warning("origin must be in upper left corner");
539   if (nColBuffers != 2) display_warning("number of color buffer is not 2");
540   if (nAuxBuffers != 1) display_warning("number of auxiliary buffer is not 1");
541
542   if (isExtensionSupported("GL_ARB_texture_env_combine") == 0 &&
543     isExtensionSupported("GL_EXT_texture_env_combine") == 0 &&
544     show_warning)
545     display_warning("Your video card doesn't support GL_ARB_texture_env_combine extension");
546   if (isExtensionSupported("GL_ARB_multitexture") == 0 && show_warning)
547     display_warning("Your video card doesn't support GL_ARB_multitexture extension");
548   if (isExtensionSupported("GL_ARB_texture_mirrored_repeat") == 0 && show_warning)
549     display_warning("Your video card doesn't support GL_ARB_texture_mirrored_repeat extension");
550   show_warning = 0;
551
552 #ifdef _WIN32
553   glActiveTextureARB = (PFNGLACTIVETEXTUREARBPROC)wglGetProcAddress("glActiveTextureARB");
554   glMultiTexCoord2fARB = (PFNGLMULTITEXCOORD2FARBPROC)wglGetProcAddress("glMultiTexCoord2fARB");
555 #endif // _WIN32
556
557   nbTextureUnits = 4;
558   //glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &nbTextureUnits);
559   if (nbTextureUnits == 1) display_warning("You need a video card that has at least 2 texture units");
560
561   nbAuxBuffers = 4;
562   //glGetIntegerv(GL_AUX_BUFFERS, &nbAuxBuffers);
563   if (nbAuxBuffers > 0)
564     printf("Congratulations, you have %d auxilliary buffers, we'll use them wisely !\n", nbAuxBuffers);
565 #ifdef VOODOO1
566   nbTextureUnits = 2;
567 #endif
568
569   blend_func_separate_support = 1;
570   packed_pixels_support = 0;
571 /*
572   if (isExtensionSupported("GL_EXT_blend_func_separate") == 0)
573     blend_func_separate_support = 0;
574   else
575     blend_func_separate_support = 1;
576
577   if (isExtensionSupported("GL_EXT_packed_pixels") == 0)
578     packed_pixels_support = 0;
579   else {
580     printf("packed pixels extension used\n");
581     packed_pixels_support = 1;
582   }
583 */
584
585   if (isExtensionSupported("GL_ARB_texture_non_power_of_two") == 0)
586     npot_support = 0;
587   else {
588     printf("NPOT extension used\n");
589     npot_support = 1;
590   }
591
592 #ifdef _WIN32
593   glBlendFuncSeparateEXT = (PFNGLBLENDFUNCSEPARATEEXTPROC)wglGetProcAddress("glBlendFuncSeparateEXT");
594 #endif // _WIN32
595
596   if (isExtensionSupported("GL_EXT_fog_coord") == 0)
597     fog_coord_support = 0;
598   else
599     fog_coord_support = 1;
600
601 #ifdef _WIN32
602   glFogCoordfEXT = (PFNGLFOGCOORDFPROC)wglGetProcAddress("glFogCoordfEXT");
603 #endif // _WIN32
604
605 #ifdef _WIN32
606   wglGetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC)wglGetProcAddress("wglGetExtensionsStringARB");
607 #endif // _WIN32
608
609 #ifdef _WIN32
610   glBindFramebufferEXT = (PFNGLBINDFRAMEBUFFEREXTPROC)wglGetProcAddress("glBindFramebufferEXT");
611   glFramebufferTexture2DEXT = (PFNGLFRAMEBUFFERTEXTURE2DEXTPROC)wglGetProcAddress("glFramebufferTexture2DEXT");
612   glGenFramebuffersEXT = (PFNGLGENFRAMEBUFFERSEXTPROC)wglGetProcAddress("glGenFramebuffersEXT");
613   glCheckFramebufferStatusEXT = (PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC)wglGetProcAddress("glCheckFramebufferStatusEXT");
614   glDeleteFramebuffersEXT = (PFNGLDELETEFRAMEBUFFERSEXTPROC)wglGetProcAddress("glDeleteFramebuffersEXT");
615
616   glBindRenderbufferEXT = (PFNGLBINDRENDERBUFFEREXTPROC)wglGetProcAddress("glBindRenderbufferEXT");
617   glDeleteRenderbuffersEXT = (PFNGLDELETERENDERBUFFERSEXTPROC)wglGetProcAddress("glDeleteRenderbuffersEXT");
618   glGenRenderbuffersEXT = (PFNGLGENRENDERBUFFERSEXTPROC)wglGetProcAddress("glGenRenderbuffersEXT");
619   glRenderbufferStorageEXT = (PFNGLRENDERBUFFERSTORAGEEXTPROC)wglGetProcAddress("glRenderbufferStorageEXT");
620   glFramebufferRenderbufferEXT = (PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC)wglGetProcAddress("glFramebufferRenderbufferEXT");
621   use_fbo = config.fbo && (glFramebufferRenderbufferEXT != NULL);
622 #else
623   use_fbo = config.fbo;
624 #endif // _WIN32
625
626   LOGINFO("use_fbo %d\n", use_fbo);
627
628   if (isExtensionSupported("GL_ARB_shading_language_100") &&
629     isExtensionSupported("GL_ARB_shader_objects") &&
630     isExtensionSupported("GL_ARB_fragment_shader") &&
631     isExtensionSupported("GL_ARB_vertex_shader"))
632   {
633
634 #ifdef _WIN32
635     glCreateShaderObjectARB = (PFNGLCREATESHADEROBJECTARBPROC)wglGetProcAddress("glCreateShaderObjectARB");
636     glShaderSourceARB = (PFNGLSHADERSOURCEARBPROC)wglGetProcAddress("glShaderSourceARB");
637     glCompileShaderARB = (PFNGLCOMPILESHADERARBPROC)wglGetProcAddress("glCompileShaderARB");
638     glCreateProgramObjectARB = (PFNGLCREATEPROGRAMOBJECTARBPROC)wglGetProcAddress("glCreateProgramObjectARB");
639     glAttachObjectARB = (PFNGLATTACHOBJECTARBPROC)wglGetProcAddress("glAttachObjectARB");
640     glLinkProgramARB = (PFNGLLINKPROGRAMARBPROC)wglGetProcAddress("glLinkProgramARB");
641     glUseProgramObjectARB = (PFNGLUSEPROGRAMOBJECTARBPROC)wglGetProcAddress("glUseProgramObjectARB");
642     glGetUniformLocationARB = (PFNGLGETUNIFORMLOCATIONARBPROC)wglGetProcAddress("glGetUniformLocationARB");
643     glUniform1iARB = (PFNGLUNIFORM1IARBPROC)wglGetProcAddress("glUniform1iARB");
644     glUniform4iARB = (PFNGLUNIFORM4IARBPROC)wglGetProcAddress("glUniform4iARB");
645     glUniform4fARB = (PFNGLUNIFORM4FARBPROC)wglGetProcAddress("glUniform4fARB");
646     glUniform1fARB = (PFNGLUNIFORM1FARBPROC)wglGetProcAddress("glUniform1fARB");
647     glDeleteObjectARB = (PFNGLDELETEOBJECTARBPROC)wglGetProcAddress("glDeleteObjectARB");
648     glGetInfoLogARB = (PFNGLGETINFOLOGARBPROC)wglGetProcAddress("glGetInfoLogARB");
649     glGetObjectParameterivARB = (PFNGLGETOBJECTPARAMETERIVARBPROC)wglGetProcAddress("glGetObjectParameterivARB");
650
651     glSecondaryColor3f = (PFNGLSECONDARYCOLOR3FPROC)wglGetProcAddress("glSecondaryColor3f");
652 #endif // _WIN32
653   }
654
655   if (isExtensionSupported("GL_EXT_texture_compression_s3tc") == 0  && show_warning)
656     display_warning("Your video card doesn't support GL_EXT_texture_compression_s3tc extension");
657   if (isExtensionSupported("GL_3DFX_texture_compression_FXT1") == 0  && show_warning)
658     display_warning("Your video card doesn't support GL_3DFX_texture_compression_FXT1 extension");
659
660 #ifdef _WIN32
661   glCompressedTexImage2DARB = (PFNGLCOMPRESSEDTEXIMAGE2DPROC)wglGetProcAddress("glCompressedTexImage2DARB");
662 #endif
663 /*SEB*/
664   glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
665   glPixelStorei(GL_PACK_ALIGNMENT, 1);
666
667
668 #ifdef _WIN32
669   glViewport(0, viewport_offset, width, height);
670   viewport_width = width;
671   viewport_height = height;
672   nvidia_viewport_hack = 1;
673 #else
674   glViewport(0, viewport_offset, width, height);
675   viewport_width = width;
676   viewport_height = height;
677 #endif // _WIN32
678
679   //   void do_benchmarks();
680   //   do_benchmarks();
681
682   // VP try to resolve z precision issues
683 //  glMatrixMode(GL_MODELVIEW);
684 //  glLoadIdentity();
685 //  glTranslatef(0, 0, 1-zscale);
686 //  glScalef(1, 1, zscale);
687
688   widtho = width/2;
689   heighto = height/2;
690
691   pBufferWidth = pBufferHeight = -1;
692
693   current_buffer = GL_BACK;
694
695   texture_unit = GL_TEXTURE0;
696
697   {
698     int i;
699     for (i=0; i<NB_TEXBUFS; i++)
700       texbufs[i].start = texbufs[i].end = 0xffffffff;
701   }
702
703   if (!use_fbo && nbAuxBuffers == 0) {
704     // create the framebuffer saving texture
705     int w = width, h = height;
706     glBindTexture(GL_TEXTURE_2D, color_texture);
707     if (!npot_support) {
708       w = h = 1;
709       while (w<width) w*=2;
710       while (h<height) h*=2;
711     }
712     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
713     glBindTexture(GL_TEXTURE_2D, 0);
714     save_w = save_h = 0;
715   }
716
717   void FindBestDepthBias();
718   FindBestDepthBias();
719
720   init_geometry();
721   init_textures();
722   init_combiner();
723
724 /*
725   // Aniso filter check
726   if (config.anisofilter > 0 )
727     glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &largest_supported_anisotropy);
728
729   // ATI hack - certain texture formats are slow on ATI?
730   // Hmm, perhaps the internal format need to be specified explicitly...
731   {
732     GLint ifmt;
733     glTexImage2D(GL_PROXY_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, NULL);
734     glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &ifmt);
735     if (ifmt != GL_RGB5_A1) {
736       display_warning("ATI SUCKS %x\n", ifmt);
737       ati_sucks = 1;
738     } else
739       ati_sucks = 0;
740   }
741 */
742
743   return 1;
744 }
745
746 FX_ENTRY void FX_CALL
747 grGlideShutdown( void )
748 {
749   LOG("grGlideShutdown\r\n");
750 }
751
752 FX_ENTRY FxBool FX_CALL
753 grSstWinClose( GrContext_t context )
754 {
755   int i, clear_texbuff = use_fbo;
756   LOG("grSstWinClose(%d)\r\n", context);
757
758   for (i=0; i<2; i++) {
759     tmu_usage[i].min = 0xfffffff;
760     tmu_usage[i].max = 0;
761     invtex[i] = 0;
762   }
763
764   free_combiners();
765 #ifndef WIN32
766   try // I don't know why, but opengl can be killed before this function call when emulator is closed (Gonetz).
767     // 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.
768   {
769     if (use_fbo)
770       glBindFramebuffer( GL_FRAMEBUFFER, 0 );
771   }
772   catch (...)
773   {
774     clear_texbuff = 0;
775   }
776
777   if (clear_texbuff)
778   {
779     for (i=0; i<nb_fb; i++)
780     {
781       glDeleteTextures( 1, &(fbs[i].texid) );
782       glDeleteFramebuffers( 1, &(fbs[i].fbid) );
783       glDeleteRenderbuffers( 1, &(fbs[i].zbid) );
784     }
785   }
786 #endif
787   nb_fb = 0;
788
789   free_textures();
790 #ifndef WIN32
791   // ZIGGY for some reasons, Pj64 doesn't like remove_tex on exit
792   remove_tex(0, 0xfffffff);
793 #endif
794
795   //*/
796 #ifdef _WIN32
797   if (hGLRC)
798   {
799     wglMakeCurrent(hDC,NULL);
800     wglDeleteContext(hGLRC);
801     hGLRC = NULL;
802   }
803   if (fullscreen)
804   {
805     ChangeDisplaySettings(NULL, 0);
806     SetWindowPos(hwnd_win, NULL,
807       windowedRect.left, windowedRect.top,
808       0, 0,
809       SWP_NOZORDER | SWP_NOSIZE);
810     SetWindowLong(hwnd_win, GWL_STYLE, windowedStyle);
811     SetWindowLong(hwnd_win, GWL_EXSTYLE, windowedExStyle);
812     if (windowedMenu) SetMenu(hwnd_win, windowedMenu);
813     fullscreen = 0;
814   }
815 #else
816   CoreVideo_Quit();
817   //SDL_QuitSubSystem(SDL_INIT_VIDEO);
818   //sleep(2);
819 #endif
820   return FXTRUE;
821 }
822
823 FX_ENTRY void FX_CALL grTextureBufferExt( GrChipID_t            tmu,
824                                          FxU32                          startAddress,
825                                          GrLOD_t                        lodmin,
826                                          GrLOD_t                        lodmax,
827                                          GrAspectRatio_t        aspect,
828                                          GrTextureFormat_t      fmt,
829                                          FxU32                          evenOdd)
830 {
831   int i;
832   static int fbs_init = 0;
833
834   LOG("grTextureBufferExt(%d, %d, %d, %d %d, %d, %d)\r\n", tmu, startAddress, lodmin, lodmax, aspect, fmt, evenOdd);
835   if (lodmin != lodmax) display_warning("grTextureBufferExt : loading more than one LOD");
836   if (!use_fbo) {
837
838     if (!render_to_texture) { //initialization
839       return;
840     }
841
842     render_to_texture = 2;
843
844     if (aspect < 0)
845     {
846       pBufferHeight = 1 << lodmin;
847       pBufferWidth = pBufferHeight >> -aspect;
848     }
849     else
850     {
851       pBufferWidth = 1 << lodmin;
852       pBufferHeight = pBufferWidth >> aspect;
853     }
854
855     if (curBufferAddr && startAddress+1 != curBufferAddr)
856       updateTexture();
857 #ifdef SAVE_CBUFFER
858     //printf("saving %dx%d\n", pBufferWidth, pBufferHeight);
859     // save color buffer
860     if (nbAuxBuffers > 0) {
861       //glDrawBuffer(GL_AUX0);
862       //current_buffer = GL_AUX0;
863     } else {
864       int tw, th;
865       if (pBufferWidth < screen_width)
866         tw = pBufferWidth;
867       else
868         tw = screen_width;
869       if (pBufferHeight < screen_height)
870         th = pBufferHeight;
871       else
872         th = screen_height;
873       //glReadBuffer(GL_BACK);
874       glActiveTexture(texture_unit);
875       glBindTexture(GL_TEXTURE_2D, color_texture);
876       // save incrementally the framebuffer
877       if (save_w) {
878         if (tw > save_w && th > save_h) {
879           glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, save_h,
880             0, viewport_offset+save_h, tw, th-save_h);
881           glCopyTexSubImage2D(GL_TEXTURE_2D, 0, save_w, 0,
882             save_w, viewport_offset, tw-save_w, save_h);
883           save_w = tw;
884           save_h = th;
885         } else if (tw > save_w) {
886           glCopyTexSubImage2D(GL_TEXTURE_2D, 0, save_w, 0,
887             save_w, viewport_offset, tw-save_w, save_h);
888           save_w = tw;
889         } else if (th > save_h) {
890           glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, save_h,
891             0, viewport_offset+save_h, save_w, th-save_h);
892           save_h = th;
893         }
894       } else {
895         glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0,
896           0, viewport_offset, tw, th);
897         save_w = tw;
898         save_h = th;
899       }
900       glBindTexture(GL_TEXTURE_2D, default_texture);
901     }
902 #endif
903
904     if (startAddress+1 != curBufferAddr ||
905       (curBufferAddr == 0L && nbAuxBuffers == 0))
906       buffer_cleared = 0;
907
908     curBufferAddr = pBufferAddress = startAddress+1;
909     pBufferFmt = fmt;
910
911     int rtmu = startAddress < grTexMinAddress(GR_TMU1)? 0 : 1;
912     int size = pBufferWidth*pBufferHeight*2; //grTexFormatSize(fmt);
913     if ((unsigned int) tmu_usage[rtmu].min > pBufferAddress)
914       tmu_usage[rtmu].min = pBufferAddress;
915     if ((unsigned int) tmu_usage[rtmu].max < pBufferAddress+size)
916       tmu_usage[rtmu].max = pBufferAddress+size;
917         //printf("tmu %d usage now %gMb - %gMb\n",
918     //      rtmu, tmu_usage[rtmu].min/1024.0f, tmu_usage[rtmu].max/1024.0f);
919
920
921     width = pBufferWidth;
922     height = pBufferHeight;
923
924     widtho = width/2;
925     heighto = height/2;
926
927     // this could be improved, but might be enough as long as the set of
928     // texture buffer addresses stay small
929     for (i=(texbuf_i-1)&(NB_TEXBUFS-1) ; i!=texbuf_i; i=(i-1)&(NB_TEXBUFS-1))
930       if (texbufs[i].start == pBufferAddress)
931         break;
932     texbufs[i].start = pBufferAddress;
933     texbufs[i].end = pBufferAddress + size;
934     texbufs[i].fmt = fmt;
935     if (i == texbuf_i)
936       texbuf_i = (texbuf_i+1)&(NB_TEXBUFS-1);
937         //printf("texbuf %x fmt %x\n", pBufferAddress, fmt);
938
939     // ZIGGY it speeds things up to not delete the buffers
940     // a better thing would be to delete them *sometimes*
941     //   remove_tex(pBufferAddress+1, pBufferAddress + size);
942     add_tex(pBufferAddress);
943
944         //printf("viewport %dx%d\n", width, height);
945     if (height > screen_height) {
946       glViewport( 0, viewport_offset + screen_height - height, width, height);
947     } else
948       glViewport( 0, viewport_offset, width, height);
949
950     glScissor(0, viewport_offset, width, height);
951
952
953   } else {
954     if (!render_to_texture) //initialization
955     {
956       if(!fbs_init)
957       {
958         for(i=0; i<100; i++) fbs[i].address = 0;
959         fbs_init = 1;
960         nb_fb = 0;
961       }
962       return; //no need to allocate FBO if render buffer is not texture buffer
963     }
964
965     render_to_texture = 2;
966
967     if (aspect < 0)
968     {
969       pBufferHeight = 1 << lodmin;
970       pBufferWidth = pBufferHeight >> -aspect;
971     }
972     else
973     {
974       pBufferWidth = 1 << lodmin;
975       pBufferHeight = pBufferWidth >> aspect;
976     }
977     pBufferAddress = startAddress+1;
978
979     width = pBufferWidth;
980     height = pBufferHeight;
981
982     widtho = width/2;
983     heighto = height/2;
984
985     for (i=0; i<nb_fb; i++)
986     {
987       if (fbs[i].address == pBufferAddress)
988       {
989 //        if (fbs[i].width == width && fbs[i].height == height) //select already allocated FBO
990         if (fbs[i].width >= width && fbs[i].height >= height) //select already allocated FBO, or large enough
991         {
992 //unsigned int tticks = ticksGetTicks();
993           glBindFramebuffer( GL_FRAMEBUFFER, 0 );
994           glBindFramebuffer( GL_FRAMEBUFFER, fbs[i].fbid );
995           glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbs[i].texid, 0 );
996           glBindRenderbuffer( GL_RENDERBUFFER, fbs[i].zbid );
997           glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbs[i].zbid );
998           glViewport( 0, 0, width, height);
999           glScissor( 0, 0, width, height);
1000                   fbs[i].fb_width=width;
1001                   fbs[i].fb_height=height;
1002           if (fbs[i].buff_clear)
1003           {
1004             glDepthMask(1);
1005             glClear( GL_DEPTH_BUFFER_BIT ); //clear z-buffer only. we may need content, stored in the frame buffer
1006             fbs[i].buff_clear = 0;
1007           }
1008           CHECK_FRAMEBUFFER_STATUS();
1009           curBufferAddr = pBufferAddress;
1010 //printf("select existing fbo (%u ms)\n", ticksGetTicks()-tticks);
1011           return;
1012         }
1013         else //create new FBO at the same address, delete old one 
1014         {
1015 //unsigned int tticks = ticksGetTicks();
1016           glDeleteFramebuffers( 1, &(fbs[i].fbid) );
1017           glDeleteRenderbuffers( 1, &(fbs[i].zbid) );
1018           if (nb_fb > 1)
1019             memmove(&(fbs[i]), &(fbs[i+1]), sizeof(fb)*(nb_fb-i));
1020           nb_fb--;
1021 //printf("delete existing fbo (%u ms)\n", ticksGetTicks()-tticks);
1022           break;
1023         }
1024       }
1025     }
1026 //unsigned int tticks = ticksGetTicks();
1027     remove_tex(pBufferAddress, pBufferAddress + width*height*2/*grTexFormatSize(fmt)*/);
1028 //printf("delete texture (%u ms)\n", ticksGetTicks()-tticks);
1029     //create new FBO
1030     glGenFramebuffers( 1, &(fbs[nb_fb].fbid) );
1031     glGenRenderbuffers( 1, &(fbs[nb_fb].zbid) );
1032     glBindRenderbuffer( GL_RENDERBUFFER, fbs[nb_fb].zbid );
1033     glRenderbufferStorage( GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height);
1034     fbs[nb_fb].address = pBufferAddress;
1035     fbs[nb_fb].width = width;
1036     fbs[nb_fb].height = height;
1037     fbs[nb_fb].fb_width = width;
1038     fbs[nb_fb].fb_height = height;
1039     fbs[nb_fb].texid = pBufferAddress;
1040     fbs[nb_fb].buff_clear = 0;
1041     add_tex(fbs[nb_fb].texid);
1042     glBindTexture(GL_TEXTURE_2D, fbs[nb_fb].texid);
1043     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0,
1044       GL_RGB, GL_UNSIGNED_BYTE, NULL);
1045     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
1046     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
1047
1048     glBindFramebuffer( GL_FRAMEBUFFER, fbs[nb_fb].fbid);
1049     glFramebufferTexture2D(GL_FRAMEBUFFER,
1050       GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbs[nb_fb].texid, 0);
1051     glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbs[nb_fb].zbid );
1052     glViewport(0,0,width,height);
1053     glScissor(0,0,width,height);
1054     glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
1055     glDepthMask(1);
1056     glClear( GL_DEPTH_BUFFER_BIT );
1057     CHECK_FRAMEBUFFER_STATUS();
1058     curBufferAddr = pBufferAddress;
1059     nb_fb++;
1060 //printf("create new fbo=fb[%i] (%u ms)\n", nb_fb-1, ticksGetTicks()-tticks);
1061   }
1062 }
1063
1064 int CheckTextureBufferFormat(GrChipID_t tmu, FxU32 startAddress, GrTexInfo *info )
1065 {
1066   int found, i;
1067   if (!use_fbo) {
1068     for (found=i=0; i<2; i++)
1069       if ((FxU32) tmu_usage[i].min <= startAddress && (FxU32) tmu_usage[i].max > startAddress) {
1070         //printf("tmu %d == framebuffer %x\n", tmu, startAddress);
1071         found = 1;
1072         break;
1073       }
1074   } else {
1075     found = i = 0;
1076     while (i < nb_fb)
1077     {
1078       unsigned int end = fbs[i].address + fbs[i].fb_width*fbs[i].fb_height*2;
1079       if (startAddress >= fbs[i].address &&  startAddress < end)
1080       {
1081         found = 1;
1082         break;
1083       }
1084       i++;
1085     }
1086   }
1087
1088   if (!use_fbo && found) {
1089     int tw, th, rh, cw, ch;
1090     if (info->aspectRatioLog2 < 0)
1091     {
1092       th = 1 << info->largeLodLog2;
1093       tw = th >> -info->aspectRatioLog2;
1094     }
1095     else
1096     {
1097       tw = 1 << info->largeLodLog2;
1098       th = tw >> info->aspectRatioLog2;
1099     }
1100
1101     if (info->aspectRatioLog2 < 0)
1102     {
1103       ch = 256;
1104       cw = ch >> -info->aspectRatioLog2;
1105     }
1106     else
1107     {
1108       cw = 256;
1109       ch = cw >> info->aspectRatioLog2;
1110     }
1111
1112     if (use_fbo || th < screen_height)
1113       rh = th;
1114     else
1115       rh = screen_height;
1116
1117     //printf("th %d rh %d ch %d\n", th, rh, ch);
1118
1119     invtex[tmu] = 1.0f - (th - rh) / (float)th;
1120   } else
1121     invtex[tmu] = 0;
1122
1123   if (info->format == GR_TEXFMT_ALPHA_INTENSITY_88 ) {
1124     if (!found) {
1125       return 0;
1126     }
1127     if(tmu == 0)
1128     {
1129       if(blackandwhite1 != found)
1130       {
1131         blackandwhite1 = found;
1132         need_to_compile = 1;
1133       }
1134     }
1135     else
1136     {
1137       if(blackandwhite0 != found)
1138       {
1139         blackandwhite0 = found;
1140         need_to_compile = 1;
1141       }
1142     }
1143     return 1;
1144   }
1145   return 0;
1146
1147 }
1148
1149
1150 FX_ENTRY void FX_CALL
1151 grTextureAuxBufferExt( GrChipID_t tmu,
1152                       FxU32      startAddress,
1153                       GrLOD_t    thisLOD,
1154                       GrLOD_t    largeLOD,
1155                       GrAspectRatio_t aspectRatio,
1156                       GrTextureFormat_t format,
1157                       FxU32      odd_even_mask )
1158 {
1159   LOG("grTextureAuxBufferExt(%d, %d, %d, %d %d, %d, %d)\r\n", tmu, startAddress, thisLOD, largeLOD, aspectRatio, format, odd_even_mask);
1160   //display_warning("grTextureAuxBufferExt");
1161 }
1162
1163 FX_ENTRY void FX_CALL grAuxBufferExt( GrBuffer_t buffer );
1164
1165 FX_ENTRY GrProc FX_CALL
1166 grGetProcAddress( char *procName )
1167 {
1168   LOG("grGetProcAddress(%s)\r\n", procName);
1169   if(!strcmp(procName, "grSstWinOpenExt"))
1170     return (GrProc)grSstWinOpenExt;
1171   if(!strcmp(procName, "grTextureBufferExt"))
1172     return (GrProc)grTextureBufferExt;
1173   if(!strcmp(procName, "grChromaRangeExt"))
1174     return (GrProc)grChromaRangeExt;
1175   if(!strcmp(procName, "grChromaRangeModeExt"))
1176     return (GrProc)grChromaRangeModeExt;
1177   if(!strcmp(procName, "grTexChromaRangeExt"))
1178     return (GrProc)grTexChromaRangeExt;
1179   if(!strcmp(procName, "grTexChromaModeExt"))
1180     return (GrProc)grTexChromaModeExt;
1181   // ZIGGY framebuffer copy extension
1182   if(!strcmp(procName, "grFramebufferCopyExt"))
1183     return (GrProc)grFramebufferCopyExt;
1184   if(!strcmp(procName, "grColorCombineExt"))
1185     return (GrProc)grColorCombineExt;
1186   if(!strcmp(procName, "grAlphaCombineExt"))
1187     return (GrProc)grAlphaCombineExt;
1188   if(!strcmp(procName, "grTexColorCombineExt"))
1189     return (GrProc)grTexColorCombineExt;
1190   if(!strcmp(procName, "grTexAlphaCombineExt"))
1191     return (GrProc)grTexAlphaCombineExt;
1192   if(!strcmp(procName, "grConstantColorValueExt"))
1193     return (GrProc)grConstantColorValueExt;
1194   if(!strcmp(procName, "grTextureAuxBufferExt"))
1195     return (GrProc)grTextureAuxBufferExt;
1196   if(!strcmp(procName, "grAuxBufferExt"))
1197     return (GrProc)grAuxBufferExt;
1198   if(!strcmp(procName, "grWrapperFullScreenResolutionExt"))
1199     return (GrProc)grWrapperFullScreenResolutionExt;
1200   if(!strcmp(procName, "grConfigWrapperExt"))
1201     return (GrProc)grConfigWrapperExt;
1202   if(!strcmp(procName, "grKeyPressedExt"))
1203     return (GrProc)grKeyPressedExt;
1204   if(!strcmp(procName, "grQueryResolutionsExt"))
1205     return (GrProc)grQueryResolutionsExt;
1206   if(!strcmp(procName, "grGetGammaTableExt"))
1207     return (GrProc)grGetGammaTableExt;
1208   display_warning("grGetProcAddress : %s", procName);
1209   return 0;
1210 }
1211
1212 FX_ENTRY FxU32 FX_CALL
1213 grGet( FxU32 pname, FxU32 plength, FxI32 *params )
1214 {
1215   LOG("grGet(%d,%d)\r\n", pname, plength);
1216   switch(pname)
1217   {
1218   case GR_MAX_TEXTURE_SIZE:
1219     if (plength < 4 || params == NULL) return 0;
1220     params[0] = 2048;
1221     return 4;
1222     break;
1223   case GR_NUM_TMU:
1224     if (plength < 4 || params == NULL) return 0;
1225     if (!nbTextureUnits)
1226     {
1227       grSstWinOpen((unsigned long)NULL, GR_RESOLUTION_640x480 | 0x80000000, 0, GR_COLORFORMAT_ARGB,
1228         GR_ORIGIN_UPPER_LEFT, 2, 1);
1229       grSstWinClose(0);
1230     }
1231 #ifdef VOODOO1
1232     params[0] = 1;
1233 #else
1234     if (nbTextureUnits > 2)
1235       params[0] = 2;
1236     else
1237       params[0] = 1;
1238 #endif
1239     return 4;
1240     break;
1241   case GR_NUM_BOARDS:
1242   case GR_NUM_FB:
1243   case GR_REVISION_FB:
1244   case GR_REVISION_TMU:
1245     if (plength < 4 || params == NULL) return 0;
1246     params[0] = 1;
1247     return 4;
1248     break;
1249   case GR_MEMORY_FB:
1250     if (plength < 4 || params == NULL) return 0;
1251     params[0] = 16*1024*1024;
1252     return 4;
1253     break;
1254   case GR_MEMORY_TMU:
1255     if (plength < 4 || params == NULL) return 0;
1256     params[0] = 16*1024*1024;
1257     return 4;
1258     break;
1259   case GR_MEMORY_UMA:
1260     if (plength < 4 || params == NULL) return 0;
1261     params[0] = 16*1024*1024*nbTextureUnits;
1262     return 4;
1263     break;
1264   case GR_BITS_RGBA:
1265     if (plength < 16 || params == NULL) return 0;
1266     params[0] = 8;
1267     params[1] = 8;
1268     params[2] = 8;
1269     params[3] = 8;
1270     return 16;
1271     break;
1272   case GR_BITS_DEPTH:
1273     if (plength < 4 || params == NULL) return 0;
1274     params[0] = 16;
1275     return 4;
1276     break;
1277   case GR_BITS_GAMMA:
1278     if (plength < 4 || params == NULL) return 0;
1279     params[0] = 8;
1280     return 4;
1281     break;
1282   case GR_GAMMA_TABLE_ENTRIES:
1283     if (plength < 4 || params == NULL) return 0;
1284     params[0] = 256;
1285     return 4;
1286     break;
1287   case GR_FOG_TABLE_ENTRIES:
1288     if (plength < 4 || params == NULL) return 0;
1289     params[0] = 64;
1290     return 4;
1291     break;
1292   case GR_WDEPTH_MIN_MAX:
1293     if (plength < 8 || params == NULL) return 0;
1294     params[0] = 0;
1295     params[1] = 65528;
1296     return 8;
1297     break;
1298   case GR_ZDEPTH_MIN_MAX:
1299     if (plength < 8 || params == NULL) return 0;
1300     params[0] = 0;
1301     params[1] = 65535;
1302     return 8;
1303     break;
1304   case GR_LFB_PIXEL_PIPE:
1305     if (plength < 4 || params == NULL) return 0;
1306     params[0] = FXFALSE;
1307     return 4;
1308     break;
1309   case GR_MAX_TEXTURE_ASPECT_RATIO:
1310     if (plength < 4 || params == NULL) return 0;
1311     params[0] = 3;
1312     return 4;
1313     break;
1314   case GR_NON_POWER_OF_TWO_TEXTURES:
1315     if (plength < 4 || params == NULL) return 0;
1316     params[0] = FXFALSE;
1317     return 4;
1318     break;
1319   case GR_TEXTURE_ALIGN:
1320     if (plength < 4 || params == NULL) return 0;
1321     params[0] = 0;
1322     return 4;
1323     break;
1324   default:
1325     display_warning("unknown pname in grGet : %x", pname);
1326   }
1327   return 0;
1328 }
1329
1330 FX_ENTRY const char * FX_CALL
1331 grGetString( FxU32 pname )
1332 {
1333   LOG("grGetString(%d)\r\n", pname);
1334   switch(pname)
1335   {
1336   case GR_EXTENSION:
1337     {
1338       static char extension[] = "CHROMARANGE TEXCHROMA TEXMIRROR PALETTE6666 FOGCOORD EVOODOO TEXTUREBUFFER TEXUMA TEXFMT COMBINE GETGAMMA";
1339       return extension;
1340     }
1341     break;
1342   case GR_HARDWARE:
1343     {
1344       static char hardware[] = "Voodoo5 (tm)";
1345       return hardware;
1346     }
1347     break;
1348   case GR_VENDOR:
1349     {
1350       static char vendor[] = "3Dfx Interactive";
1351       return vendor;
1352     }
1353     break;
1354   case GR_RENDERER:
1355     {
1356       static char renderer[] = "Glide";
1357       return renderer;
1358     }
1359     break;
1360   case GR_VERSION:
1361     {
1362       static char version[] = "3.0";
1363       return version;
1364     }
1365     break;
1366   default:
1367     display_warning("unknown grGetString selector : %x", pname);
1368   }
1369   return NULL;
1370 }
1371
1372 static void render_rectangle(int texture_number,
1373                              int dst_x, int dst_y,
1374                              int src_width, int src_height,
1375                              int tex_width, int tex_height, int invert)
1376 {
1377   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);
1378   int vertexOffset_location;
1379   int textureSizes_location;
1380   static float data[] = {
1381     ((int)dst_x),                             //X 0
1382     invert*-((int)dst_y),                     //Y 0 
1383     0.0f,                                     //U 0 
1384     0.0f,                                     //V 0
1385
1386     ((int)dst_x),                             //X 1
1387     invert*-((int)dst_y + (int)src_height),   //Y 1
1388     0.0f,                                     //U 1
1389     (float)src_height / (float)tex_height,    //V 1
1390
1391     ((int)dst_x + (int)src_width), 
1392     invert*-((int)dst_y + (int)src_height),
1393     (float)src_width / (float)tex_width,
1394     (float)src_height / (float)tex_height,
1395
1396     ((int)dst_x),
1397     invert*-((int)dst_y),
1398     0.0f,
1399     0.0f
1400   };
1401
1402   vbo_disable();
1403   glDisableVertexAttribArray(COLOUR_ATTR);
1404   glDisableVertexAttribArray(TEXCOORD_1_ATTR);
1405   glDisableVertexAttribArray(FOG_ATTR);
1406
1407   glVertexAttribPointer(POSITION_ATTR,2,GL_FLOAT,false,2,data); //Position
1408   glVertexAttribPointer(TEXCOORD_0_ATTR,2,GL_FLOAT,false,2,&data[2]); //Tex
1409
1410   glEnableVertexAttribArray(COLOUR_ATTR);
1411   glEnableVertexAttribArray(TEXCOORD_1_ATTR);
1412   glEnableVertexAttribArray(FOG_ATTR);
1413
1414
1415   disable_textureSizes();
1416
1417   glDrawArrays(GL_TRIANGLE_STRIP,0,4);
1418   vbo_enable();
1419
1420
1421 /*
1422   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1423   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1424   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1425   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1426   glBegin(GL_QUADS);
1427   glMultiTexCoord2fARB(texture_number, 0.0f, 0.0f);
1428   glVertex2f(((int)dst_x - widtho) / (float)(width/2),
1429     invert*-((int)dst_y - heighto) / (float)(height/2));
1430   glMultiTexCoord2fARB(texture_number, 0.0f, (float)src_height / (float)tex_height);
1431   glVertex2f(((int)dst_x - widtho) / (float)(width/2),
1432     invert*-((int)dst_y + (int)src_height - heighto) / (float)(height/2));
1433   glMultiTexCoord2fARB(texture_number, (float)src_width / (float)tex_width, (float)src_height / (float)tex_height);
1434   glVertex2f(((int)dst_x + (int)src_width - widtho) / (float)(width/2),
1435     invert*-((int)dst_y + (int)src_height - heighto) / (float)(height/2));
1436   glMultiTexCoord2fARB(texture_number, (float)src_width / (float)tex_width, 0.0f);
1437   glVertex2f(((int)dst_x + (int)src_width - widtho) / (float)(width/2),
1438     invert*-((int)dst_y - heighto) / (float)(height/2));
1439   glMultiTexCoord2fARB(texture_number, 0.0f, 0.0f);
1440   glVertex2f(((int)dst_x - widtho) / (float)(width/2),
1441     invert*-((int)dst_y - heighto) / (float)(height/2));
1442   glEnd();
1443 */
1444
1445   compile_shader();
1446
1447   glEnable(GL_DEPTH_TEST);
1448   glEnable(GL_BLEND);
1449 }
1450
1451 void reloadTexture()
1452 {
1453   if (use_fbo || !render_to_texture || buffer_cleared)
1454     return;
1455
1456   LOG("reload texture %dx%d\n", width, height);
1457   //printf("reload texture %dx%d\n", width, height);
1458
1459   buffer_cleared = 1;
1460
1461   //glPushAttrib(GL_ALL_ATTRIB_BITS);
1462   glActiveTexture(texture_unit);
1463   glBindTexture(GL_TEXTURE_2D, pBufferAddress);
1464   //glDisable(GL_ALPHA_TEST);
1465   //glDrawBuffer(current_buffer);
1466   glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
1467   set_copy_shader();
1468   glDisable(GL_DEPTH_TEST);
1469   glDisable(GL_CULL_FACE);
1470   int w = 0, h = 0;
1471   if (height > screen_height) h = screen_height - height;
1472   render_rectangle(texture_unit,
1473     -w, -h,
1474     width,  height,
1475     width, height, -1);
1476   glBindTexture(GL_TEXTURE_2D, default_texture);
1477   //glPopAttrib();
1478 }
1479
1480 void updateTexture()
1481 {
1482   if (!use_fbo && render_to_texture == 2) {
1483     LOG("update texture %x\n", pBufferAddress);
1484     //printf("update texture %x\n", pBufferAddress);
1485
1486     // nothing changed, don't update the texture
1487     if (!buffer_cleared) {
1488       LOG("update cancelled\n", pBufferAddress);
1489       return;
1490     }
1491
1492     //glPushAttrib(GL_ALL_ATTRIB_BITS);
1493
1494     // save result of render to texture into actual texture
1495     //glReadBuffer(current_buffer);
1496     glActiveTexture(texture_unit);
1497     // ZIGGY
1498     // deleting the texture before resampling it increases speed on certain old
1499     // nvidia cards (geforce 2 for example), unfortunatly it slows down a lot
1500     // on newer cards.
1501     //glDeleteTextures( 1, &pBufferAddress );
1502     glBindTexture(GL_TEXTURE_2D, pBufferAddress);
1503     glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
1504       0, viewport_offset, width, height, 0);
1505
1506     glBindTexture(GL_TEXTURE_2D, default_texture);
1507     //glPopAttrib();
1508   }
1509 }
1510
1511 FX_ENTRY void FX_CALL grFramebufferCopyExt(int x, int y, int w, int h,
1512                                            int from, int to, int mode)
1513 {
1514   if (mode == GR_FBCOPY_MODE_DEPTH) {
1515
1516     int tw = 1, th = 1;
1517     if (npot_support) {
1518       tw = width; th = height;
1519     } else {
1520       while (tw < width) tw <<= 1;
1521       while (th < height) th <<= 1;
1522     }
1523
1524     if (from == GR_FBCOPY_BUFFER_BACK && to == GR_FBCOPY_BUFFER_FRONT) {
1525       //printf("save depth buffer %d\n", render_to_texture);
1526       // save the depth image in a texture
1527       //glReadBuffer(current_buffer);
1528       glBindTexture(GL_TEXTURE_2D, depth_texture);
1529       glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT,
1530         0, viewport_offset, tw, th, 0);
1531       glBindTexture(GL_TEXTURE_2D, default_texture);
1532       return;
1533     }
1534     if (from == GR_FBCOPY_BUFFER_FRONT && to == GR_FBCOPY_BUFFER_BACK) {
1535       //printf("writing to depth buffer %d\n", render_to_texture);
1536       //glPushAttrib(GL_ALL_ATTRIB_BITS);
1537       //glDisable(GL_ALPHA_TEST);
1538       //glDrawBuffer(current_buffer);
1539       glActiveTexture(texture_unit);
1540       glBindTexture(GL_TEXTURE_2D, depth_texture);
1541       glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
1542       set_depth_shader();
1543       glEnable(GL_DEPTH_TEST);
1544       glDepthFunc(GL_ALWAYS);
1545       glDisable(GL_CULL_FACE);
1546       render_rectangle(texture_unit,
1547         0, 0,
1548         width,  height,
1549         tw, th, -1);
1550       glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
1551       glBindTexture(GL_TEXTURE_2D, default_texture);
1552       //glPopAttrib();
1553       return;
1554     }
1555
1556   }
1557 }
1558
1559 FX_ENTRY void FX_CALL
1560 grRenderBuffer( GrBuffer_t buffer )
1561 {
1562 #ifdef _WIN32
1563   static HANDLE region = NULL;
1564   int realWidth = pBufferWidth, realHeight = pBufferHeight;
1565 #endif // _WIN32
1566   LOG("grRenderBuffer(%d)\r\n", buffer);
1567   //printf("grRenderBuffer(%d)\n", buffer);
1568
1569   switch(buffer)
1570   {
1571   case GR_BUFFER_BACKBUFFER:
1572     if(render_to_texture)
1573     {
1574       updateTexture();
1575
1576       // VP z fix
1577       //glMatrixMode(GL_MODELVIEW);
1578       //glLoadIdentity();
1579       //glTranslatef(0, 0, 1-zscale);
1580       //glScalef(1, 1, zscale);
1581       inverted_culling = 0;
1582       grCullMode(culling_mode);
1583
1584       width = savedWidth;
1585       height = savedHeight;
1586       widtho = savedWidtho;
1587       heighto = savedHeighto;
1588       if (use_fbo) {
1589         glBindFramebuffer(GL_FRAMEBUFFER, 0);
1590         glBindRenderbuffer( GL_RENDERBUFFER, 0 );
1591       }
1592       curBufferAddr = 0;
1593
1594       glViewport(0, viewport_offset, width, viewport_height);
1595       glScissor(0, viewport_offset, width, height);
1596
1597 #ifdef SAVE_CBUFFER
1598       if (!use_fbo && render_to_texture == 2) {
1599         // restore color buffer
1600         if (nbAuxBuffers > 0) {
1601           //glDrawBuffer(GL_BACK);
1602           current_buffer = GL_BACK;
1603         } else if (save_w) {
1604           int tw = 1, th = 1;
1605           //printf("restore %dx%d\n", save_w, save_h);
1606           if (npot_support) {
1607             tw = screen_width;
1608             th = screen_height;
1609           } else {
1610             while (tw < screen_width) tw <<= 1;
1611             while (th < screen_height) th <<= 1;
1612           }
1613
1614           //glPushAttrib(GL_ALL_ATTRIB_BITS);
1615           //glDisable(GL_ALPHA_TEST);
1616           //glDrawBuffer(GL_BACK);
1617           glActiveTexture(texture_unit);
1618           glBindTexture(GL_TEXTURE_2D, color_texture);
1619           glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
1620           set_copy_shader();
1621           glDisable(GL_DEPTH_TEST);
1622           glDisable(GL_CULL_FACE);
1623           render_rectangle(texture_unit,
1624             0, 0,
1625             save_w,  save_h,
1626             tw, th, -1);
1627           glBindTexture(GL_TEXTURE_2D, default_texture);
1628           //glPopAttrib();
1629
1630           save_w = save_h = 0;
1631         }
1632       }
1633 #endif
1634       render_to_texture = 0;
1635     }
1636     //glDrawBuffer(GL_BACK);
1637     break;
1638   case 6: // RENDER TO TEXTURE
1639     if(!render_to_texture)
1640     {
1641       savedWidth = width;
1642       savedHeight = height;
1643       savedWidtho = widtho;
1644       savedHeighto = heighto;
1645     }
1646
1647     {
1648       if (!use_fbo) {
1649         //glMatrixMode(GL_MODELVIEW);
1650         //glLoadIdentity();
1651         //glTranslatef(0, 0, 1-zscale);
1652         //glScalef(1, 1, zscale);
1653         inverted_culling = 0;
1654       } else {
1655 /*
1656         float m[4*4] = {1.0f, 0.0f, 0.0f, 0.0f,
1657           0.0f,-1.0f, 0.0f, 0.0f,
1658           0.0f, 0.0f, 1.0f, 0.0f,
1659           0.0f, 0.0f, 0.0f, 1.0f};
1660         glMatrixMode(GL_MODELVIEW);
1661         glLoadMatrixf(m);
1662         // VP z fix
1663         glTranslatef(0, 0, 1-zscale);
1664         glScalef(1, 1*1, zscale);
1665 */
1666         inverted_culling = 1;
1667         grCullMode(culling_mode);
1668       }
1669     }
1670     render_to_texture = 1;
1671     break;
1672   default:
1673     display_warning("grRenderBuffer : unknown buffer : %x", buffer);
1674   }
1675 }
1676
1677 FX_ENTRY void FX_CALL
1678 grAuxBufferExt( GrBuffer_t buffer )
1679 {
1680   LOG("grAuxBufferExt(%d)\r\n", buffer);
1681   //display_warning("grAuxBufferExt");
1682
1683   if (buffer == GR_BUFFER_AUXBUFFER) {
1684     invtex[0] = 0;
1685     invtex[1] = 0;
1686     need_to_compile = 0;
1687     set_depth_shader();
1688     glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
1689     glEnable(GL_DEPTH_TEST);
1690     glDepthFunc(GL_ALWAYS);
1691     glDisable(GL_CULL_FACE);
1692     //glDisable(GL_ALPHA_TEST);
1693     glDepthMask(GL_TRUE);
1694     grTexFilterMode(GR_TMU1, GR_TEXTUREFILTER_POINT_SAMPLED, GR_TEXTUREFILTER_POINT_SAMPLED);
1695   } else {
1696     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
1697     need_to_compile = 1;
1698   }
1699 }
1700
1701 FX_ENTRY void FX_CALL
1702 grBufferClear( GrColor_t color, GrAlpha_t alpha, FxU32 depth )
1703 {
1704   vbo_draw();
1705   LOG("grBufferClear(%d,%d,%d)\r\n", color, alpha, depth);
1706   switch(lfb_color_fmt)
1707   {
1708   case GR_COLORFORMAT_ARGB:
1709     glClearColor(((color >> 16) & 0xFF) / 255.0f,
1710       ((color >>  8) & 0xFF) / 255.0f,
1711       ( color        & 0xFF) / 255.0f,
1712       alpha / 255.0f);
1713     break;
1714   case GR_COLORFORMAT_RGBA:
1715     glClearColor(((color >> 24) & 0xFF) / 255.0f,
1716       ((color >> 16) & 0xFF) / 255.0f,
1717       (color         & 0xFF) / 255.0f,
1718       alpha / 255.0f);
1719     break;
1720   default:
1721     display_warning("grBufferClear: unknown color format : %x", lfb_color_fmt);
1722   }
1723
1724   if (w_buffer_mode)
1725     glClearDepthf(1.0f - ((1.0f + (depth >> 4) / 4096.0f) * (1 << (depth & 0xF))) / 65528.0);
1726   else
1727     glClearDepthf(depth / 65535.0f);
1728   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1729
1730   // ZIGGY TODO check that color mask is on
1731   buffer_cleared = 1;
1732
1733 }
1734
1735 // #include <unistd.h>
1736 FX_ENTRY void FX_CALL
1737 grBufferSwap( FxU32 swap_interval )
1738 {
1739   vbo_draw();
1740 //      glFinish();
1741 //  printf("rendercallback is %p\n", renderCallback);
1742   if(renderCallback)
1743       (*renderCallback)(1);
1744   int i;
1745   LOG("grBufferSwap(%d)\r\n", swap_interval);
1746   //printf("swap\n");
1747   if (render_to_texture) {
1748     display_warning("swap while render_to_texture\n");
1749     return;
1750   }
1751
1752   CoreVideo_GL_SwapBuffers();
1753   for (i = 0; i < nb_fb; i++)
1754     fbs[i].buff_clear = 1;
1755
1756   // VP debugging
1757 #ifdef VPDEBUG
1758   dump_stop();
1759   SDL_Event event;
1760   while (SDL_PollEvent(&event)) {
1761     switch (event.type) {
1762 case SDL_KEYDOWN:
1763   switch (event.key.keysym.sym) {
1764 case 'd':
1765   printf("Dumping !\n");
1766   dump_start();
1767   break;
1768 case 'w': {
1769   static int wireframe;
1770   wireframe = !wireframe;
1771   glPolygonMode(GL_FRONT_AND_BACK, wireframe? GL_LINE : GL_FILL);
1772   break;
1773           }
1774   }
1775   break;
1776     }
1777   }
1778 #endif
1779 }
1780
1781 // frame buffer
1782
1783 FX_ENTRY FxBool FX_CALL
1784 grLfbLock( GrLock_t type, GrBuffer_t buffer, GrLfbWriteMode_t writeMode,
1785           GrOriginLocation_t origin, FxBool pixelPipeline,
1786           GrLfbInfo_t *info )
1787 {
1788   LOG("grLfbLock(%d,%d,%d,%d,%d)\r\n", type, buffer, writeMode, origin, pixelPipeline);
1789 printf("grLfbLock(%d,%d,%d,%d,%d)\r\n", type, buffer, writeMode, origin, pixelPipeline);
1790   if (type == GR_LFB_WRITE_ONLY)
1791   {
1792     display_warning("grLfbLock : write only");
1793   }
1794   else
1795   {
1796     unsigned char *buf;
1797     int i,j;
1798
1799     switch(buffer)
1800     {
1801     case GR_BUFFER_FRONTBUFFER:
1802       //glReadBuffer(GL_FRONT);
1803       break;
1804     case GR_BUFFER_BACKBUFFER:
1805       //glReadBuffer(GL_BACK);
1806       break;
1807     default:
1808       display_warning("grLfbLock : unknown buffer : %x", buffer);
1809     }
1810
1811     if(buffer != GR_BUFFER_AUXBUFFER)
1812     {
1813       if (writeMode == GR_LFBWRITEMODE_888) {
1814 /*SEB*/
1815         buf = (unsigned char*)malloc(width*height*4);
1816         //printf("LfbLock GR_LFBWRITEMODE_888\n");
1817         info->lfbPtr = frameBuffer;
1818         info->strideInBytes = width*4;
1819         info->writeMode = GR_LFBWRITEMODE_888;
1820         info->origin = origin;
1821         //glReadPixels(0, viewport_offset, width, height, GL_BGRA, GL_UNSIGNED_BYTE, frameBuffer);
1822         glReadPixels(0, viewport_offset, width, height, GL_RGBA, GL_UNSIGNED_BYTE, buf);
1823
1824 /*SEB*/
1825             unsigned char *p=buf;
1826         for (j=0; j<height; j++)
1827         {
1828             short unsigned int *f=frameBuffer+(height-j-1)*width;
1829           for (i=0; i<width; i++)
1830           {
1831             *(f++) =
1832               (*(p)   <<24) |
1833               (*(p+1) <<16) |
1834               (*(p+2) << 8) |
1835                   (0xff);
1836               p+=4;
1837           }
1838         }
1839         free(buf);
1840       } else {
1841         buf = (unsigned char*)malloc(width*height*4);
1842
1843         info->lfbPtr = frameBuffer;
1844         info->strideInBytes = width*2;
1845         info->writeMode = GR_LFBWRITEMODE_565;
1846         info->origin = origin;
1847         glReadPixels(0, viewport_offset, width, height, GL_RGBA, GL_UNSIGNED_BYTE, buf);
1848
1849 /*SEB*/
1850             unsigned char *p=buf;
1851         for (j=0; j<height; j++)
1852         {
1853               short unsigned int *f=frameBuffer+(height-j-1)*width;
1854           for (i=0; i<width; i++)
1855           {
1856 /*            frameBuffer[(height-j-1)*width+i] =
1857               ((buf[j*width*4+i*4+0] >> 3) << 11) |
1858               ((buf[j*width*4+i*4+1] >> 2) <<  5) |
1859               (buf[j*width*4+i*4+2] >> 3);*/
1860             *(f++) =
1861               ((*(p)   >> 3) << 11) |
1862               ((*(p+1) >> 2) <<  5) |
1863               (*(p+2)  >> 3);
1864               p+=4;
1865           }
1866         }
1867         free(buf);
1868       }
1869     }
1870     else
1871     {
1872       info->lfbPtr = depthBuffer;
1873       info->strideInBytes = width*2;
1874       info->writeMode = GR_LFBWRITEMODE_ZA16;
1875       info->origin = origin;
1876       //*SEB* *TODO* check alignment
1877       glReadPixels(0, viewport_offset, width, height, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, depthBuffer);
1878     }
1879   }
1880
1881   return FXTRUE;
1882 }
1883
1884 FX_ENTRY FxBool FX_CALL
1885 grLfbUnlock( GrLock_t type, GrBuffer_t buffer )
1886 {
1887   LOG("grLfbUnlock(%d,%d)\r\n", type, buffer);
1888   if (type == GR_LFB_WRITE_ONLY)
1889   {
1890     display_warning("grLfbUnlock : write only");
1891   }
1892   return FXTRUE;
1893 }
1894
1895 FX_ENTRY FxBool FX_CALL
1896 grLfbReadRegion( GrBuffer_t src_buffer,
1897                 FxU32 src_x, FxU32 src_y,
1898                 FxU32 src_width, FxU32 src_height,
1899                 FxU32 dst_stride, void *dst_data )
1900 {
1901   unsigned char *buf;
1902   unsigned int i,j;
1903   unsigned short *frameBuffer = (unsigned short*)dst_data;
1904   unsigned short *depthBuffer = (unsigned short*)dst_data;
1905   LOG("grLfbReadRegion(%d,%d,%d,%d,%d,%d)\r\n", src_buffer, src_x, src_y, src_width, src_height, dst_stride);
1906 //printf("grLfbReadRegion(%d,%d,%d,%d,%d,%d)\r\n", src_buffer, src_x, src_y, src_width, src_height, dst_stride);
1907
1908   switch(src_buffer)
1909   {
1910   case GR_BUFFER_FRONTBUFFER:
1911     //glReadBuffer(GL_FRONT);
1912     break;
1913   case GR_BUFFER_BACKBUFFER:
1914     //glReadBuffer(GL_BACK);
1915     break;
1916     /*case GR_BUFFER_AUXBUFFER:
1917     glReadBuffer(current_buffer);
1918     break;*/
1919   default:
1920     display_warning("grReadRegion : unknown buffer : %x", src_buffer);
1921   }
1922
1923   if(src_buffer != GR_BUFFER_AUXBUFFER)
1924   {
1925     buf = (unsigned char*)malloc(src_width*src_height*4);
1926
1927     glReadPixels(src_x, (viewport_offset)+height-src_y-src_height, src_width, src_height, GL_RGBA, GL_UNSIGNED_BYTE, buf);
1928     for (j=0; j<src_height; j++)
1929     {
1930 /*SEB*/
1931       unsigned char *p=buf+(src_height-j-1)*src_width*4;
1932       unsigned short *f=frameBuffer+(j*dst_stride/2);
1933       for (i=0; i<src_width; i++)
1934       {
1935 /*        frameBuffer[j*(dst_stride/2)+i] =
1936           ((buf[(src_height-j-1)*src_width*4+i*4+0] >> 3) << 11) |
1937           ((buf[(src_height-j-1)*src_width*4+i*4+1] >> 2) <<  5) |
1938           (buf[(src_height-j-1)*src_width*4+i*4+2] >> 3);*/
1939         *(f++) =
1940           ((*(p) >> 3) << 11) |
1941           ((*(p+1) >> 2) <<  5) |
1942           (*(p+2) >> 3);
1943           p+=4;
1944       }
1945     }
1946     free(buf);
1947   }
1948   else
1949   {
1950     buf = (unsigned char*)malloc(src_width*src_height*2);
1951 //*SEB read in buf, not depthBuffer.
1952     glReadPixels(src_x, (viewport_offset)+height-src_y-src_height, src_width, src_height, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, buf);
1953
1954     for (j=0;j<src_height; j++)
1955     {
1956 //*SEB*
1957       unsigned short *d=depthBuffer+j*dst_stride/2;
1958       unsigned short *p=(unsigned short*)buf+(src_height-j-1)*src_width; //orignal look fishy. why *4???
1959       for (i=0; i<src_width; i++)
1960       {
1961 /*        depthBuffer[j*(dst_stride/2)+i] =
1962           ((unsigned short*)buf)[(src_height-j-1)*src_width*4+i*4];*/
1963         *(d++) = *(p++); //why *4 (prob. GL_PACK was=4), plus transcoding to short, that make *8 ???
1964       }
1965     }
1966     free(buf);
1967   }
1968
1969   return FXTRUE;
1970 }
1971
1972 FX_ENTRY FxBool FX_CALL
1973 grLfbWriteRegion( GrBuffer_t dst_buffer,
1974                  FxU32 dst_x, FxU32 dst_y,
1975                  GrLfbSrcFmt_t src_format,
1976                  FxU32 src_width, FxU32 src_height,
1977                  FxBool pixelPipeline,
1978                  FxI32 src_stride, void *src_data )
1979 {
1980   unsigned char *buf;
1981   unsigned int i,j;
1982   unsigned short *frameBuffer = (unsigned short*)src_data;
1983   int texture_number;
1984   unsigned int tex_width = 1, tex_height = 1;
1985   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);
1986 //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);
1987
1988   //glPushAttrib(GL_ALL_ATTRIB_BITS);
1989
1990   while (tex_width < src_width) tex_width <<= 1;
1991   while (tex_height < src_height) tex_height <<= 1;
1992
1993   switch(dst_buffer)
1994   {
1995   case GR_BUFFER_BACKBUFFER:
1996     //glDrawBuffer(GL_BACK);
1997     break;
1998   case GR_BUFFER_AUXBUFFER:
1999     //glDrawBuffer(current_buffer);
2000     break;
2001   default:
2002     display_warning("grLfbWriteRegion : unknown buffer : %x", dst_buffer);
2003   }
2004
2005   if(dst_buffer != GR_BUFFER_AUXBUFFER)
2006   {
2007     buf = (unsigned char*)malloc(tex_width*tex_height*4);
2008
2009     texture_number = GL_TEXTURE0;
2010     glActiveTexture(texture_number);
2011
2012     const unsigned int half_stride = src_stride / 2;
2013
2014     const int comp_stride = half_stride - src_width;
2015     const int comp_tex = (tex_width - src_width)*4;
2016     unsigned short *f=frameBuffer;
2017     unsigned char *p=buf;
2018
2019     switch(src_format)
2020     {
2021     case GR_LFB_SRC_FMT_1555:
2022       for (j=0; j<src_height; j++)
2023       {
2024         for (i=0; i<src_width; i++)
2025         {
2026 /*          const unsigned int col = frameBuffer[j*half_stride+i];
2027           buf[j*tex_width*4+i*4+0]=((col>>10)&0x1F)<<3;
2028           buf[j*tex_width*4+i*4+1]=((col>>5)&0x1F)<<3;
2029           buf[j*tex_width*4+i*4+2]=((col>>0)&0x1F)<<3;
2030           buf[j*tex_width*4+i*4+3]= (col>>15) ? 0xFF : 0;*/
2031           const unsigned int col = *(f++);
2032           *(p)=((col>>10)&0x1F)<<3;
2033           *(p+1)=((col>>5)&0x1F)<<3;
2034           *(p+2)=((col>>0)&0x1F)<<3;
2035           *(p+3)= (col>>15) ? 0xFF : 0;
2036           p+=4;
2037         }
2038         p+=comp_tex;
2039         f+=comp_stride;
2040       }
2041       break;
2042     case GR_LFBWRITEMODE_555:
2043       for (j=0; j<src_height; j++)
2044       {
2045         for (i=0; i<src_width; i++)
2046         {
2047 /*          const unsigned int col = frameBuffer[j*half_stride+i];
2048           buf[j*tex_width*4+i*4+0]=((col>>10)&0x1F)<<3;
2049           buf[j*tex_width*4+i*4+1]=((col>>5)&0x1F)<<3;
2050           buf[j*tex_width*4+i*4+2]=((col>>0)&0x1F)<<3;
2051           buf[j*tex_width*4+i*4+3]=0xFF;*/
2052           const unsigned int col = *(f++);
2053           *(p)=((col>>10)&0x1F)<<3;
2054           *(p+1)=((col>>5)&0x1F)<<3;
2055           *(p+2)=((col>>0)&0x1F)<<3;
2056           *(p+3)=0xFF;
2057           p+=4;
2058         }
2059         p+=comp_tex;
2060         f+=comp_stride;
2061       }
2062       break;
2063     case GR_LFBWRITEMODE_565:
2064       for (j=0; j<src_height; j++)
2065       {
2066         for (i=0; i<src_width; i++)
2067         {
2068 /*          const unsigned int col = frameBuffer[j*half_stride+i];
2069           buf[j*tex_width*4+i*4+0]=((col>>11)&0x1F)<<3;
2070           buf[j*tex_width*4+i*4+1]=((col>>5)&0x3F)<<2;
2071           buf[j*tex_width*4+i*4+2]=((col>>0)&0x1F)<<3;
2072           buf[j*tex_width*4+i*4+3]=0xFF;*/
2073           const unsigned int col = *(f++);
2074           *(p)=((col>>11)&0x1F)<<3;
2075           *(p+1)=((col>>5)&0x3F)<<2;
2076           *(p+2)=((col>>0)&0x1F)<<3;
2077           *(p+3)=0xFF;
2078           p+=4;
2079         }
2080         p+=comp_tex;
2081         f+=comp_stride;
2082       }
2083       break;
2084     default:
2085       display_warning("grLfbWriteRegion : unknown format : %d", src_format);
2086     }
2087
2088 #ifdef VPDEBUG
2089     if (dumping) {
2090       ilTexImage(tex_width, tex_height, 1, 4, IL_RGBA, IL_UNSIGNED_BYTE, buf);
2091       char name[128];
2092       static int id;
2093       sprintf(name, "dump/writecolor%d.png", id++);
2094       ilSaveImage(name);
2095       //printf("dumped gdLfbWriteRegion %s\n", name);
2096     }
2097 #endif
2098
2099     glBindTexture(GL_TEXTURE_2D, default_texture);
2100     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex_width, tex_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, buf);
2101     free(buf);
2102
2103     set_copy_shader();
2104
2105     glDisable(GL_DEPTH_TEST);
2106     glDisable(GL_BLEND);
2107     render_rectangle(texture_number,
2108       dst_x, dst_y,
2109       src_width,  src_height,
2110       tex_width,  tex_height, +1);
2111
2112   }
2113   else
2114   {
2115     float *buf = (float*)malloc(src_width*(src_height+(viewport_offset))*sizeof(float));
2116
2117     if (src_format != GR_LFBWRITEMODE_ZA16)
2118       display_warning("unknown depth buffer write format:%x", src_format);
2119
2120     if(dst_x || dst_y)
2121       display_warning("dst_x:%d, dst_y:%d\n",dst_x, dst_y);
2122
2123     for (j=0; j<src_height; j++)
2124     {
2125       for (i=0; i<src_width; i++)
2126       {
2127         buf[(j+(viewport_offset))*src_width+i] =
2128           (frameBuffer[(src_height-j-1)*(src_stride/2)+i]/(65536.0f*(2.0f/zscale)))+1-zscale/2.0f;
2129       }
2130     }
2131
2132 #ifdef VPDEBUG
2133     if (dumping) {
2134       unsigned char * buf2 = (unsigned char *)malloc(src_width*(src_height+(viewport_offset)));
2135       for (i=0; i<src_width*src_height ; i++)
2136         buf2[i] = buf[i]*255.0f;
2137       ilTexImage(src_width, src_height, 1, 1, IL_LUMINANCE, IL_UNSIGNED_BYTE, buf2);
2138       char name[128];
2139       static int id;
2140       sprintf(name, "dump/writedepth%d.png", id++);
2141       ilSaveImage(name);
2142       //printf("dumped gdLfbWriteRegion %s\n", name);
2143       free(buf2);
2144     }
2145 #endif
2146
2147     glEnable(GL_DEPTH_TEST);
2148     glDepthFunc(GL_ALWAYS);
2149
2150     //glDrawBuffer(GL_BACK);
2151     glClear( GL_DEPTH_BUFFER_BIT );
2152     glDepthMask(1);
2153     //glDrawPixels(src_width, src_height+(viewport_offset), GL_DEPTH_COMPONENT, GL_FLOAT, buf);
2154
2155     free(buf);
2156   }
2157   //glDrawBuffer(current_buffer);
2158   //glPopAttrib();
2159   return FXTRUE;
2160 }
2161
2162 /* wrapper-specific glide extensions */
2163
2164 FX_ENTRY char ** FX_CALL
2165 grQueryResolutionsExt(FxI32 * Size)
2166 {
2167   return 0;
2168 /*
2169   LOG("grQueryResolutionsExt\r\n");
2170   return g_FullScreenResolutions.getResolutionsList(Size);
2171 */
2172 }
2173
2174 FX_ENTRY GrScreenResolution_t FX_CALL grWrapperFullScreenResolutionExt(FxU32* width, FxU32* height)
2175 {
2176   return 0;
2177 /*
2178   LOG("grWrapperFullScreenResolutionExt\r\n");
2179   g_FullScreenResolutions.getResolution(config.res, width, height);
2180   return config.res;
2181 */
2182 }
2183
2184 FX_ENTRY FxBool FX_CALL grKeyPressedExt(FxU32 key)
2185 {
2186   return 0;
2187 /*
2188 #ifdef _WIN32
2189   return (GetAsyncKeyState(key) & 0x8000);
2190 #else
2191   if (key == 1) //LBUTTON
2192   {
2193     Uint8 mstate = SDL_GetMouseState(NULL, NULL);
2194     return (mstate & SDL_BUTTON_LMASK);
2195   }
2196   else
2197   {
2198     Uint8 *keystates = SDL_GetKeyState( NULL );
2199     if( keystates[ key ] )
2200     {
2201       return 1;
2202     }
2203     else
2204     {
2205       return 0;
2206     }
2207   }
2208 #endif
2209 */
2210 }
2211
2212 FX_ENTRY void FX_CALL grConfigWrapperExt(FxI32 resolution, FxI32 vram, FxBool fbo, FxBool aniso)
2213 {
2214   LOG("grConfigWrapperExt\r\n");
2215   config.res = resolution;
2216   config.vram_size = vram;
2217   config.fbo = fbo;
2218   config.anisofilter = aniso;
2219 }
2220
2221 // unused by glide64
2222
2223 FX_ENTRY FxI32 FX_CALL
2224 grQueryResolutions( const GrResolution *resTemplate, GrResolution *output )
2225 {
2226   int res_inf = 0;
2227   int res_sup = 0xf;
2228   int i;
2229   int n=0;
2230   LOG("grQueryResolutions\r\n");
2231   display_warning("grQueryResolutions");
2232   if ((unsigned int)resTemplate->resolution != GR_QUERY_ANY)
2233   {
2234     res_inf = res_sup = resTemplate->resolution;
2235   }
2236   if ((unsigned int)resTemplate->refresh == GR_QUERY_ANY) display_warning("querying any refresh rate");
2237   if ((unsigned int)resTemplate->numAuxBuffers == GR_QUERY_ANY) display_warning("querying any numAuxBuffers");
2238   if ((unsigned int)resTemplate->numColorBuffers == GR_QUERY_ANY) display_warning("querying any numColorBuffers");
2239
2240   if (output == NULL) return res_sup - res_inf + 1;
2241   for (i=res_inf; i<=res_sup; i++)
2242   {
2243     output[n].resolution = i;
2244     output[n].refresh = resTemplate->refresh;
2245     output[n].numAuxBuffers = resTemplate->numAuxBuffers;
2246     output[n].numColorBuffers = resTemplate->numColorBuffers;
2247     n++;
2248   }
2249   return res_sup - res_inf + 1;
2250 }
2251
2252 FX_ENTRY FxBool FX_CALL
2253 grReset( FxU32 what )
2254 {
2255   display_warning("grReset");
2256   return 1;
2257 }
2258
2259 FX_ENTRY void FX_CALL
2260 grEnable( GrEnableMode_t mode )
2261 {
2262   LOG("grEnable(%d)\r\n", mode);
2263   if (mode == GR_TEXTURE_UMA_EXT)
2264     UMAmode = 1;
2265 }
2266
2267 FX_ENTRY void FX_CALL
2268 grDisable( GrEnableMode_t mode )
2269 {
2270   LOG("grDisable(%d)\r\n", mode);
2271   if (mode == GR_TEXTURE_UMA_EXT)
2272     UMAmode = 0;
2273 }
2274
2275 FX_ENTRY void FX_CALL
2276 grDisableAllEffects( void )
2277 {
2278   display_warning("grDisableAllEffects");
2279 }
2280
2281 FX_ENTRY void FX_CALL
2282 grErrorSetCallback( GrErrorCallbackFnc_t fnc )
2283 {
2284   display_warning("grErrorSetCallback");
2285 }
2286
2287 FX_ENTRY void FX_CALL
2288 grFinish(void)
2289 {
2290   display_warning("grFinish");
2291 }
2292
2293 FX_ENTRY void FX_CALL
2294 grFlush(void)
2295 {
2296   display_warning("grFlush");
2297 }
2298
2299 FX_ENTRY void FX_CALL
2300 grTexMultibase( GrChipID_t tmu,
2301                FxBool     enable )
2302 {
2303   display_warning("grTexMultibase");
2304 }
2305
2306 FX_ENTRY void FX_CALL
2307 grTexMipMapMode( GrChipID_t     tmu,
2308                 GrMipMapMode_t mode,
2309                 FxBool         lodBlend )
2310 {
2311   display_warning("grTexMipMapMode");
2312 }
2313
2314 FX_ENTRY void FX_CALL
2315 grTexDownloadTablePartial( GrTexTable_t type,
2316                           void         *data,
2317                           int          start,
2318                           int          end )
2319 {
2320   display_warning("grTexDownloadTablePartial");
2321 }
2322
2323 FX_ENTRY void FX_CALL
2324 grTexDownloadTable( GrTexTable_t type,
2325                    void         *data )
2326 {
2327   display_warning("grTexDownloadTable");
2328 }
2329
2330 FX_ENTRY FxBool FX_CALL
2331 grTexDownloadMipMapLevelPartial( GrChipID_t        tmu,
2332                                 FxU32             startAddress,
2333                                 GrLOD_t           thisLod,
2334                                 GrLOD_t           largeLod,
2335                                 GrAspectRatio_t   aspectRatio,
2336                                 GrTextureFormat_t format,
2337                                 FxU32             evenOdd,
2338                                 void              *data,
2339                                 int               start,
2340                                 int               end )
2341 {
2342   display_warning("grTexDownloadMipMapLevelPartial");
2343   return 1;
2344 }
2345
2346 FX_ENTRY void FX_CALL
2347 grTexDownloadMipMapLevel( GrChipID_t        tmu,
2348                          FxU32             startAddress,
2349                          GrLOD_t           thisLod,
2350                          GrLOD_t           largeLod,
2351                          GrAspectRatio_t   aspectRatio,
2352                          GrTextureFormat_t format,
2353                          FxU32             evenOdd,
2354                          void              *data )
2355 {
2356   display_warning("grTexDownloadMipMapLevel");
2357 }
2358
2359 FX_ENTRY void FX_CALL
2360 grTexNCCTable( GrNCCTable_t table )
2361 {
2362   display_warning("grTexNCCTable");
2363 }
2364
2365 FX_ENTRY void FX_CALL
2366 grViewport( FxI32 x, FxI32 y, FxI32 width, FxI32 height )
2367 {
2368   display_warning("grViewport");
2369 }
2370
2371 FX_ENTRY void FX_CALL
2372 grDepthRange( FxFloat n, FxFloat f )
2373 {
2374   display_warning("grDepthRange");
2375 }
2376
2377 FX_ENTRY void FX_CALL
2378 grSplash(float x, float y, float width, float height, FxU32 frame)
2379 {
2380   display_warning("grSplash");
2381 }
2382
2383 FX_ENTRY FxBool FX_CALL
2384 grSelectContext( GrContext_t context )
2385 {
2386   display_warning("grSelectContext");
2387   return 1;
2388 }
2389
2390 FX_ENTRY void FX_CALL
2391 grAADrawTriangle(
2392                  const void *a, const void *b, const void *c,
2393                  FxBool ab_antialias, FxBool bc_antialias, FxBool ca_antialias
2394                  )
2395 {
2396   display_warning("grAADrawTriangle");
2397 }
2398
2399 FX_ENTRY void FX_CALL
2400 grAlphaControlsITRGBLighting( FxBool enable )
2401 {
2402   display_warning("grAlphaControlsITRGBLighting");
2403 }
2404
2405 FX_ENTRY void FX_CALL
2406 grGlideSetVertexLayout( const void *layout )
2407 {
2408   display_warning("grGlideSetVertexLayout");
2409 }
2410
2411 FX_ENTRY void FX_CALL
2412 grGlideGetVertexLayout( void *layout )
2413 {
2414   display_warning("grGlideGetVertexLayout");
2415 }
2416
2417 FX_ENTRY void FX_CALL
2418 grGlideSetState( const void *state )
2419 {
2420   display_warning("grGlideSetState");
2421 }
2422
2423 FX_ENTRY void FX_CALL
2424 grGlideGetState( void *state )
2425 {
2426   display_warning("grGlideGetState");
2427 }
2428
2429 FX_ENTRY void FX_CALL
2430 grLfbWriteColorFormat(GrColorFormat_t colorFormat)
2431 {
2432   display_warning("grLfbWriteColorFormat");
2433 }
2434
2435 FX_ENTRY void FX_CALL
2436 grLfbWriteColorSwizzle(FxBool swizzleBytes, FxBool swapWords)
2437 {
2438   display_warning("grLfbWriteColorSwizzle");
2439 }
2440
2441 FX_ENTRY void FX_CALL
2442 grLfbConstantDepth( FxU32 depth )
2443 {
2444   display_warning("grLfbConstantDepth");
2445 }
2446
2447 FX_ENTRY void FX_CALL
2448 grLfbConstantAlpha( GrAlpha_t alpha )
2449 {
2450   display_warning("grLfbConstantAlpha");
2451 }
2452
2453 FX_ENTRY void FX_CALL
2454 grTexMultibaseAddress( GrChipID_t       tmu,
2455                       GrTexBaseRange_t range,
2456                       FxU32            startAddress,
2457                       FxU32            evenOdd,
2458                       GrTexInfo        *info )
2459 {
2460   display_warning("grTexMultibaseAddress");
2461 }
2462
2463 /*
2464 inline void MySleep(FxU32 ms)
2465 {
2466 #ifdef _WIN32
2467   Sleep(ms);
2468 #else
2469   SDL_Delay(ms);
2470 #endif
2471 }
2472 */
2473
2474 #ifdef _WIN32
2475 static void CorrectGamma(LPVOID apGammaRamp)
2476 {
2477   HDC hdc = GetDC(NULL);
2478   if (hdc != NULL)
2479   {
2480     SetDeviceGammaRamp(hdc, apGammaRamp);
2481     ReleaseDC(NULL, hdc);
2482   }
2483 }
2484 #else
2485 static void CorrectGamma(const FxU16 aGammaRamp[3][256])
2486 {
2487   //TODO?
2488   //int res = SDL_SetGammaRamp(aGammaRamp[0], aGammaRamp[1], aGammaRamp[2]);
2489   //LOG("SDL_SetGammaRamp returned %d\r\n", res);
2490 }
2491 #endif
2492
2493 FX_ENTRY void FX_CALL
2494 grLoadGammaTable( FxU32 nentries, FxU32 *red, FxU32 *green, FxU32 *blue)
2495 {
2496   LOG("grLoadGammaTable\r\n");
2497   if (!fullscreen)
2498     return;
2499   FxU16 aGammaRamp[3][256];
2500   for (int i = 0; i < 256; i++)
2501   {
2502     aGammaRamp[0][i] = (FxU16)((red[i] << 8) & 0xFFFF);
2503     aGammaRamp[1][i] = (FxU16)((green[i] << 8) & 0xFFFF);
2504     aGammaRamp[2][i] = (FxU16)((blue[i] << 8) & 0xFFFF);
2505   }
2506   CorrectGamma(aGammaRamp);
2507   //MySleep(1000); //workaround for Mupen64
2508 }
2509
2510 FX_ENTRY void FX_CALL
2511 grGetGammaTableExt(FxU32 nentries, FxU32 *red, FxU32 *green, FxU32 *blue)
2512 {
2513   return;
2514   //TODO?
2515   /*
2516   LOG("grGetGammaTableExt()\r\n");
2517   FxU16 aGammaRamp[3][256];
2518 #ifdef _WIN32
2519   HDC hdc = GetDC(NULL);
2520   if (hdc == NULL)
2521     return;
2522   if (GetDeviceGammaRamp(hdc, aGammaRamp) == TRUE)
2523   {
2524     ReleaseDC(NULL, hdc);
2525 #else
2526   if (SDL_GetGammaRamp(aGammaRamp[0], aGammaRamp[1], aGammaRamp[2]) != -1)
2527   {
2528 #endif
2529     for (int i = 0; i < 256; i++)
2530     {
2531       red[i] = aGammaRamp[0][i] >> 8;
2532       green[i] = aGammaRamp[1][i] >> 8;
2533       blue[i] = aGammaRamp[2][i] >> 8;
2534     }
2535   }
2536   */
2537 }
2538
2539 FX_ENTRY void FX_CALL
2540 guGammaCorrectionRGB( FxFloat gammaR, FxFloat gammaG, FxFloat gammaB )
2541 {
2542   LOG("guGammaCorrectionRGB()\r\n");
2543   if (!fullscreen)
2544     return;
2545   FxU16 aGammaRamp[3][256];
2546   for (int i = 0; i < 256; i++)
2547   {
2548     aGammaRamp[0][i] = (((FxU16)((pow(i/255.0F, 1.0F/gammaR)) * 255.0F + 0.5F)) << 8) & 0xFFFF;
2549     aGammaRamp[1][i] = (((FxU16)((pow(i/255.0F, 1.0F/gammaG)) * 255.0F + 0.5F)) << 8) & 0xFFFF;
2550     aGammaRamp[2][i] = (((FxU16)((pow(i/255.0F, 1.0F/gammaB)) * 255.0F + 0.5F)) << 8) & 0xFFFF;
2551   }
2552   CorrectGamma(aGammaRamp);
2553 }
2554
2555 FX_ENTRY void FX_CALL
2556 grDitherMode( GrDitherMode_t mode )
2557 {
2558   display_warning("grDitherMode");
2559 }
2560
2561 void grChromaRangeExt(GrColor_t color0, GrColor_t color1, FxU32 mode)
2562 {
2563   display_warning("grChromaRangeExt");
2564 }
2565
2566 void grChromaRangeModeExt(GrChromakeyMode_t mode)
2567 {
2568   display_warning("grChromaRangeModeExt");
2569 }
2570
2571 void grTexChromaRangeExt(GrChipID_t tmu, GrColor_t color0, GrColor_t color1, GrTexChromakeyMode_t mode)
2572 {
2573   display_warning("grTexChromaRangeExt");
2574 }
2575
2576 void grTexChromaModeExt(GrChipID_t tmu, GrChromakeyMode_t mode)
2577 {
2578   display_warning("grTexChromaRangeModeExt");
2579 }
2580
2581 // VP debug
2582 #ifdef VPDEBUG
2583 int dumping = 0;
2584 static int tl_i;
2585 static int tl[10240];
2586
2587 void dump_start()
2588 {
2589   static int init;
2590   if (!init) {
2591     init = 1;
2592     ilInit();
2593     ilEnable(IL_FILE_OVERWRITE);
2594   }
2595   dumping = 1;
2596   tl_i = 0;
2597 }
2598
2599 void dump_stop()
2600 {
2601   if (!dumping) return;
2602
2603   int i, j;
2604   for (i=0; i<nb_fb; i++) {
2605     dump_tex(fbs[i].texid);
2606   }
2607   dump_tex(default_texture);
2608   dump_tex(depth_texture);
2609
2610   dumping = 0;
2611
2612   glReadBuffer(GL_FRONT);
2613   glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, frameBuffer);
2614   ilTexImage(width, height, 1, 4, IL_RGBA, IL_UNSIGNED_BYTE, frameBuffer);
2615   ilSaveImage("dump/framecolor.png");
2616   glReadPixels(0, 0, width, height, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, depthBuffer);
2617   //   FILE * fp = fopen("glide_depth1.bin", "rb");
2618   //   fread(depthBuffer, 2, width*height, fp);
2619   //   fclose(fp);
2620   for (j=0; j<height; j++) {
2621     for (i=0; i<width; i++) {
2622       //uint16_t d = ( (uint16_t *)depthBuffer )[i+(height-1-j)*width]/2 + 0x8000;
2623       uint16_t d = ( (uint16_t *)depthBuffer )[i+j*width];
2624       uint32_t c = ( (uint32_t *)frameBuffer )[i+j*width];
2625       ( (unsigned char *)frameBuffer )[(i+j*width)*3] = d&0xff;
2626       ( (unsigned char *)frameBuffer )[(i+j*width)*3+1] = d>>8;
2627       ( (unsigned char *)frameBuffer )[(i+j*width)*3+2] = c&0xff;
2628     }
2629   }
2630   ilTexImage(width, height, 1, 3, IL_RGB, IL_UNSIGNED_BYTE, frameBuffer);
2631   ilSaveImage("dump/framedepth.png");
2632
2633   for (i=0; i<tl_i; i++) {
2634     glBindTexture(GL_TEXTURE_2D, tl[i]);
2635     GLint w, h, fmt;
2636     glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &w);
2637     glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &h);
2638     glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &fmt);
2639     fprintf(stderr, "Texture %d %dx%d fmt %x\n", tl[i], (int)w, (int)h, (int) fmt);
2640
2641     uint32_t * pixels = (uint32_t *) malloc(w*h*4);
2642     // 0x1902 is another constant meaning GL_DEPTH_COMPONENT
2643     // (but isn't defined in gl's headers !!)
2644     if (fmt != GL_DEPTH_COMPONENT && fmt != 0x1902) {
2645       glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
2646       ilTexImage(w, h, 1, 4, IL_RGBA, IL_UNSIGNED_BYTE, pixels);
2647     } else {
2648       glGetTexImage(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, pixels);
2649       int i;
2650       for (i=0; i<w*h; i++)
2651         ((unsigned char *)frameBuffer)[i] = ((unsigned short *)pixels)[i]/256;
2652       ilTexImage(w, h, 1, 1, IL_LUMINANCE, IL_UNSIGNED_BYTE, frameBuffer);
2653     }
2654     char name[128];
2655     //     sprintf(name, "mkdir -p dump ; rm -f dump/tex%04d.png", i);
2656     //     system(name);
2657     sprintf(name, "dump/tex%04d.png", i);
2658     fprintf(stderr, "Writing '%s'\n", name);
2659     ilSaveImage(name);
2660
2661     //     SDL_FreeSurface(surf);
2662     free(pixels);
2663   }
2664   glBindTexture(GL_TEXTURE_2D, default_texture);
2665 }
2666
2667 void dump_tex(int id)
2668 {
2669   if (!dumping) return;
2670
2671   int n;
2672   // yes, it's inefficient
2673   for (n=0; n<tl_i; n++)
2674     if (tl[n] == id)
2675       return;
2676
2677   tl[tl_i++] = id;
2678
2679   int i = tl_i-1;
2680 }
2681
2682 #endif