1 /***************************************************************************
2                            draw.c  -  description
3                              -------------------
4     begin                : Sun Mar 08 2009
5     copyright            : (C) 1999-2009 by Pete Bernert
6     web                  : www.pbernert.com
7  ***************************************************************************/
8 
9 /***************************************************************************
10  *                                                                         *
11  *   This program is free software; you can redistribute it and/or modify  *
12  *   it under the terms of the GNU General Public License as published by  *
13  *   the Free Software Foundation; either version 2 of the License, or     *
14  *   (at your option) any later version. See also the license.txt file for *
15  *   additional informations.                                              *
16  *                                                                         *
17  ***************************************************************************/
18 
19 #include "stdafx.h"
20 
21 #define _IN_DRAW
22 
23 #include "externals.h"
24 #include "gpu.h"
25 #include "draw.h"
26 #include "prim.h"
27 #include "texture.h"
28 #include "menu.h"
29 
30 #include "gte_accuracy.h"
31 
32 #if defined(_MACGL)
33 // if you use it, you must include it
34 #include <OpenGL/gl.h>
35 #include <OpenGL/glext.h>
36 #include "drawgl.h"
37 #endif
38 ////////////////////////////////////////////////////////////////////////////////////
39 // defines
40 
41 #define SIGNBIT 0x800
42 #define S_MASK  0xf000
43 #define L_MASK  0xfffff000
44 
45 // ownscale: some ogl drivers have buggy texture matrix funcs, so it
46 //           is safer to calc sow/tow ourselves
47 
48 #ifdef OWNSCALE
49 
50 #define ST_FACSPRITE       255.99f
51 #define ST_BFFACSPRITE     0.5f/256.0f
52 #define ST_BFFACSPRITESORT 0.333f/256.0f
53 
54 #define ST_OFFSET          0.5f/256.0f;
55 
56 #define ST_FAC             255.99f
57 #define ST_BFFAC           0.5f/256.0f
58 #define ST_BFFACSORT       0.333f/256.0f
59 
60 #define ST_FACTRI          255.99f
61 #define ST_BFFACTRI        0.5f/256.0f
62 #define ST_BFFACTRISORT    0.333f/256.0f
63 
64 #define ST_FACVRAMX        255.0f
65 #define ST_FACVRAM         256.0f
66 
67 ///////////////////////////////////////////////////////////////
68 
69 #else
70 
71 #define ST_BFFACSPRITE     0.5f
72 #define ST_BFFACSPRITESORT 0.333f
73 
74 #define ST_BFFAC           0.5f
75 #define ST_BFFACSORT       0.333f
76 
77 #define ST_BFFACTRI        0.5f
78 #define ST_BFFACTRISORT    0.333f
79 
80 #define ST_OFFSET          0.5f;
81 
82 #endif
83 
84 ////////////////////////////////////////////////////////////////////////////////////
85 // draw globals; most will be initialized again later (by config or checks)
86 
87 #ifdef _WINDOWS
88 HDC            dcGlobal = NULL;
89 HWND           hWWindow;
90 #endif
91 
92 BOOL           bIsFirstFrame = TRUE;
93 
94 // resolution/ratio vars
95 
96 int            iResX;
97 int            iResY;
98 BOOL           bKeepRatio    = FALSE;
99 BOOL           bForceRatio43 = FALSE;
100 RECT           rRatioRect;
101 
102 // psx mask related vars
103 
104 BOOL           bCheckMask = FALSE;
105 int            iUseMask = 0;
106 int            iSetMask = 0;
107 unsigned short sSetMask = 0;
108 uint32_t       lSetMask = 0;
109 
110 // drawing/coord vars
111 
112 OGLVertex      vertex[4];
113 GLubyte        gl_ux[8];
114 GLubyte        gl_vy[8];
115 short          sprtY,sprtX,sprtH,sprtW;
116 
117 // drawing options
118 
119 BOOL           bOpaquePass;
120 BOOL           bAdvancedBlend;
121 BOOL           bUseLines;
122 BOOL           bUseAntiAlias;
123 int            iTexQuality;
124 int            iUsePalTextures=1;
125 BOOL           bSnapShot=FALSE;
126 BOOL           bSmallAlpha=FALSE;
127 int            iShowFPS=0;
128 BOOL           bGteAccuracy;
129 
130 // OGL extension support
131 
132 int                iForceVSync=-1;
133 int                iUseExts=0;
134 BOOL               bGLExt;
135 BOOL               bGLFastMovie=FALSE;
136 BOOL               bGLSoft;
137 BOOL               bGLBlend;
138 #if defined (_MACGL) // always supported on OSX > 10.4.3
139 #define glBlendEquationEXTEx glBlendEquationEXT
140 #define glColorTableEXTEx glColorTableEXT
141 #else
142 PFNGLBLENDEQU      glBlendEquationEXTEx=NULL;
143 PFNGLCOLORTABLEEXT glColorTableEXTEx=NULL;
144 #endif
145 // gfx card buffer infos
146 
147 int            iDepthFunc=0;
148 int            iZBufferDepth=0;
149 GLbitfield     uiBufferBits=GL_COLOR_BUFFER_BIT;
150 
151 ////////////////////////////////////////////////////////////////////////
152 // Set OGL pixel format
153 ////////////////////////////////////////////////////////////////////////
154 
155 #ifdef _WINDOWS
bSetupPixelFormat(HDC hDC)156 BOOL bSetupPixelFormat(HDC hDC)
157 {
158  int pixelformat;
159  static PIXELFORMATDESCRIPTOR pfd =
160   {
161    sizeof(PIXELFORMATDESCRIPTOR),    // size of this pfd
162     1,                               // version number
163     PFD_DRAW_TO_WINDOW |             // support window
164       PFD_SUPPORT_OPENGL |           // support OpenGL
165       PFD_DOUBLEBUFFER,              // double buffered
166     PFD_TYPE_RGBA,                   // RGBA type
167     16,                              // 16-bit color depth  (adjusted later)
168     0, 0, 0, 0, 0, 0,                // color bits ignored
169     0,                               // no alpha buffer
170     0,                               // shift bit ignored
171     0,                               // no accumulation buffer
172     0, 0, 0, 0,                      // accum bits ignored
173     0,                               // z-buffer
174     0,
175     0,                               // no auxiliary buffer
176     PFD_MAIN_PLANE,                  // main layer
177     0,                               // reserved
178     0, 0, 0                          // layer masks ignored
179   };
180 
181  pfd.cColorBits=iColDepth;                             // set user color depth
182  pfd.cDepthBits=iZBufferDepth;                         // set user zbuffer (by psx mask)
183 
184  if((pixelformat=ChoosePixelFormat(hDC,&pfd))==0)
185   {
186    MessageBox(NULL,"ChoosePixelFormat failed","Error",MB_OK);
187    return FALSE;
188   }
189 
190  if(SetPixelFormat(hDC,pixelformat, &pfd)==FALSE)
191   {
192    MessageBox(NULL,"SetPixelFormat failed","Error",MB_OK);
193    return FALSE;
194   }
195 
196  return TRUE;
197 }
198 #endif
199 
200 ////////////////////////////////////////////////////////////////////////
201 // Get extension infos (f.e. pal textures / packed pixels)
202 ////////////////////////////////////////////////////////////////////////
203 
GetExtInfos(void)204 void GetExtInfos(void)
205 {
206  BOOL bPacked=FALSE;                                   // default: no packed pixel support
207 
208  bGLExt=FALSE;                                         // default: no extensions
209  bGLFastMovie=FALSE;
210 
211  if(strstr((char *)glGetString(GL_EXTENSIONS),         // packed pixels available?
212     "GL_EXT_packed_pixels"))
213   bPacked=TRUE;                                        // -> ok
214 
215  if(bPacked && bUse15bitMdec)                          // packed available and 15bit mdec wanted?
216   bGLFastMovie=TRUE;                                   // -> ok
217 
218  if(bPacked && (iTexQuality==1 || iTexQuality==2))     // packed available and 16 bit texture format?
219   {
220    bGLFastMovie=TRUE;                                  // -> ok
221    bGLExt=TRUE;
222   }
223 
224  if(iUseExts &&                                        // extension support wanted?
225     (strstr((char *)glGetString(GL_EXTENSIONS),
226      "GL_EXT_texture_edge_clamp") ||
227      strstr((char *)glGetString(GL_EXTENSIONS),        // -> check clamp support, if yes: use it
228      "GL_SGIS_texture_edge_clamp")))
229       iClampType=GL_TO_EDGE_CLAMP;
230  else iClampType=GL_CLAMP;
231 
232 #if !defined (_MACGL) // OSX > 10.4.3 defines this
233  glColorTableEXTEx=(PFNGLCOLORTABLEEXT)NULL;           // init ogl palette func pointer
234 #endif
235 
236 #ifndef __sun
237  if(iGPUHeight!=1024 &&                                // no pal textures in ZN mode (height=1024)!
238     strstr((char *)glGetString(GL_EXTENSIONS),         // otherwise: check ogl support
239     "GL_EXT_paletted_texture"))
240   {
241    iUsePalTextures=1;                                  // -> wow, supported, get func pointer
242 
243 #ifdef _WINDOWS
244    glColorTableEXTEx=(PFNGLCOLORTABLEEXT)wglGetProcAddress("glColorTableEXT");
245 #elif defined (_MACGL)
246     // no prob, done already in OSX > 10.4.3
247 #else
248    glColorTableEXTEx=(PFNGLCOLORTABLEEXT)glXGetProcAddress("glColorTableEXT");
249 #endif
250 
251    if(glColorTableEXTEx==NULL) iUsePalTextures=0;      // -> ha, cheater... no func, no support
252 
253   }
254  else iUsePalTextures=0;
255 #else
256  iUsePalTextures=0;
257 #endif
258 }
259 
260 ////////////////////////////////////////////////////////////////////////
261 // Setup some stuff depending on user settings or in-game toggle
262 ////////////////////////////////////////////////////////////////////////
263 
SetExtGLFuncs(void)264 void SetExtGLFuncs(void)
265 {
266  //----------------------------------------------------//
267 
268  SetFixes();                                           // update fix infos
269 
270  //----------------------------------------------------//
271 
272 #ifdef _WINDOWS
273  if((iForceVSync>=0) &&                                // force vsync?
274     strstr((char *)glGetString(GL_EXTENSIONS),         // and extension available?
275     "WGL_EXT_swap_control"))
276   {
277    PFNWGLSWAPINTERVALFARPROC wglSwapIntervalEXT=
278     (PFNWGLSWAPINTERVALFARPROC)wglGetProcAddress("wglSwapIntervalEXT");
279 
280    if(wglSwapIntervalEXT) wglSwapIntervalEXT(iForceVSync);
281   }
282 #endif
283 #ifdef _MACGL
284  SetVSync(iForceVSync);
285 #endif
286  if(iUseExts && !(dwActFixes&1024) &&                  // extensions wanted? and not turned off by game fix?
287     strstr((char *)glGetString(GL_EXTENSIONS),         // and blend_subtract available?
288     "GL_EXT_blend_subtract"))
289      {                                                 // -> get ogl blend function pointer
290 #ifdef _WINDOWS
291       glBlendEquationEXTEx=(PFNGLBLENDEQU)wglGetProcAddress("glBlendEquationEXT");
292 #elif defined(_MACGL)
293     // no prob, OSX > 10.4.3 has this
294 #else
295       glBlendEquationEXTEx=(PFNGLBLENDEQU)glXGetProcAddress("glBlendEquationEXT");
296 #endif
297      }
298  else                                                  // no subtract blending?
299   {
300    if(glBlendEquationEXTEx)                            // -> change to additive blending (if subract was active)
301     glBlendEquationEXTEx(FUNC_ADD_EXT);
302 #if !defined(_MACGL) // BTW, why set to null? strange...
303    glBlendEquationEXTEx=(PFNGLBLENDEQU)NULL;           // -> no more blend function pointer
304 #endif
305   }
306 
307  //----------------------------------------------------//
308 
309  if(iUseExts && bAdvancedBlend &&                      // advanced blending wanted ?
310     strstr((char *)glGetString(GL_EXTENSIONS),         // and extension avail?
311            "GL_EXT_texture_env_combine"))
312   {
313    bUseMultiPass=FALSE;bGLBlend=TRUE;                  // -> no need for 2 passes, perfect
314 
315    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, COMBINE_EXT);
316    glTexEnvf(GL_TEXTURE_ENV, COMBINE_RGB_EXT, GL_MODULATE);
317    glTexEnvf(GL_TEXTURE_ENV, COMBINE_ALPHA_EXT, GL_MODULATE);
318    glTexEnvf(GL_TEXTURE_ENV, RGB_SCALE_EXT, 2.0f);
319   }
320  else                                                  // no advanced blending wanted/available:
321   {
322    if(bAdvancedBlend) bUseMultiPass=TRUE;              // -> pseudo-advanced with 2 passes
323    else               bUseMultiPass=FALSE;             // -> or simple 'bright color' mode
324    bGLBlend=FALSE;                                     // -> no ext blending!
325 
326    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
327   }
328 
329  //----------------------------------------------------//
330  // init standard tex quality 0-2, and big alpha mode 3
331 
332  if(!(dwActFixes&0x4000) && iFilterType && iTexQuality>=3)
333       bSmallAlpha=TRUE;
334  else bSmallAlpha=FALSE;
335 
336  if(bOpaquePass)                                        // opaque mode?
337   {
338    if(dwActFixes&32)
339     {
340      TCF[0]=CP8RGBA_0;
341      PalTexturedColourFn=CP8RGBA;                      // -> init col func
342     }
343    else
344     {
345      TCF[0]=XP8RGBA_0;
346      PalTexturedColourFn=XP8RGBA;                      // -> init col func
347     }
348 
349    TCF[1]=XP8RGBA_1;
350    glAlphaFunc(GL_GREATER,0.49f);
351   }
352  else                                                  // no opaque mode?
353   {
354    TCF[0]=TCF[1]=P8RGBA;
355    PalTexturedColourFn=P8RGBA;                         // -> init col func
356    glAlphaFunc(GL_NOTEQUAL,0);                         // --> set alpha func
357   }
358 
359  //----------------------------------------------------//
360 
361  LoadSubTexFn=LoadSubTexturePageSort;                  // init load tex ptr
362 
363  giWantedFMT=GL_RGBA;                                  // init ogl tex format
364 
365  switch(iTexQuality)                                   // -> quality:
366   {
367    //--------------------------------------------------//
368    case 0:                                             // -> don't care
369     giWantedRGBA=4;
370     giWantedTYPE=GL_UNSIGNED_BYTE;
371     break;
372    //--------------------------------------------------//
373    case 1:                                             // -> R4G4B4A4
374     if(bGLExt)
375      {
376       giWantedRGBA=GL_RGBA4;
377       giWantedTYPE=GL_UNSIGNED_SHORT_4_4_4_4_EXT;
378       LoadSubTexFn=LoadPackedSubTexturePageSort;
379       if(bOpaquePass)
380        {
381         if(dwActFixes&32) PTCF[0]=CP4RGBA_0;
382         else              PTCF[0]=XP4RGBA_0;
383         PTCF[1]=XP4RGBA_1;
384        }
385       else
386        {
387         PTCF[0]=PTCF[1]=P4RGBA;
388        }
389      }
390     else
391      {
392       giWantedRGBA=GL_RGBA4;
393       giWantedTYPE=GL_UNSIGNED_BYTE;
394      }
395     break;
396    //--------------------------------------------------//
397    case 2:                                             // -> R5B5G5A1
398     if(bGLExt)
399      {
400       giWantedRGBA=GL_RGB5_A1;
401       giWantedTYPE=GL_UNSIGNED_SHORT_5_5_5_1_EXT;
402       LoadSubTexFn=LoadPackedSubTexturePageSort;
403       if(bOpaquePass)
404        {
405         if(dwActFixes&32) PTCF[0]=CP5RGBA_0;
406         else              PTCF[0]=XP5RGBA_0;
407         PTCF[1]=XP5RGBA_1;
408        }
409       else
410        {
411         PTCF[0]=PTCF[1]=P5RGBA;
412        }
413      }
414     else
415      {
416       giWantedRGBA=GL_RGB5_A1;giWantedTYPE=GL_UNSIGNED_BYTE;
417      }
418     break;
419    //--------------------------------------------------//
420    case 3:                                             // -> R8G8B8A8
421     giWantedRGBA=GL_RGBA8;
422     giWantedTYPE=GL_UNSIGNED_BYTE;
423 
424     if(bSmallAlpha)
425      {
426       if(bOpaquePass)                                  // opaque mode?
427        {
428         if(dwActFixes&32) {TCF[0]=CP8RGBAEx_0;PalTexturedColourFn=CP8RGBAEx;}
429         else              {TCF[0]=XP8RGBAEx_0;PalTexturedColourFn=XP8RGBAEx;}
430         TCF[1]=XP8RGBAEx_1;
431        }
432      }
433 
434     break;
435    //--------------------------------------------------//
436    case 4:                                             // -> R8G8B8A8
437     giWantedRGBA = GL_RGBA8;
438     giWantedTYPE = GL_UNSIGNED_BYTE;
439 
440     if(strstr((char *)glGetString(GL_EXTENSIONS),      // and extension avail?
441               "GL_EXT_bgra"))
442      {
443       giWantedFMT  = GL_BGRA_EXT;
444 
445       if(bOpaquePass)                                  // opaque mode?
446        {
447         if(bSmallAlpha)
448          {
449           if(dwActFixes&32) {TCF[0]=CP8BGRAEx_0;PalTexturedColourFn=CP8RGBAEx;}
450           else              {TCF[0]=XP8BGRAEx_0;PalTexturedColourFn=XP8RGBAEx;}
451           TCF[1]=XP8BGRAEx_1;
452          }
453         else
454          {
455           if(dwActFixes&32) {TCF[0]=CP8BGRA_0;PalTexturedColourFn=CP8RGBA;}
456           else              {TCF[0]=XP8BGRA_0;PalTexturedColourFn=XP8RGBA;}
457           TCF[1]=XP8BGRA_1;
458          }
459        }
460       else                                             // no opaque mode?
461        {
462         TCF[0]=TCF[1]=P8BGRA;                          // -> init col func
463        }
464      }
465     else
466      {
467       iTexQuality=3;
468       if(bSmallAlpha)
469        {
470         if(bOpaquePass)                                 // opaque mode?
471          {
472           if(dwActFixes&32) {TCF[0]=CP8RGBAEx_0;PalTexturedColourFn=CP8RGBAEx;}
473           else              {TCF[0]=XP8RGBAEx_0;PalTexturedColourFn=XP8RGBAEx;}
474           TCF[1]=XP8RGBAEx_1;
475          }
476        }
477      }
478 
479     break;
480    //--------------------------------------------------//
481   }
482 
483  bBlendEnable=FALSE;                                   // init blending: off
484  glDisable(GL_BLEND);
485 
486  SetScanTrans();                                       // init scan lines (if wanted)
487 }
488 
489 ////////////////////////////////////////////////////////////////////////
490 // setup scan lines
491 ////////////////////////////////////////////////////////////////////////
492 
493 #define R_TSP 0x00,0x45,0x00,0xff
494 #define G_TSP 0x00,0x00,0x45,0xff
495 #define B_TSP 0x45,0x00,0x00,0xff
496 #define O_TSP 0x45,0x45,0x45,0xff
497 #define N_TSP 0x00,0x00,0x00,0xff
498 
499 GLuint  gTexScanName=0;
500 
501 GLubyte texscan[4][16]=
502 {
503 {R_TSP, G_TSP, B_TSP, N_TSP},
504 {O_TSP, N_TSP, O_TSP, N_TSP},
505 {B_TSP, N_TSP, R_TSP, G_TSP},
506 {O_TSP, N_TSP, O_TSP, N_TSP}
507 };
508 
CreateScanLines(void)509 void CreateScanLines(void)
510 {
511  if(iUseScanLines)
512   {
513    int y;
514    if(iScanBlend<0)                                    // special scan mask mode
515     {
516      glGenTextures(1, &gTexScanName);
517      glBindTexture(GL_TEXTURE_2D, gTexScanName);
518 
519      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
520      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
521      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
522      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
523      glTexImage2D(GL_TEXTURE_2D, 0, 4, 4, 4, 0,GL_RGBA, GL_UNSIGNED_BYTE, texscan);
524     }
525    else                                                // otherwise simple lines in a display list
526     {
527      uiScanLine=glGenLists(1);
528      glNewList(uiScanLine,GL_COMPILE);
529      #ifdef _MACGL
530       // not mac specific, just commenting out to be friendly
531       // use it if you like
532       // this draws anti-aliased lines with user-chosen color
533       glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_CURRENT_BIT);
534       glEnable(GL_BLEND | GL_LINE_SMOOTH);
535       glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
536       glColor4f(iScanlineColor[0],iScanlineColor[1],iScanlineColor[2],iScanlineColor[3]);
537       glBegin(GL_LINES);
538       for(y=0;y<iResY;y+=2)
539       {
540        glVertex2f(0,y);
541        glVertex2f(iResX,y);
542       }
543       glEnd();
544       glPopAttrib();
545 	 #else
546 	      for(y=0;y<iResY;y+=2)
547       {
548        glBegin(GL_QUADS);
549          glVertex2f(0,y);
550          glVertex2f(iResX,y);
551          glVertex2f(iResX,y+1);
552          glVertex2f(0,y+1);
553        glEnd();
554       }
555 
556     #endif
557     glEndList();
558     }
559   }
560 }
561 
562 ////////////////////////////////////////////////////////////////////////
563 // Initialize OGL
564 ////////////////////////////////////////////////////////////////////////
565 
566 #ifdef _WINDOWS
567 HGLRC GLCONTEXT=NULL;
568 #endif
569 
GLinitialize()570 int GLinitialize()
571 {
572 #ifdef _WINDOWS
573  HGLRC objectRC;
574  // init
575  dcGlobal = GetDC(hWWindow);                           // FIRST: dc/rc stuff
576  objectRC = wglCreateContext(dcGlobal);
577  GLCONTEXT=objectRC;
578  wglMakeCurrent(dcGlobal, objectRC);
579  // CheckWGLExtensions(dcGlobal);
580  if(bWindowMode) ReleaseDC(hWWindow,dcGlobal);         // win mode: release dc again
581 #endif
582 #if defined (_MACGL)
583  BringContextForward();
584 #endif
585  glViewport(rRatioRect.left,                           // init viewport by ratio rect
586             iResY-(rRatioRect.top+rRatioRect.bottom),
587             rRatioRect.right,
588             rRatioRect.bottom);
589 
590  glScissor(0, 0, iResX, iResY);                        // init clipping (fullscreen)
591  glEnable(GL_SCISSOR_TEST);
592 
593 #ifndef OWNSCALE
594  glMatrixMode(GL_TEXTURE);                             // init psx tex sow and tow if not "ownscale"
595  glLoadIdentity();
596  glScalef(1.0f/255.99f,1.0f/255.99f,1.0f);             // geforce precision hack
597 #endif
598 
599  glMatrixMode(GL_PROJECTION);                          // init projection with psx resolution
600  glLoadIdentity();
601  glOrtho(0,PSXDisplay.DisplayMode.x,
602          PSXDisplay.DisplayMode.y, 0, -1, 1);
603 
604  if(iZBufferDepth)                                     // zbuffer?
605   {
606    uiBufferBits=GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT;
607    glEnable(GL_DEPTH_TEST);
608    glDepthFunc(GL_ALWAYS);
609    iDepthFunc=1;
610   }
611  else                                                  // no zbuffer?
612   {
613    uiBufferBits=GL_COLOR_BUFFER_BIT;
614    glDisable(GL_DEPTH_TEST);
615   }
616 
617  glClearColor(0.0f, 0.0f, 0.0f, 0.0f);                 // first buffer clear
618  glClear(uiBufferBits);
619 
620  if(bUseLines)                                         // funny lines
621   {
622    glPolygonMode(GL_FRONT, GL_LINE);
623    glPolygonMode(GL_BACK, GL_LINE);
624   }
625  else                                                  // or the real filled thing
626   {
627    glPolygonMode(GL_FRONT, GL_FILL);
628    glPolygonMode(GL_BACK, GL_FILL);
629   }
630 
631  MakeDisplayLists();                                   // lists for menu/opaque
632  GetExtInfos();                                        // get ext infos
633  SetExtGLFuncs();                                      // init all kind of stuff (tex function pointers)
634 
635  glEnable(GL_ALPHA_TEST);                              // wanna alpha test
636 
637  if(!bUseAntiAlias)                                    // no anti-alias (default)
638   {
639    glDisable(GL_LINE_SMOOTH);
640    glDisable(GL_POLYGON_SMOOTH);
641    glDisable(GL_POINT_SMOOTH);
642   }
643  else                                                  // wanna try it? glitches galore...
644   {
645    glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);
646    glEnable(GL_LINE_SMOOTH);
647    glEnable(GL_POLYGON_SMOOTH);
648    glEnable(GL_POINT_SMOOTH);
649    glHint(GL_LINE_SMOOTH_HINT,GL_NICEST);
650    glHint(GL_POINT_SMOOTH_HINT,GL_NICEST);
651    glHint(GL_POLYGON_SMOOTH_HINT,GL_NICEST);
652   }
653 
654  ubGloAlpha=127;                                       // init some drawing vars
655  ubGloColAlpha=127;
656  TWin.UScaleFactor = 1;
657  TWin.VScaleFactor = 1;
658  bDrawMultiPass=FALSE;
659  bTexEnabled=FALSE;
660  bUsingTWin=FALSE;
661 
662  if(bDrawDither)  glEnable(GL_DITHER);                 // dither mode
663  else             glDisable(GL_DITHER);
664 
665  glDisable(GL_FOG);                                    // turn all (currently) unused modes off
666  glDisable(GL_LIGHTING);
667  glDisable(GL_LOGIC_OP);
668  glDisable(GL_STENCIL_TEST);
669  glDisable(GL_TEXTURE_1D);
670  glDisable(GL_TEXTURE_2D);
671  glDisable(GL_CULL_FACE);
672 
673  glPixelTransferi(GL_RED_SCALE, 1);                    // to be sure:
674  glPixelTransferi(GL_RED_BIAS, 0);                     // init more OGL vals
675  glPixelTransferi(GL_GREEN_SCALE, 1);
676  glPixelTransferi(GL_GREEN_BIAS, 0);
677  glPixelTransferi(GL_BLUE_SCALE, 1);
678  glPixelTransferi(GL_BLUE_BIAS, 0);
679  glPixelTransferi(GL_ALPHA_SCALE, 1);
680  glPixelTransferi(GL_ALPHA_BIAS, 0);
681 
682 #ifdef _WINDOWS
683                                                        // detect Windows hw/sw mode (just for info)
684  if(!strcmp("Microsoft Corporation",(LPTSTR)glGetString(GL_VENDOR)) &&
685     !strcmp("GDI Generic",          (LPTSTR)glGetString(GL_RENDERER)))
686       bGLSoft=TRUE;
687  else bGLSoft=FALSE;
688 #endif
689 
690  glFlush();                                            // we are done...
691  glFinish();
692 
693  CreateScanLines();                                    // setup scanline stuff (if wanted)
694 
695  CheckTextureMemory();                                 // check available tex memory
696 
697  if(bKeepRatio) SetAspectRatio();                      // set ratio
698 
699  if(iShowFPS)                                          // user wants FPS display on startup?
700   {
701    ulKeybits|=KEY_SHOWFPS;                             // -> ok, turn display on
702    szDispBuf[0]=0;
703    BuildDispMenu(0);
704   }
705 
706  bIsFirstFrame = FALSE;                                // we have survived the first frame :)
707 
708  return 0;
709 }
710 
711 ////////////////////////////////////////////////////////////////////////
712 // clean up OGL stuff
713 ////////////////////////////////////////////////////////////////////////
714 
GLcleanup()715 void GLcleanup()
716 {
717  KillDisplayLists();                                   // bye display lists
718 
719  if(iUseScanLines)                                     // scanlines used?
720   {
721    if(iScanBlend<0)
722     {
723      if(gTexScanName!=0)                               // some scanline tex?
724       glDeleteTextures(1, &gTexScanName);              // -> delete it
725      gTexScanName=0;
726     }
727    else glDeleteLists(uiScanLine,1);                   // otherwise del scanline display list
728   }
729 
730  CleanupTextureStore();                                // bye textures
731 
732 #ifdef _WINDOWS
733  wglMakeCurrent(NULL, NULL);                           // bye context
734  if(GLCONTEXT) wglDeleteContext(GLCONTEXT);
735  if(!bWindowMode && dcGlobal)
736   ReleaseDC(hWWindow,dcGlobal);
737 #endif
738 }
739 
740 ////////////////////////////////////////////////////////////////////////
741 ////////////////////////////////////////////////////////////////////////
742 ////////////////////////////////////////////////////////////////////////
743 
744 ////////////////////////////////////////////////////////////////////////
745 ////////////////////////////////////////////////////////////////////////
746 ////////////////////////////////////////////////////////////////////////
747 
748 ////////////////////////////////////////////////////////////////////////
749 // Offset stuff
750 ////////////////////////////////////////////////////////////////////////
751 
752 // please note: it is hardly do-able in a hw/accel plugin to get the
753 //              real psx polygon coord mapping right... the following
754 //              works not to bad with many games, though
755 
CheckCoord4()756 static __inline BOOL CheckCoord4()
757 {
758  if(lx0<0)
759   {
760    if(((lx1-lx0)>CHKMAX_X) ||
761       ((lx2-lx0)>CHKMAX_X))
762     {
763      if(lx3<0)
764       {
765        if((lx1-lx3)>CHKMAX_X) return TRUE;
766        if((lx2-lx3)>CHKMAX_X) return TRUE;
767       }
768     }
769   }
770  if(lx1<0)
771   {
772    if((lx0-lx1)>CHKMAX_X) return TRUE;
773    if((lx2-lx1)>CHKMAX_X) return TRUE;
774    if((lx3-lx1)>CHKMAX_X) return TRUE;
775   }
776  if(lx2<0)
777   {
778    if((lx0-lx2)>CHKMAX_X) return TRUE;
779    if((lx1-lx2)>CHKMAX_X) return TRUE;
780    if((lx3-lx2)>CHKMAX_X) return TRUE;
781   }
782  if(lx3<0)
783   {
784    if(((lx1-lx3)>CHKMAX_X) ||
785       ((lx2-lx3)>CHKMAX_X))
786     {
787      if(lx0<0)
788       {
789        if((lx1-lx0)>CHKMAX_X) return TRUE;
790        if((lx2-lx0)>CHKMAX_X) return TRUE;
791       }
792     }
793   }
794 
795 
796  if(ly0<0)
797   {
798    if((ly1-ly0)>CHKMAX_Y) return TRUE;
799    if((ly2-ly0)>CHKMAX_Y) return TRUE;
800   }
801  if(ly1<0)
802   {
803    if((ly0-ly1)>CHKMAX_Y) return TRUE;
804    if((ly2-ly1)>CHKMAX_Y) return TRUE;
805    if((ly3-ly1)>CHKMAX_Y) return TRUE;
806   }
807  if(ly2<0)
808   {
809    if((ly0-ly2)>CHKMAX_Y) return TRUE;
810    if((ly1-ly2)>CHKMAX_Y) return TRUE;
811    if((ly3-ly2)>CHKMAX_Y) return TRUE;
812   }
813  if(ly3<0)
814   {
815    if((ly1-ly3)>CHKMAX_Y) return TRUE;
816    if((ly2-ly3)>CHKMAX_Y) return TRUE;
817   }
818 
819  return FALSE;
820 }
821 
CheckCoord3()822 static __inline BOOL CheckCoord3()
823 {
824  if(lx0<0)
825   {
826    if((lx1-lx0)>CHKMAX_X) return TRUE;
827    if((lx2-lx0)>CHKMAX_X) return TRUE;
828   }
829  if(lx1<0)
830   {
831    if((lx0-lx1)>CHKMAX_X) return TRUE;
832    if((lx2-lx1)>CHKMAX_X) return TRUE;
833   }
834  if(lx2<0)
835   {
836    if((lx0-lx2)>CHKMAX_X) return TRUE;
837    if((lx1-lx2)>CHKMAX_X) return TRUE;
838   }
839  if(ly0<0)
840   {
841    if((ly1-ly0)>CHKMAX_Y) return TRUE;
842    if((ly2-ly0)>CHKMAX_Y) return TRUE;
843   }
844  if(ly1<0)
845   {
846    if((ly0-ly1)>CHKMAX_Y) return TRUE;
847    if((ly2-ly1)>CHKMAX_Y) return TRUE;
848   }
849  if(ly2<0)
850   {
851    if((ly0-ly2)>CHKMAX_Y) return TRUE;
852    if((ly1-ly2)>CHKMAX_Y) return TRUE;
853   }
854 
855  return FALSE;
856 }
857 
858 
CheckCoord2()859 static __inline BOOL CheckCoord2()
860 {
861  if(lx0<0)
862   {
863    if((lx1-lx0)>CHKMAX_X) return TRUE;
864   }
865  if(lx1<0)
866   {
867    if((lx0-lx1)>CHKMAX_X) return TRUE;
868   }
869  if(ly0<0)
870   {
871    if((ly1-ly0)>CHKMAX_Y) return TRUE;
872   }
873  if(ly1<0)
874   {
875    if((ly0-ly1)>CHKMAX_Y) return TRUE;
876   }
877 
878  return FALSE;
879 }
880 
881 /*
882 //Lewpys "offsetline" func:
883 
884 void offsetline(void)
885 {
886 	float x0, x1, y0, y1, oolength, xl, yl;
887 
888  if(bDisplayNotSet)
889   SetOGLDisplaySettings(1);
890 
891  if(!(dwActFixes&16))
892   {
893    if((lx0 & SIGNBIT)) lx0|=S_MASK;
894    else                lx0&=~S_MASK;
895    if((lx1 & SIGNBIT)) lx1|=S_MASK;
896    else                lx1&=~S_MASK;
897    if((ly0 & SIGNBIT)) ly0|=S_MASK;
898    else                ly0&=~S_MASK;
899    if((ly1 & SIGNBIT)) ly1|=S_MASK;
900    else                ly1&=~S_MASK;
901   }
902 
903  x0 = (float)(lx0 + PSXDisplay.CumulOffset.x);
904  x1 = (float)(lx1 + PSXDisplay.CumulOffset.x);
905  y0 = (float)(ly0 + PSXDisplay.CumulOffset.y);
906  y1 = (float)(ly1 + PSXDisplay.CumulOffset.y);
907 
908  oolength = (float)1/((float)sqrt((y1 - y0)*(y1 - y0) + (x1 - x0)*(x1 - x0)) * (float)2);
909 //	oolength = (float)1/((float)sqrt(((y1 - y0)*(y1 - y0) + (x1 - x0)*(x1 - x0)) * (float)2));
910 
911 	xl = (x1 - x0) * oolength;
912 	yl = (y1 - y0) * oolength;
913 
914 	x0 += 0.5f;
915 	x1 += 0.5f;
916 
917 	x0 -= xl - yl;
918 	x1 += xl + yl;
919 	y0 -= yl + xl;
920 	y1 += yl - xl;
921 
922 	vertex[0].x=x0;
923 	vertex[1].x=x1;
924 	vertex[0].y=y0;
925 	vertex[1].y=y1;
926 
927 	x0 -= yl * 2;
928 	x1 -= yl * 2;
929 	y0 += xl * 2;
930 	y1 += xl * 2;
931 
932 	vertex[2].x=x1;
933 	vertex[3].x=x0;
934 	vertex[2].y=y1;
935 	vertex[3].y=y0;
936 }
937 */
938 
939 
940 // Pete's way: a very easy (and hopefully fast) approach for lines
941 // without sqrt... using a small float -> short cast trick :)
942 
943 #define VERTEX_OFFX 0.2f
944 #define VERTEX_OFFY 0.2f
945 
offsetline(void)946 BOOL offsetline(void)
947 {
948  short x0,x1,y0,y1,dx,dy;float px,py;
949 
950  if(bDisplayNotSet)
951   SetOGLDisplaySettings(1);
952 
953  if(!(dwActFixes&16))
954   {
955    lx0=(short)(((int)lx0<<SIGNSHIFT)>>SIGNSHIFT);
956    lx1=(short)(((int)lx1<<SIGNSHIFT)>>SIGNSHIFT);
957    ly0=(short)(((int)ly0<<SIGNSHIFT)>>SIGNSHIFT);
958    ly1=(short)(((int)ly1<<SIGNSHIFT)>>SIGNSHIFT);
959 
960    if(CheckCoord2()) return TRUE;
961   }
962 
963  x0 = (lx0 + PSXDisplay.CumulOffset.x)+1;
964  x1 = (lx1 + PSXDisplay.CumulOffset.x)+1;
965  y0 = (ly0 + PSXDisplay.CumulOffset.y)+1;
966  y1 = (ly1 + PSXDisplay.CumulOffset.y)+1;
967 
968  dx=x1-x0;
969  dy=y1-y0;
970 
971  if(dx>=0)
972   {
973    if(dy>=0)
974     {
975      px=0.5f;
976           if(dx>dy) py=-0.5f;
977      else if(dx<dy) py= 0.5f;
978      else           py= 0.0f;
979     }
980    else
981     {
982      py=-0.5f;
983      dy=-dy;
984           if(dx>dy) px= 0.5f;
985      else if(dx<dy) px=-0.5f;
986      else           px= 0.0f;
987     }
988   }
989  else
990   {
991    if(dy>=0)
992     {
993      py=0.5f;
994      dx=-dx;
995           if(dx>dy) px=-0.5f;
996      else if(dx<dy) px= 0.5f;
997      else           px= 0.0f;
998     }
999    else
1000     {
1001      px=-0.5f;
1002           if(dx>dy) py=-0.5f;
1003      else if(dx<dy) py= 0.5f;
1004      else           py= 0.0f;
1005     }
1006   }
1007 
1008  vertex[0].x=(short)((float)x0-px);
1009  vertex[3].x=(short)((float)x0+py);
1010 
1011  vertex[0].y=(short)((float)y0-py);
1012  vertex[3].y=(short)((float)y0-px);
1013 
1014  vertex[1].x=(short)((float)x1-py);
1015  vertex[2].x=(short)((float)x1+px);
1016 
1017  vertex[1].y=(short)((float)y1+px);
1018  vertex[2].y=(short)((float)y1+py);
1019 
1020  if(vertex[0].x==vertex[3].x &&                        // ortho rect? done
1021     vertex[1].x==vertex[2].x &&
1022     vertex[0].y==vertex[1].y &&
1023     vertex[2].y==vertex[3].y) return FALSE;
1024  if(vertex[0].x==vertex[1].x &&
1025     vertex[2].x==vertex[3].x &&
1026     vertex[0].y==vertex[3].y &&
1027     vertex[1].y==vertex[2].y) return FALSE;
1028 
1029  vertex[0].x-=VERTEX_OFFX;                             // otherwise a small offset
1030  vertex[0].y-=VERTEX_OFFY;                             // to get better accuracy
1031  vertex[1].x-=VERTEX_OFFX;
1032  vertex[1].y-=VERTEX_OFFY;
1033  vertex[2].x-=VERTEX_OFFX;
1034  vertex[2].y-=VERTEX_OFFY;
1035  vertex[3].x-=VERTEX_OFFX;
1036  vertex[3].y-=VERTEX_OFFY;
1037 
1038  return FALSE;
1039 }
1040 
1041 /////////////////////////////////////////////////////////
1042 
offset2(void)1043 BOOL offset2(void)
1044 {
1045  if(bDisplayNotSet)
1046   SetOGLDisplaySettings(1);
1047 
1048  if(!(dwActFixes&16))
1049   {
1050    lx0=(short)(((int)lx0<<SIGNSHIFT)>>SIGNSHIFT);
1051    lx1=(short)(((int)lx1<<SIGNSHIFT)>>SIGNSHIFT);
1052    ly0=(short)(((int)ly0<<SIGNSHIFT)>>SIGNSHIFT);
1053    ly1=(short)(((int)ly1<<SIGNSHIFT)>>SIGNSHIFT);
1054 
1055    if(CheckCoord2()) return TRUE;
1056   }
1057 
1058  if(!getGteVertex(lx0, ly0, &vertex[0].x, &vertex[0].y))
1059  {
1060 	vertex[0].x=lx0;
1061 	vertex[0].y=ly0;
1062  }
1063  if(!getGteVertex(lx1, ly1, &vertex[1].x, &vertex[1].y))
1064  {
1065 	vertex[1].x=lx1;
1066 	vertex[1].y=ly1;
1067  }
1068 
1069  vertex[0].x+=PSXDisplay.CumulOffset.x;
1070  vertex[1].x+=PSXDisplay.CumulOffset.x;
1071  vertex[0].y+=PSXDisplay.CumulOffset.y;
1072  vertex[1].y+=PSXDisplay.CumulOffset.y;
1073 
1074  return FALSE;
1075 }
1076 
1077 /////////////////////////////////////////////////////////
1078 
offset3(void)1079 BOOL offset3(void)
1080 {
1081  if(bDisplayNotSet)
1082   SetOGLDisplaySettings(1);
1083 
1084  if(!(dwActFixes&16))
1085   {
1086    lx0=(short)(((int)lx0<<SIGNSHIFT)>>SIGNSHIFT);
1087    lx1=(short)(((int)lx1<<SIGNSHIFT)>>SIGNSHIFT);
1088    lx2=(short)(((int)lx2<<SIGNSHIFT)>>SIGNSHIFT);
1089    ly0=(short)(((int)ly0<<SIGNSHIFT)>>SIGNSHIFT);
1090    ly1=(short)(((int)ly1<<SIGNSHIFT)>>SIGNSHIFT);
1091    ly2=(short)(((int)ly2<<SIGNSHIFT)>>SIGNSHIFT);
1092 
1093    if(CheckCoord3()) return TRUE;
1094   }
1095 
1096  if(!getGteVertex(lx0, ly0, &vertex[0].x, &vertex[0].y))
1097  {
1098 	vertex[0].x=lx0;
1099 	vertex[0].y=ly0;
1100  }
1101  if(!getGteVertex(lx1, ly1, &vertex[1].x, &vertex[1].y))
1102  {
1103 	vertex[1].x=lx1;
1104 	vertex[1].y=ly1;
1105  }
1106  if(!getGteVertex(lx2, ly2, &vertex[2].x, &vertex[2].y))
1107  {
1108 	vertex[2].x=lx2;
1109 	vertex[2].y=ly2;
1110  }
1111 
1112  vertex[0].x+=PSXDisplay.CumulOffset.x;
1113  vertex[1].x+=PSXDisplay.CumulOffset.x;
1114  vertex[2].x+=PSXDisplay.CumulOffset.x;
1115  vertex[0].y+=PSXDisplay.CumulOffset.y;
1116  vertex[1].y+=PSXDisplay.CumulOffset.y;
1117  vertex[2].y+=PSXDisplay.CumulOffset.y;
1118 
1119  return FALSE;
1120 }
1121 
1122 /////////////////////////////////////////////////////////
1123 
offset4(void)1124 BOOL offset4(void)
1125 {
1126  if(bDisplayNotSet)
1127   SetOGLDisplaySettings(1);
1128 
1129  if(!(dwActFixes&16))
1130   {
1131    lx0=(short)(((int)lx0<<SIGNSHIFT)>>SIGNSHIFT);
1132    lx1=(short)(((int)lx1<<SIGNSHIFT)>>SIGNSHIFT);
1133    lx2=(short)(((int)lx2<<SIGNSHIFT)>>SIGNSHIFT);
1134    lx3=(short)(((int)lx3<<SIGNSHIFT)>>SIGNSHIFT);
1135    ly0=(short)(((int)ly0<<SIGNSHIFT)>>SIGNSHIFT);
1136    ly1=(short)(((int)ly1<<SIGNSHIFT)>>SIGNSHIFT);
1137    ly2=(short)(((int)ly2<<SIGNSHIFT)>>SIGNSHIFT);
1138    ly3=(short)(((int)ly3<<SIGNSHIFT)>>SIGNSHIFT);
1139 
1140    if(CheckCoord4()) return TRUE;
1141   }
1142 
1143  if(!getGteVertex(lx0, ly0, &vertex[0].x, &vertex[0].y))
1144  {
1145 	vertex[0].x=lx0;
1146 	vertex[0].y=ly0;
1147  }
1148  if(!getGteVertex(lx1, ly1, &vertex[1].x, &vertex[1].y))
1149  {
1150 	vertex[1].x=lx1;
1151 	vertex[1].y=ly1;
1152  }
1153  if(!getGteVertex(lx2, ly2, &vertex[2].x, &vertex[2].y))
1154  {
1155 	vertex[2].x=lx2;
1156 	vertex[2].y=ly2;
1157  }
1158  if(!getGteVertex(lx3, ly3, &vertex[3].x, &vertex[3].y))
1159  {
1160 	vertex[3].x=lx3;
1161 	vertex[3].y=ly3;
1162  }
1163 
1164  vertex[0].x+=PSXDisplay.CumulOffset.x;
1165  vertex[1].x+=PSXDisplay.CumulOffset.x;
1166  vertex[2].x+=PSXDisplay.CumulOffset.x;
1167  vertex[3].x+=PSXDisplay.CumulOffset.x;
1168  vertex[0].y+=PSXDisplay.CumulOffset.y;
1169  vertex[1].y+=PSXDisplay.CumulOffset.y;
1170  vertex[2].y+=PSXDisplay.CumulOffset.y;
1171  vertex[3].y+=PSXDisplay.CumulOffset.y;
1172 
1173  return FALSE;
1174 }
1175 
1176 /////////////////////////////////////////////////////////
1177 
offsetST(void)1178 void offsetST(void)
1179 {
1180  if(bDisplayNotSet)
1181   SetOGLDisplaySettings(1);
1182 
1183  if(!(dwActFixes&16))
1184   {
1185    lx0=(short)(((int)lx0<<SIGNSHIFT)>>SIGNSHIFT);
1186    ly0=(short)(((int)ly0<<SIGNSHIFT)>>SIGNSHIFT);
1187 
1188    if(lx0<-512 && PSXDisplay.DrawOffset.x<=-512)
1189     lx0+=2048;
1190 
1191    if(ly0<-512 && PSXDisplay.DrawOffset.y<=-512)
1192     ly0+=2048;
1193   }
1194 
1195  ly1 = ly0;
1196  ly2 = ly3 = ly0+sprtH;
1197  lx3 = lx0;
1198  lx1 = lx2 = lx0+sprtW;
1199 
1200  vertex[0].x=lx0+PSXDisplay.CumulOffset.x;
1201  vertex[1].x=lx1+PSXDisplay.CumulOffset.x;
1202  vertex[2].x=lx2+PSXDisplay.CumulOffset.x;
1203  vertex[3].x=lx3+PSXDisplay.CumulOffset.x;
1204  vertex[0].y=ly0+PSXDisplay.CumulOffset.y;
1205  vertex[1].y=ly1+PSXDisplay.CumulOffset.y;
1206  vertex[2].y=ly2+PSXDisplay.CumulOffset.y;
1207  vertex[3].y=ly3+PSXDisplay.CumulOffset.y;
1208 }
1209 
1210 /////////////////////////////////////////////////////////
1211 
offsetScreenUpload(int Position)1212 void offsetScreenUpload(int Position)
1213 {
1214  if(bDisplayNotSet)
1215   SetOGLDisplaySettings(1);
1216 
1217  if(Position==-1)
1218   {
1219    int lmdx,lmdy;
1220 
1221    lmdx=xrUploadArea.x0;
1222    lmdy=xrUploadArea.y0;
1223 
1224    lx0-=lmdx;
1225    ly0-=lmdy;
1226    lx1-=lmdx;
1227    ly1-=lmdy;
1228    lx2-=lmdx;
1229    ly2-=lmdy;
1230    lx3-=lmdx;
1231    ly3-=lmdy;
1232   }
1233  else
1234  if(Position)
1235   {
1236    lx0-=PSXDisplay.DisplayPosition.x;
1237    ly0-=PSXDisplay.DisplayPosition.y;
1238    lx1-=PSXDisplay.DisplayPosition.x;
1239    ly1-=PSXDisplay.DisplayPosition.y;
1240    lx2-=PSXDisplay.DisplayPosition.x;
1241    ly2-=PSXDisplay.DisplayPosition.y;
1242    lx3-=PSXDisplay.DisplayPosition.x;
1243    ly3-=PSXDisplay.DisplayPosition.y;
1244   }
1245  else
1246   {
1247    lx0-=PreviousPSXDisplay.DisplayPosition.x;
1248    ly0-=PreviousPSXDisplay.DisplayPosition.y;
1249    lx1-=PreviousPSXDisplay.DisplayPosition.x;
1250    ly1-=PreviousPSXDisplay.DisplayPosition.y;
1251    lx2-=PreviousPSXDisplay.DisplayPosition.x;
1252    ly2-=PreviousPSXDisplay.DisplayPosition.y;
1253    lx3-=PreviousPSXDisplay.DisplayPosition.x;
1254    ly3-=PreviousPSXDisplay.DisplayPosition.y;
1255   }
1256 
1257  vertex[0].x=lx0 + PreviousPSXDisplay.Range.x0;
1258  vertex[1].x=lx1 + PreviousPSXDisplay.Range.x0;
1259  vertex[2].x=lx2 + PreviousPSXDisplay.Range.x0;
1260  vertex[3].x=lx3 + PreviousPSXDisplay.Range.x0;
1261  vertex[0].y=ly0 + PreviousPSXDisplay.Range.y0;
1262  vertex[1].y=ly1 + PreviousPSXDisplay.Range.y0;
1263  vertex[2].y=ly2 + PreviousPSXDisplay.Range.y0;
1264  vertex[3].y=ly3 + PreviousPSXDisplay.Range.y0;
1265 
1266  if(iUseMask)
1267   {
1268    vertex[0].z=vertex[1].z=vertex[2].z=vertex[3].z=gl_z;
1269    gl_z+=0.00004f;
1270   }
1271 }
1272 
1273 /////////////////////////////////////////////////////////
1274 
offsetBlk(void)1275 void offsetBlk(void)
1276 {
1277  if(bDisplayNotSet)
1278   SetOGLDisplaySettings(1);
1279 
1280  vertex[0].x=lx0-PSXDisplay.GDrawOffset.x + PreviousPSXDisplay.Range.x0;
1281  vertex[1].x=lx1-PSXDisplay.GDrawOffset.x + PreviousPSXDisplay.Range.x0;
1282  vertex[2].x=lx2-PSXDisplay.GDrawOffset.x + PreviousPSXDisplay.Range.x0;
1283  vertex[3].x=lx3-PSXDisplay.GDrawOffset.x + PreviousPSXDisplay.Range.x0;
1284  vertex[0].y=ly0-PSXDisplay.GDrawOffset.y + PreviousPSXDisplay.Range.y0;
1285  vertex[1].y=ly1-PSXDisplay.GDrawOffset.y + PreviousPSXDisplay.Range.y0;
1286  vertex[2].y=ly2-PSXDisplay.GDrawOffset.y + PreviousPSXDisplay.Range.y0;
1287  vertex[3].y=ly3-PSXDisplay.GDrawOffset.y + PreviousPSXDisplay.Range.y0;
1288 
1289  if(iUseMask)
1290   {
1291    vertex[0].z=vertex[1].z=vertex[2].z=vertex[3].z=gl_z;
1292    gl_z+=0.00004f;
1293   }
1294 }
1295 
1296 ////////////////////////////////////////////////////////////////////////
1297 // texture sow/tow calculations
1298 ////////////////////////////////////////////////////////////////////////
1299 
assignTextureVRAMWrite(void)1300 void assignTextureVRAMWrite(void)
1301 {
1302 #ifdef OWNSCALE
1303 
1304  vertex[0].sow=0.5f/ ST_FACVRAMX;
1305  vertex[0].tow=0.5f/ ST_FACVRAM;
1306 
1307  vertex[1].sow=(float)gl_ux[1]/ ST_FACVRAMX;
1308  vertex[1].tow=0.5f/ ST_FACVRAM;
1309 
1310  vertex[2].sow=(float)gl_ux[2]/ ST_FACVRAMX;
1311  vertex[2].tow=(float)gl_vy[2]/ ST_FACVRAM;
1312 
1313  vertex[3].sow=0.5f/ ST_FACVRAMX;
1314  vertex[3].tow=(float)gl_vy[3]/ ST_FACVRAM;
1315 
1316 #else
1317 
1318  if(gl_ux[1]==255)
1319   {
1320    vertex[0].sow=(gl_ux[0]*255.99f)/255.0f;
1321    vertex[1].sow=(gl_ux[1]*255.99f)/255.0f;
1322    vertex[2].sow=(gl_ux[2]*255.99f)/255.0f;
1323    vertex[3].sow=(gl_ux[3]*255.99f)/255.0f;
1324   }
1325  else
1326   {
1327    vertex[0].sow=gl_ux[0];
1328    vertex[1].sow=gl_ux[1];
1329    vertex[2].sow=gl_ux[2];
1330    vertex[3].sow=gl_ux[3];
1331   }
1332 
1333  vertex[0].tow=gl_vy[0];
1334  vertex[1].tow=gl_vy[1];
1335  vertex[2].tow=gl_vy[2];
1336  vertex[3].tow=gl_vy[3];
1337 
1338 #endif
1339 }
1340 
1341 GLuint  gLastTex=0;
1342 GLuint  gLastFMode=(GLuint)-1;
1343 
1344 /////////////////////////////////////////////////////////
1345 
assignTextureSprite(void)1346 void assignTextureSprite(void)
1347 {
1348  if(bUsingTWin)
1349   {
1350    vertex[0].sow=vertex[3].sow=(float)gl_ux[0]/TWin.UScaleFactor;
1351    vertex[1].sow=vertex[2].sow=(float)sSprite_ux2/TWin.UScaleFactor;
1352    vertex[0].tow=vertex[1].tow=(float)gl_vy[0]/TWin.VScaleFactor;
1353    vertex[2].tow=vertex[3].tow=(float)sSprite_vy2/TWin.VScaleFactor;
1354    gLastTex=gTexName;
1355 
1356    if(iFilterType>0 && iFilterType<3 && iHiResTextures!=2)
1357     {
1358      float fxmin=65536.0f,fxmax=0.0f,fymin=65536.0f,fymax=0.0f;int i;
1359 
1360      for(i=0;i<4;i++)
1361       {
1362        if(vertex[i].sow<fxmin) fxmin=vertex[i].sow;
1363        if(vertex[i].tow<fymin) fymin=vertex[i].tow;
1364        if(vertex[i].sow>fxmax) fxmax=vertex[i].sow;
1365        if(vertex[i].tow>fymax) fymax=vertex[i].tow;
1366       }
1367 
1368      for(i=0;i<4;i++)
1369       {
1370 #ifdef OWNSCALE
1371        if(vertex[i].sow==fxmin) vertex[i].sow+=0.375f/(float)TWin.Position.x1;
1372        if(vertex[i].sow==fxmax) vertex[i].sow-=0.375f/(float)TWin.Position.x1;
1373        if(vertex[i].tow==fymin) vertex[i].tow+=0.375f/(float)TWin.Position.y1;
1374        if(vertex[i].tow==fymax) vertex[i].tow-=0.375f/(float)TWin.Position.y1;
1375 #else
1376        if(vertex[i].sow==fxmin) vertex[i].sow+=96.0f/(float)TWin.Position.x1;
1377        if(vertex[i].sow==fxmax) vertex[i].sow-=96.0f/(float)TWin.Position.x1;
1378        if(vertex[i].tow==fymin) vertex[i].tow+=96.0f/(float)TWin.Position.y1;
1379        if(vertex[i].tow==fymax) vertex[i].tow-=96.0f/(float)TWin.Position.y1;
1380 #endif
1381       }
1382     }
1383 
1384   }
1385  else
1386   {
1387 #ifdef OWNSCALE
1388 
1389    vertex[0].sow=vertex[3].sow=(float)gl_ux[0]     / ST_FACSPRITE;
1390    vertex[1].sow=vertex[2].sow=(float)sSprite_ux2  / ST_FACSPRITE;
1391    vertex[0].tow=vertex[1].tow=(float)gl_vy[0]     / ST_FACSPRITE;
1392    vertex[2].tow=vertex[3].tow=(float)sSprite_vy2  / ST_FACSPRITE;
1393 
1394 #else
1395 
1396    vertex[0].sow=vertex[3].sow=gl_ux[0];
1397    vertex[1].sow=vertex[2].sow=sSprite_ux2;
1398    vertex[0].tow=vertex[1].tow=gl_vy[0];
1399    vertex[2].tow=vertex[3].tow=sSprite_vy2;
1400 
1401 #endif
1402 
1403    if(iFilterType>2)
1404     {
1405      if(gLastTex!=gTexName || gLastFMode!=0)
1406       {
1407        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1408        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1409        gLastTex=gTexName;gLastFMode=0;
1410       }
1411     }
1412   }
1413 
1414  if(usMirror & 0x1000)
1415   {
1416    vertex[0].sow=vertex[1].sow;
1417    vertex[1].sow=vertex[2].sow=vertex[3].sow;
1418    vertex[3].sow=vertex[0].sow;
1419   }
1420 
1421  if(usMirror & 0x2000)
1422   {
1423    vertex[0].tow=vertex[3].tow;
1424    vertex[2].tow=vertex[3].tow=vertex[1].tow;
1425    vertex[1].tow=vertex[0].tow;
1426   }
1427 
1428 }
1429 
1430 /////////////////////////////////////////////////////////
1431 
assignTexture3(void)1432 void assignTexture3(void)
1433 {
1434  if(bUsingTWin)
1435   {
1436    vertex[0].sow=(float)gl_ux[0]/TWin.UScaleFactor;
1437    vertex[0].tow=(float)gl_vy[0]/TWin.VScaleFactor;
1438    vertex[1].sow=(float)gl_ux[1]/TWin.UScaleFactor;
1439    vertex[1].tow=(float)gl_vy[1]/TWin.VScaleFactor;
1440    vertex[2].sow=(float)gl_ux[2]/TWin.UScaleFactor;
1441    vertex[2].tow=(float)gl_vy[2]/TWin.VScaleFactor;
1442    gLastTex=gTexName;
1443   }
1444  else
1445   {
1446 #ifdef OWNSCALE
1447    vertex[0].sow=(float)gl_ux[0] / ST_FACTRI;
1448    vertex[0].tow=(float)gl_vy[0] / ST_FACTRI;
1449    vertex[1].sow=(float)gl_ux[1] / ST_FACTRI;
1450 
1451    vertex[1].tow=(float)gl_vy[1] / ST_FACTRI;
1452    vertex[2].sow=(float)gl_ux[2] / ST_FACTRI;
1453    vertex[2].tow=(float)gl_vy[2] / ST_FACTRI;
1454 #else
1455    vertex[0].sow=gl_ux[0];
1456    vertex[0].tow=gl_vy[0];
1457    vertex[1].sow=gl_ux[1];
1458    vertex[1].tow=gl_vy[1];
1459    vertex[2].sow=gl_ux[2];
1460    vertex[2].tow=gl_vy[2];
1461 #endif
1462 
1463    if(iFilterType>2)
1464     {
1465      if(gLastTex!=gTexName || gLastFMode!=1)
1466       {
1467        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1468        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1469        gLastTex=gTexName;gLastFMode=1;
1470       }
1471     }
1472 
1473    if(iFilterType)
1474     {
1475      float fxmin=256.0f,fxmax=0.0f,fymin=256.0f,fymax=0.0f;int i;
1476      for(i=0;i<3;i++)
1477       {
1478        if(vertex[i].sow<fxmin) fxmin=vertex[i].sow;
1479        if(vertex[i].tow<fymin) fymin=vertex[i].tow;
1480        if(vertex[i].sow>fxmax) fxmax=vertex[i].sow;
1481        if(vertex[i].tow>fymax) fymax=vertex[i].tow;
1482       }
1483 
1484      for(i=0;i<3;i++)
1485       {
1486        if(vertex[i].sow==fxmin) vertex[i].sow+=ST_BFFACSORT;
1487        if(vertex[i].sow==fxmax) vertex[i].sow-=ST_BFFACSORT;
1488        if(vertex[i].tow==fymin) vertex[i].tow+=ST_BFFACSORT;
1489        if(vertex[i].tow==fymax) vertex[i].tow-=ST_BFFACSORT;
1490       }
1491     }
1492   }
1493 }
1494 
1495 /////////////////////////////////////////////////////////
1496 
assignTexture4(void)1497 void assignTexture4(void)
1498 {
1499  if(bUsingTWin)
1500   {
1501    vertex[0].sow=(float)gl_ux[0]/TWin.UScaleFactor;
1502    vertex[0].tow=(float)gl_vy[0]/TWin.VScaleFactor;
1503    vertex[1].sow=(float)gl_ux[1]/TWin.UScaleFactor;
1504    vertex[1].tow=(float)gl_vy[1]/TWin.VScaleFactor;
1505    vertex[2].sow=(float)gl_ux[2]/TWin.UScaleFactor;
1506    vertex[2].tow=(float)gl_vy[2]/TWin.VScaleFactor;
1507    vertex[3].sow=(float)gl_ux[3]/TWin.UScaleFactor;
1508    vertex[3].tow=(float)gl_vy[3]/TWin.VScaleFactor;
1509    gLastTex=gTexName;
1510   }
1511  else
1512   {
1513 #ifdef OWNSCALE
1514    vertex[0].sow=(float)gl_ux[0] / ST_FAC;
1515    vertex[0].tow=(float)gl_vy[0] / ST_FAC;
1516    vertex[1].sow=(float)gl_ux[1] / ST_FAC;
1517    vertex[1].tow=(float)gl_vy[1] / ST_FAC;
1518    vertex[2].sow=(float)gl_ux[2] / ST_FAC;
1519    vertex[2].tow=(float)gl_vy[2] / ST_FAC;
1520    vertex[3].sow=(float)gl_ux[3] / ST_FAC;
1521    vertex[3].tow=(float)gl_vy[3] / ST_FAC;
1522 #else
1523    vertex[0].sow=gl_ux[0];
1524    vertex[0].tow=gl_vy[0];
1525    vertex[1].sow=gl_ux[1];
1526    vertex[1].tow=gl_vy[1];
1527    vertex[2].sow=gl_ux[2];
1528    vertex[2].tow=gl_vy[2];
1529    vertex[3].sow=gl_ux[3];
1530    vertex[3].tow=gl_vy[3];
1531 #endif
1532 
1533    if(iFilterType>2)
1534     {
1535      if(gLastTex!=gTexName || gLastFMode!=1)
1536       {
1537        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1538        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1539        gLastTex=gTexName;gLastFMode=1;
1540       }
1541     }
1542 
1543    if(iFilterType)
1544     {
1545      float fxmin=256.0f,fxmax=0.0f,fymin=256.0f,fymax=0.0f;int i;
1546      for(i=0;i<4;i++)
1547       {
1548        if(vertex[i].sow<fxmin) fxmin=vertex[i].sow;
1549        if(vertex[i].tow<fymin) fymin=vertex[i].tow;
1550        if(vertex[i].sow>fxmax) fxmax=vertex[i].sow;
1551        if(vertex[i].tow>fymax) fymax=vertex[i].tow;
1552       }
1553 
1554      for(i=0;i<4;i++)
1555       {
1556        if(vertex[i].sow==fxmin) vertex[i].sow+=ST_BFFACSORT;
1557        if(vertex[i].sow==fxmax) vertex[i].sow-=ST_BFFACSORT;
1558        if(vertex[i].tow==fymin) vertex[i].tow+=ST_BFFACSORT;
1559        if(vertex[i].tow==fymax) vertex[i].tow-=ST_BFFACSORT;
1560       }
1561     }
1562   }
1563 }
1564 
1565 ////////////////////////////////////////////////////////////////////////
1566 ////////////////////////////////////////////////////////////////////////
1567 ////////////////////////////////////////////////////////////////////////
1568 
1569 ////////////////////////////////////////////////////////////////////////
1570 // render pos / buffers
1571 ////////////////////////////////////////////////////////////////////////
1572 
1573 #ifndef _WINDOWS
1574 #define EqualRect(pr1,pr2) ((pr1)->left==(pr2)->left && (pr1)->top==(pr2)->top && (pr1)->right==(pr2)->right && (pr1)->bottom==(pr2)->bottom)
1575 #endif
1576 
1577 ////////////////////////////////////////////////////////////////////////
1578 // SetDisplaySettings: "simply" calcs the new drawing area and updates
1579 //                     the ogl clipping (scissor)
1580 
1581 BOOL bSetClip=FALSE;
1582 
SetOGLDisplaySettings(BOOL DisplaySet)1583 void SetOGLDisplaySettings(BOOL DisplaySet)
1584 {
1585  static RECT rprev={0,0,0,0};
1586  static RECT rC   ={0,0,0,0};
1587  static int iOldX=0;
1588  static int iOldY=0;
1589  RECT r;float XS,YS;
1590 
1591  bDisplayNotSet = FALSE;
1592 
1593  //----------------------------------------------------// that's a whole screen upload
1594  if(!DisplaySet)
1595   {
1596    RECT rX;
1597    PSXDisplay.GDrawOffset.x=0;
1598    PSXDisplay.GDrawOffset.y=0;
1599 
1600    PSXDisplay.CumulOffset.x = PSXDisplay.DrawOffset.x+PreviousPSXDisplay.Range.x0;
1601    PSXDisplay.CumulOffset.y = PSXDisplay.DrawOffset.y+PreviousPSXDisplay.Range.y0;
1602 
1603    rprev.left=rprev.left+1;
1604 
1605    rX=rRatioRect;
1606    rX.top=iResY-(rRatioRect.top+rRatioRect.bottom);
1607 
1608    if(bSetClip || !EqualRect(&rC,&rX))
1609     {
1610      rC=rX;
1611      glScissor(rC.left,rC.top,rC.right,rC.bottom);
1612      bSetClip=FALSE;
1613     }
1614    return;
1615   }
1616  //----------------------------------------------------//
1617 
1618  PSXDisplay.GDrawOffset.y = PreviousPSXDisplay.DisplayPosition.y;
1619  PSXDisplay.GDrawOffset.x = PreviousPSXDisplay.DisplayPosition.x;
1620  PSXDisplay.CumulOffset.x = PSXDisplay.DrawOffset.x - PSXDisplay.GDrawOffset.x+PreviousPSXDisplay.Range.x0;
1621  PSXDisplay.CumulOffset.y = PSXDisplay.DrawOffset.y - PSXDisplay.GDrawOffset.y+PreviousPSXDisplay.Range.y0;
1622 
1623  r.top   =PSXDisplay.DrawArea.y0 - PreviousPSXDisplay.DisplayPosition.y;
1624  r.bottom=PSXDisplay.DrawArea.y1 - PreviousPSXDisplay.DisplayPosition.y;
1625 
1626  if(r.bottom<0 || r.top>=PSXDisplay.DisplayMode.y)
1627   {
1628    r.top   =PSXDisplay.DrawArea.y0 - PSXDisplay.DisplayPosition.y;
1629    r.bottom=PSXDisplay.DrawArea.y1 - PSXDisplay.DisplayPosition.y;
1630   }
1631 
1632  r.left  =PSXDisplay.DrawArea.x0 - PreviousPSXDisplay.DisplayPosition.x;
1633  r.right =PSXDisplay.DrawArea.x1 - PreviousPSXDisplay.DisplayPosition.x;
1634 
1635  if(r.right<0 || r.left>=PSXDisplay.DisplayMode.x)
1636   {
1637    r.left  =PSXDisplay.DrawArea.x0 - PSXDisplay.DisplayPosition.x;
1638    r.right =PSXDisplay.DrawArea.x1 - PSXDisplay.DisplayPosition.x;
1639   }
1640 
1641  if(!bSetClip && EqualRect(&r,&rprev) &&
1642     iOldX == PSXDisplay.DisplayMode.x &&
1643     iOldY == PSXDisplay.DisplayMode.y)
1644   return;
1645 
1646  rprev = r;
1647  iOldX = PSXDisplay.DisplayMode.x;
1648  iOldY = PSXDisplay.DisplayMode.y;
1649 
1650  XS=(float)rRatioRect.right/(float)PSXDisplay.DisplayMode.x;
1651  YS=(float)rRatioRect.bottom/(float)PSXDisplay.DisplayMode.y;
1652 
1653  if(PreviousPSXDisplay.Range.x0)
1654   {
1655    short s=PreviousPSXDisplay.Range.x0+PreviousPSXDisplay.Range.x1;
1656 
1657    r.left+=PreviousPSXDisplay.Range.x0+1;
1658 
1659    r.right+=PreviousPSXDisplay.Range.x0;
1660 
1661    if(r.left>s)  r.left=s;
1662    if(r.right>s) r.right=s;
1663   }
1664 
1665  if(PreviousPSXDisplay.Range.y0)
1666   {
1667    short s=PreviousPSXDisplay.Range.y0+PreviousPSXDisplay.Range.y1;
1668 
1669    r.top+=PreviousPSXDisplay.Range.y0+1;
1670    r.bottom+=PreviousPSXDisplay.Range.y0;
1671 
1672    if(r.top>s)    r.top=s;
1673    if(r.bottom>s) r.bottom=s;
1674   }
1675 
1676  // Set the ClipArea variables to reflect the new screen,
1677  // offset from zero (since it is a new display buffer)
1678  r.left   = (int)(((float)(r.left))      *XS);
1679  r.top    = (int)(((float)(r.top))       *YS);
1680  r.right  = (int)(((float)(r.right  + 1))*XS);
1681  r.bottom = (int)(((float)(r.bottom + 1))*YS);
1682 
1683  // Limit clip area to the screen size
1684  if (r.left   > iResX)   r.left   = iResX;
1685  if (r.left   < 0)       r.left   = 0;
1686  if (r.top    > iResY)   r.top    = iResY;
1687  if (r.top    < 0)       r.top    = 0;
1688  if (r.right  > iResX)   r.right  = iResX;
1689  if (r.right  < 0)       r.right  = 0;
1690  if (r.bottom > iResY)   r.bottom = iResY;
1691  if (r.bottom < 0)       r.bottom = 0;
1692 
1693  r.right -=r.left;
1694  r.bottom-=r.top;
1695  r.top=iResY-(r.top+r.bottom);
1696 
1697  r.left+=rRatioRect.left;
1698  r.top -=rRatioRect.top;
1699 
1700  if(bSetClip || !EqualRect(&r,&rC))
1701   {
1702    glScissor(r.left,r.top,r.right,r.bottom);
1703    rC=r;
1704    bSetClip=FALSE;
1705   }
1706 }
1707 
1708 ////////////////////////////////////////////////////////////////////////
1709 ////////////////////////////////////////////////////////////////////////
1710 ////////////////////////////////////////////////////////////////////////
1711 
1712