+/***************************************************************************\r
+ draw.c - description\r
+ -------------------\r
+ begin : Sun Mar 08 2009\r
+ copyright : (C) 1999-2009 by Pete Bernert\r
+ web : www.pbernert.com \r
+ ***************************************************************************/\r
+\r
+/***************************************************************************\r
+ * *\r
+ * This program is free software; you can redistribute it and/or modify *\r
+ * it under the terms of the GNU General Public License as published by *\r
+ * the Free Software Foundation; either version 2 of the License, or *\r
+ * (at your option) any later version. See also the license.txt file for *\r
+ * additional informations. *\r
+ * *\r
+ ***************************************************************************/\r
+\r
+//*************************************************************************// \r
+// History of changes:\r
+//\r
+// 2009/03/08 - Pete \r
+// - generic cleanup for the Peops release\r
+//\r
+//*************************************************************************// \r
+\r
+\r
+#define _IN_DRAW\r
+\r
+#ifdef _WINDOWS\r
+#include "stdafx.h"\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <math.h>\r
+#include "externals.h"\r
+#include "gpu.h"\r
+#include "draw.h"\r
+#include "prim.h"\r
+#include "texture.h"\r
+#else\r
+#include "gpuExternals.h"\r
+#include "GPUPlugin.h"\r
+#include "gpuDraw.h"\r
+#include "gpuPrim.h"\r
+#include "gpuTexture.h"\r
+#include "gpuStdafx.h"\r
+\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <math.h>\r
+#endif\r
+//#include "menu.h"\r
+ \r
+////////////////////////////////////////////////////////////////////////////////////\r
+// defines\r
+\r
+#define SIGNBIT 0x800\r
+#define S_MASK 0xf000\r
+#define L_MASK 0xfffff000\r
+\r
+// ownscale: some ogl drivers have buggy texture matrix funcs, so it\r
+// is safer to calc sow/tow ourselves\r
+\r
+#ifdef OWNSCALE\r
+\r
+///////////////////////////////////////////////////////////////\r
+\r
+#define ST_FACSPRITE 255.99f\r
+#define ST_BFFACSPRITE 0.5f/256.0f\r
+#define ST_BFFACSPRITESORT 0.333f/256.0f\r
+\r
+#define ST_OFFSET 0.5f/256.0f;\r
+\r
+#define ST_FAC 255.99f\r
+#define ST_BFFAC 0.5f/256.0f\r
+#define ST_BFFACSORT 0.333f/256.0f\r
+\r
+#define ST_FACTRI 255.99f\r
+#define ST_BFFACTRI 0.5f/256.0f\r
+#define ST_BFFACTRISORT 0.333f/256.0f\r
+\r
+#define ST_FACVRAMX 255.0f\r
+#define ST_FACVRAM 256.0f\r
+\r
+///////////////////////////////////////////////////////////////\r
+\r
+#else\r
+\r
+#define ST_BFFACSPRITE 0.5f\r
+#define ST_BFFACSPRITESORT 0.333f\r
+\r
+#define ST_BFFAC 0.5f\r
+#define ST_BFFACSORT 0.333f\r
+\r
+#define ST_BFFACTRI 0.5f\r
+#define ST_BFFACTRISORT 0.333f\r
+\r
+#define ST_OFFSET 0.5f;\r
+ \r
+#endif\r
+\r
+////////////////////////////////////////////////////////////////////////////////////\r
+// draw globals\r
+\r
+#ifdef _WINDOWS\r
+HDC dcGlobal=NULL;\r
+HWND hWWindow;\r
+#else\r
+void glBlendEquationEXT(GLenum mode);\r
+void glColorTableEXT(GLenum target, GLenum internalFormat, GLsizei width, GLenum format,GLenum type, const GLvoid *data);\r
+#endif\r
+\r
+// draw globals; most will be initialized again later (by config or checks) \r
+\r
+BOOL bIsFirstFrame=TRUE;\r
+\r
+// resolution/ratio vars\r
+\r
+int iResX;\r
+int iResY;\r
+BOOL bKeepRatio=FALSE;\r
+RECT rRatioRect;\r
+\r
+// psx mask related vars\r
+\r
+BOOL bCheckMask=FALSE;\r
+int iUseMask=0;\r
+int iSetMask=0;\r
+unsigned short sSetMask=0;\r
+unsigned long lSetMask=0;\r
+\r
+// drawing/coord vars\r
+\r
+OGLVertex vertex[4];\r
+GLubyte gl_ux[8];\r
+GLubyte gl_vy[8];\r
+short sprtY,sprtX,sprtH,sprtW;\r
+\r
+// drawing options\r
+\r
+BOOL bOpaquePass;\r
+BOOL bAdvancedBlend;\r
+\r
+// OGL extension support\r
+\r
+\r
+// gfx card buffer infos\r
+\r
+int iDepthFunc=0;\r
+int iZBufferDepth=0;\r
+GLbitfield uiBufferBits=GL_COLOR_BUFFER_BIT;\r
+\r
+////////////////////////////////////////////////////////////////////////\r
+////////////////////////////////////////////////////////////////////////\r
+////////////////////////////////////////////////////////////////////////\r
+\r
+////////////////////////////////////////////////////////////////////////\r
+// Set OGL pixel format\r
+////////////////////////////////////////////////////////////////////////\r
+ \r
+#ifdef _WINDOWS\r
+BOOL bSetupPixelFormat(HDC hDC)\r
+{\r
+ int pixelformat;\r
+ static PIXELFORMATDESCRIPTOR pfd = \r
+ {\r
+ sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd\r
+ 1, // version number\r
+ PFD_DRAW_TO_WINDOW | // support window\r
+ PFD_SUPPORT_OPENGL | // support OpenGL\r
+ PFD_DOUBLEBUFFER, // double buffered\r
+ PFD_TYPE_RGBA, // RGBA type\r
+ 16, // 16-bit color depth (adjusted later)\r
+ 0, 0, 0, 0, 0, 0, // color bits ignored\r
+ 0, // no alpha buffer\r
+ 0, // shift bit ignored\r
+ 0, // no accumulation buffer\r
+ 0, 0, 0, 0, // accum bits ignored\r
+ 0, // z-buffer \r
+ 0,\r
+ 0, // no auxiliary buffer\r
+ PFD_MAIN_PLANE, // main layer\r
+ 0, // reserved\r
+ 0, 0, 0 // layer masks ignored\r
+ };\r
+ \r
+ pfd.cColorBits=iColDepth; // set user color depth\r
+ pfd.cDepthBits=iZBufferDepth; // set user zbuffer (by psx mask)\r
+\r
+ if((pixelformat=ChoosePixelFormat(hDC,&pfd))==0) \r
+ {\r
+ MessageBox(NULL,"ChoosePixelFormat failed","Error",MB_OK);\r
+ return FALSE;\r
+ }\r
+\r
+ if(SetPixelFormat(hDC,pixelformat, &pfd)==FALSE)\r
+ {\r
+ MessageBox(NULL,"SetPixelFormat failed","Error",MB_OK);\r
+ return FALSE;\r
+ }\r
+\r
+ return TRUE;\r
+}\r
+#endif\r
+\r
+////////////////////////////////////////////////////////////////////////\r
+// Get extension infos (f.e. pal textures / packed pixels)\r
+////////////////////////////////////////////////////////////////////////\r
+\r
+void GetExtInfos(void) \r
+{\r
+ BOOL bPacked=FALSE; // default: no packed pixel support\r
+\r
+ if(strstr((s8 *)glGetString(GL_EXTENSIONS), // packed pixels available?\r
+ "GL_EXT_packed_pixels")) \r
+ bPacked=TRUE; // -> ok\r
+\r
+ \r
+ #ifdef _WINDOWS\r
+ iClampType=GL_CLAMP;\r
+#else\r
+ iClampType=GL_CLAMP_TO_EDGE;\r
+#endif\r
+}\r
+\r
+////////////////////////////////////////////////////////////////////////\r
+// Setup some stuff depending on user settings or in-game toggle\r
+////////////////////////////////////////////////////////////////////////\r
+\r
+void SetExtGLFuncs(void)\r
+{\r
+ //----------------------------------------------------//\r
+\r
+ SetFixes(); // update fix infos\r
+\r
+ //----------------------------------------------------//\r
+\r
+ {\r
+ if(bAdvancedBlend) bUseMultiPass=TRUE; // -> pseudo-advanced with 2 passes\r
+ else bUseMultiPass=FALSE; // -> or simple 'bright color' mode\r
+// bGLBlend=FALSE; // -> no ext blending!\r
+\r
+ glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); \r
+ }\r
+\r
+ if(bOpaquePass) // opaque mode?\r
+ {\r
+ if(dwActFixes&32) \r
+ {\r
+ TCF[0]=CP8RGBA_0;\r
+ PalTexturedColourFn=CP8RGBA; // -> init col func\r
+ }\r
+ else\r
+ {\r
+ TCF[0]=XP8RGBA_0;\r
+ PalTexturedColourFn=XP8RGBA; // -> init col func\r
+ }\r
+\r
+ TCF[1]=XP8RGBA_1;\r
+ glAlphaFuncx(GL_GREATER,0.49f);\r
+ }\r
+ else // no opaque mode?\r
+ {\r
+ TCF[0]=TCF[1]=P8RGBA;\r
+ PalTexturedColourFn=P8RGBA; // -> init col func\r
+ glAlphaFuncx(GL_NOTEQUAL,0); // --> set alpha func\r
+ }\r
+\r
+ //----------------------------------------------------//\r
+\r
+ LoadSubTexFn=LoadSubTexturePageSort; // init load tex ptr\r
+\r
+ bBlendEnable=FALSE; // init blending: off\r
+ glDisable(GL_BLEND);\r
+\r
+ SetScanTrans(); // init scan lines (if wanted)\r
+}\r
+\r
+////////////////////////////////////////////////////////////////////////\r
+// setup scan lines\r
+////////////////////////////////////////////////////////////////////////\r
+\r
+#define R_TSP 0x00,0x45,0x00,0xff\r
+#define G_TSP 0x00,0x00,0x45,0xff\r
+#define B_TSP 0x45,0x00,0x00,0xff\r
+#define O_TSP 0x45,0x45,0x45,0xff\r
+#define N_TSP 0x00,0x00,0x00,0xff\r
+\r
+GLuint gTexScanName=0;\r
+\r
+GLubyte texscan[4][16]= \r
+{\r
+{R_TSP, G_TSP, B_TSP, N_TSP},\r
+{O_TSP, N_TSP, O_TSP, N_TSP},\r
+{B_TSP, N_TSP, R_TSP, G_TSP},\r
+{O_TSP, N_TSP, O_TSP, N_TSP}\r
+};\r
+\r
+void CreateScanLines(void)\r
+{\r
+}\r
+\r
+////////////////////////////////////////////////////////////////////////\r
+// Initialize OGL\r
+////////////////////////////////////////////////////////////////////////\r
+\r
+#ifdef _WINDOWS \r
+HGLRC GLCONTEXT=NULL;\r
+#endif\r
+\r
+#ifdef MAEMO_CHANGES\r
+bool TestEGLError(const char* pszLocation)\r
+{\r
+ /*\r
+ eglGetError returns the last error that has happened using egl,\r
+ not the status of the last called function. The user has to\r
+ check after every single egl call or at least once every frame.\r
+ */\r
+ EGLint iErr = eglGetError();\r
+ if (iErr != EGL_SUCCESS)\r
+ {\r
+ printf("%s failed (%d).\n", pszLocation, iErr);\r
+ return false;\r
+ }\r
+\r
+ return true;\r
+}\r
+\r
+void maemoGLinit(){\r
+ iResX= 800;\r
+ iResY =480;\r
+\r
+ \r
+ printf ("maemo GL init\n");\r
+ long int winxid=GDK_WINDOW_XID(GTK_WIDGET(windowG)->window);\r
+ printf ("%d\n",winxid);\r
+ \r
+ EGLContext context = 0;\r
+ EGLConfig eglConfig = 0;\r
+ EGLContext eglContext = 0;\r
+ display = eglGetDisplay( EGL_DEFAULT_DISPLAY );\r
+ \r
+ if( eglInitialize( display, NULL, NULL ) == EGL_FALSE )\r
+ { \r
+ printf( "EGL Initialize failed!\n" );\r
+ \r
+ }\r
+\r
+const EGLint attributeList[] = { \r
+ EGL_SURFACE_TYPE, EGL_WINDOW_BIT, \r
+ /*EGL_BUFFER_SIZE, 32, */\r
+ EGL_NONE \r
+ };\r
+ \r
+ EGLint pi32ConfigAttribs[5];\r
+ pi32ConfigAttribs[0] = EGL_SURFACE_TYPE;\r
+ pi32ConfigAttribs[1] = EGL_WINDOW_BIT;\r
+ pi32ConfigAttribs[2] = EGL_RENDERABLE_TYPE;\r
+ pi32ConfigAttribs[3] = EGL_OPENGL_ES2_BIT; \r
+ pi32ConfigAttribs[4] = EGL_NONE;\r
+\r
+ EGLint pi32ContextAttribs[3];\r
+ pi32ContextAttribs[0] = EGL_CONTEXT_CLIENT_VERSION;\r
+ pi32ContextAttribs[1] = 2;\r
+ pi32ContextAttribs[2] = EGL_NONE;\r
+\r
+ int iConfigs;\r
+ if (!eglChooseConfig(display, attributeList, &eglConfig, 1, &iConfigs) || (iConfigs != 1))\r
+ {\r
+ printf("Error: eglChooseConfig() failed.\n");\r
+ }\r
+ printf ("%d\n",iConfigs);\r
+ surface = eglCreateWindowSurface(display, eglConfig, (void*)winxid, NULL);\r
+ printf ("%d\n",surface);\r
+ if (!TestEGLError("eglCreateWindowSurface"))\r
+ {\r
+ printf ("eglCreateWindowSurface fail");\r
+ }\r
+\r
+ //context = eglCreateContext(display, eglConfig, NULL, pi32ContextAttribs);\r
+ context =eglCreateContext( display, eglConfig,\r
+ EGL_NO_CONTEXT, NULL \r
+ );\r
+printf ("%d\n",context);\r
+ if (!TestEGLError("eglCreateContext"))\r
+ {\r
+ printf("error eglCreateContext");\r
+ }\r
+\r
+ eglMakeCurrent(display, surface, surface, context);\r
+\r
+ if (!TestEGLError("eglMakeCurrent"))\r
+ {\r
+ printf("error eglMakeCurrent");\r
+ }\r
+}\r
+#endif\r
+\r
+int GLinitialize() \r
+{\r
+ //----------------------------------------------------// \r
+#ifdef _WINDOWS\r
+ HGLRC objectRC;\r
+ // init\r
+ dcGlobal = GetDC(hWWindow); // FIRST: dc/rc stuff\r
+ objectRC = wglCreateContext(dcGlobal); \r
+ GLCONTEXT=objectRC;\r
+ wglMakeCurrent(dcGlobal, objectRC);\r
+ // CheckWGLExtensions(dcGlobal);\r
+ if(bWindowMode) ReleaseDC(hWWindow,dcGlobal); // win mode: release dc again\r
+#endif\r
+#ifdef MAEMO_CHANGES\r
+ maemoGLinit();\r
+#endif\r
+ //----------------------------------------------------// \r
+\r
+ glViewport(rRatioRect.left, // init viewport by ratio rect\r
+ iResY-(rRatioRect.top+rRatioRect.bottom),\r
+ rRatioRect.right, \r
+ rRatioRect.bottom); \r
+ \r
+ glScissor(0, 0, iResX, iResY); // init clipping (fullscreen)\r
+ glEnable(GL_SCISSOR_TEST); \r
+\r
+#ifndef OWNSCALE\r
+ glMatrixMode(GL_TEXTURE); // init psx tex sow and tow if not "ownscale"\r
+ glLoadIdentity();\r
+ glScalef(1.0f/255.99f,1.0f/255.99f,1.0f); // geforce precision hack\r
+#endif \r
+\r
+ glMatrixMode(GL_PROJECTION); // init projection with psx resolution\r
+ glLoadIdentity();\r
+ glOrtho(0,PSXDisplay.DisplayMode.x,\r
+ PSXDisplay.DisplayMode.y, 0, -1, 1);\r
+\r
+ if(iZBufferDepth) // zbuffer?\r
+ {\r
+ uiBufferBits=GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT;\r
+ glEnable(GL_DEPTH_TEST); \r
+ glDepthFunc(GL_ALWAYS);\r
+ iDepthFunc=1;\r
+ }\r
+ else // no zbuffer?\r
+ {\r
+ uiBufferBits=GL_COLOR_BUFFER_BIT;\r
+ glDisable(GL_DEPTH_TEST);\r
+ }\r
+\r
+ glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // first buffer clear\r
+ glClear(uiBufferBits);\r
+\r
+ GetExtInfos(); // get ext infos\r
+ SetExtGLFuncs(); // init all kind of stuff (tex function pointers)\r
+ \r
+ glEnable(GL_ALPHA_TEST); // wanna alpha test\r
+\r
+ {\r
+ glDisable(GL_LINE_SMOOTH);\r
+ glDisable(GL_POINT_SMOOTH);\r
+ }\r
+\r
+ ubGloAlpha=127; // init some drawing vars\r
+ ubGloColAlpha=127;\r
+ TWin.UScaleFactor = 1;\r
+ TWin.VScaleFactor = 1;\r
+ bDrawMultiPass=FALSE;\r
+ bTexEnabled=FALSE;\r
+ bUsingTWin=FALSE;\r
+ \r
+ if(bDrawDither) glEnable(GL_DITHER); // dither mode\r
+ else glDisable(GL_DITHER); \r
+\r
+ glDisable(GL_FOG); // turn all (currently) unused modes off\r
+ glDisable(GL_LIGHTING); \r
+ glDisable(GL_STENCIL_TEST); \r
+ glDisable(GL_TEXTURE_2D);\r
+ glDisable(GL_CULL_FACE);\r
+\r
+ glFlush(); // we are done...\r
+ glFinish(); \r
+\r
+ CreateScanLines(); // setup scanline stuff (if wanted)\r
+\r
+ CheckTextureMemory(); // check available tex memory\r
+\r
+ if(bKeepRatio) SetAspectRatio(); // set ratio\r
+\r
+ \r
+ bIsFirstFrame = FALSE; // we have survived the first frame :)\r
+\r
+ return 0;\r
+}\r
+\r
+////////////////////////////////////////////////////////////////////////\r
+// clean up OGL stuff\r
+////////////////////////////////////////////////////////////////////////\r
+\r
+void GLcleanup() \r
+{ \r
+ CleanupTextureStore(); // bye textures\r
+\r
+#ifdef _WINDOWS \r
+ wglMakeCurrent(NULL, NULL); // bye context\r
+ if(GLCONTEXT) wglDeleteContext(GLCONTEXT);\r
+ if(!bWindowMode && dcGlobal) \r
+ ReleaseDC(hWWindow,dcGlobal);\r
+#endif\r
+}\r
+\r
+////////////////////////////////////////////////////////////////////////\r
+////////////////////////////////////////////////////////////////////////\r
+////////////////////////////////////////////////////////////////////////\r
+\r
+////////////////////////////////////////////////////////////////////////\r
+////////////////////////////////////////////////////////////////////////\r
+////////////////////////////////////////////////////////////////////////\r
+\r
+////////////////////////////////////////////////////////////////////////\r
+// Offset stuff\r
+////////////////////////////////////////////////////////////////////////\r
+\r
+// please note: it is hardly do-able in a hw/accel plugin to get the \r
+// real psx polygon coord mapping right... the following\r
+// works not to bad with many games, though\r
+\r
+__inline BOOL CheckCoord4()\r
+{\r
+ if(lx0<0)\r
+ {\r
+ if(((lx1-lx0)>CHKMAX_X) ||\r
+ ((lx2-lx0)>CHKMAX_X)) \r
+ {\r
+ if(lx3<0)\r
+ {\r
+ if((lx1-lx3)>CHKMAX_X) return TRUE;\r
+ if((lx2-lx3)>CHKMAX_X) return TRUE;\r
+ }\r
+ }\r
+ }\r
+ if(lx1<0)\r
+ {\r
+ if((lx0-lx1)>CHKMAX_X) return TRUE;\r
+ if((lx2-lx1)>CHKMAX_X) return TRUE;\r
+ if((lx3-lx1)>CHKMAX_X) return TRUE;\r
+ }\r
+ if(lx2<0)\r
+ {\r
+ if((lx0-lx2)>CHKMAX_X) return TRUE;\r
+ if((lx1-lx2)>CHKMAX_X) return TRUE;\r
+ if((lx3-lx2)>CHKMAX_X) return TRUE;\r
+ }\r
+ if(lx3<0)\r
+ {\r
+ if(((lx1-lx3)>CHKMAX_X) ||\r
+ ((lx2-lx3)>CHKMAX_X))\r
+ {\r
+ if(lx0<0)\r
+ {\r
+ if((lx1-lx0)>CHKMAX_X) return TRUE;\r
+ if((lx2-lx0)>CHKMAX_X) return TRUE;\r
+ }\r
+ }\r
+ }\r
+ \r
+\r
+ if(ly0<0)\r
+ {\r
+ if((ly1-ly0)>CHKMAX_Y) return TRUE;\r
+ if((ly2-ly0)>CHKMAX_Y) return TRUE;\r
+ }\r
+ if(ly1<0)\r
+ {\r
+ if((ly0-ly1)>CHKMAX_Y) return TRUE;\r
+ if((ly2-ly1)>CHKMAX_Y) return TRUE;\r
+ if((ly3-ly1)>CHKMAX_Y) return TRUE;\r
+ }\r
+ if(ly2<0)\r
+ {\r
+ if((ly0-ly2)>CHKMAX_Y) return TRUE;\r
+ if((ly1-ly2)>CHKMAX_Y) return TRUE;\r
+ if((ly3-ly2)>CHKMAX_Y) return TRUE;\r
+ }\r
+ if(ly3<0)\r
+ {\r
+ if((ly1-ly3)>CHKMAX_Y) return TRUE;\r
+ if((ly2-ly3)>CHKMAX_Y) return TRUE;\r
+ }\r
+\r
+ return FALSE;\r
+}\r
+\r
+__inline BOOL CheckCoord3()\r
+{\r
+ if(lx0<0)\r
+ {\r
+ if((lx1-lx0)>CHKMAX_X) return TRUE;\r
+ if((lx2-lx0)>CHKMAX_X) return TRUE;\r
+ }\r
+ if(lx1<0)\r
+ {\r
+ if((lx0-lx1)>CHKMAX_X) return TRUE;\r
+ if((lx2-lx1)>CHKMAX_X) return TRUE;\r
+ }\r
+ if(lx2<0)\r
+ {\r
+ if((lx0-lx2)>CHKMAX_X) return TRUE;\r
+ if((lx1-lx2)>CHKMAX_X) return TRUE;\r
+ }\r
+ if(ly0<0)\r
+ {\r
+ if((ly1-ly0)>CHKMAX_Y) return TRUE;\r
+ if((ly2-ly0)>CHKMAX_Y) return TRUE;\r
+ }\r
+ if(ly1<0)\r
+ {\r
+ if((ly0-ly1)>CHKMAX_Y) return TRUE;\r
+ if((ly2-ly1)>CHKMAX_Y) return TRUE;\r
+ }\r
+ if(ly2<0)\r
+ {\r
+ if((ly0-ly2)>CHKMAX_Y) return TRUE;\r
+ if((ly1-ly2)>CHKMAX_Y) return TRUE;\r
+ }\r
+\r
+ return FALSE;\r
+}\r
+\r
+\r
+__inline BOOL CheckCoord2()\r
+{\r
+ if(lx0<0)\r
+ {\r
+ if((lx1-lx0)>CHKMAX_X) return TRUE;\r
+ }\r
+ if(lx1<0)\r
+ {\r
+ if((lx0-lx1)>CHKMAX_X) return TRUE;\r
+ }\r
+ if(ly0<0)\r
+ {\r
+ if((ly1-ly0)>CHKMAX_Y) return TRUE;\r
+ }\r
+ if(ly1<0)\r
+ {\r
+ if((ly0-ly1)>CHKMAX_Y) return TRUE;\r
+ }\r
+\r
+ return FALSE;\r
+}\r
+\r
+// Pete's way: a very easy (and hopefully fast) approach for lines\r
+// without sqrt... using a small float -> short cast trick :)\r
+\r
+#define VERTEX_OFFX 0.2f\r
+#define VERTEX_OFFY 0.2f\r
+\r
+BOOL offsetline(void) \r
+{\r
+ short x0,x1,y0,y1,dx,dy;float px,py;\r
+\r
+ if(bDisplayNotSet)\r
+ SetOGLDisplaySettings(1);\r
+\r
+ if(!(dwActFixes&16))\r
+ {\r
+ lx0=(short)(((int)lx0<<SIGNSHIFT)>>SIGNSHIFT);\r
+ lx1=(short)(((int)lx1<<SIGNSHIFT)>>SIGNSHIFT);\r
+ ly0=(short)(((int)ly0<<SIGNSHIFT)>>SIGNSHIFT);\r
+ ly1=(short)(((int)ly1<<SIGNSHIFT)>>SIGNSHIFT);\r
+\r
+ if(CheckCoord2()) return TRUE;\r
+ }\r
+\r
+ x0 = (lx0 + PSXDisplay.CumulOffset.x)+1;\r
+ x1 = (lx1 + PSXDisplay.CumulOffset.x)+1;\r
+ y0 = (ly0 + PSXDisplay.CumulOffset.y)+1;\r
+ y1 = (ly1 + PSXDisplay.CumulOffset.y)+1;\r
+ \r
+ dx=x1-x0;\r
+ dy=y1-y0;\r
+ \r
+ if(dx>=0)\r
+ {\r
+ if(dy>=0)\r
+ {\r
+ px=0.5f;\r
+ if(dx>dy) py=-0.5f;\r
+ else if(dx<dy) py= 0.5f;\r
+ else py= 0.0f;\r
+ }\r
+ else\r
+ {\r
+ py=-0.5f;\r
+ dy=-dy;\r
+ if(dx>dy) px= 0.5f;\r
+ else if(dx<dy) px=-0.5f;\r
+ else px= 0.0f;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ if(dy>=0)\r
+ {\r
+ py=0.5f;\r
+ dx=-dx;\r
+ if(dx>dy) px=-0.5f;\r
+ else if(dx<dy) px= 0.5f;\r
+ else px= 0.0f;\r
+ }\r
+ else\r
+ {\r
+ px=-0.5f;\r
+ if(dx>dy) py=-0.5f;\r
+ else if(dx<dy) py= 0.5f;\r
+ else py= 0.0f;\r
+ }\r
+ } \r
+ \r
+ vertex[0].x=(short)((float)x0-px);\r
+ vertex[3].x=(short)((float)x0+py);\r
+ \r
+ vertex[0].y=(short)((float)y0-py);\r
+ vertex[3].y=(short)((float)y0-px);\r
+ \r
+ vertex[1].x=(short)((float)x1-py);\r
+ vertex[2].x=(short)((float)x1+px);\r
+\r
+ vertex[1].y=(short)((float)y1+px);\r
+ vertex[2].y=(short)((float)y1+py);\r
+\r
+ if(vertex[0].x==vertex[3].x && // ortho rect? done\r
+ vertex[1].x==vertex[2].x &&\r
+ vertex[0].y==vertex[1].y &&\r
+ vertex[2].y==vertex[3].y) return FALSE;\r
+ if(vertex[0].x==vertex[1].x &&\r
+ vertex[2].x==vertex[3].x &&\r
+ vertex[0].y==vertex[3].y &&\r
+ vertex[1].y==vertex[2].y) return FALSE;\r
+\r
+ vertex[0].x-=VERTEX_OFFX; // otherwise a small offset\r
+ vertex[0].y-=VERTEX_OFFY; // to get better accuracy\r
+ vertex[1].x-=VERTEX_OFFX;\r
+ vertex[1].y-=VERTEX_OFFY;\r
+ vertex[2].x-=VERTEX_OFFX;\r
+ vertex[2].y-=VERTEX_OFFY;\r
+ vertex[3].x-=VERTEX_OFFX;\r
+ vertex[3].y-=VERTEX_OFFY;\r
+\r
+ return FALSE;\r
+}\r
+\r
+///////////////////////////////////////////////////////// \r
+\r
+BOOL offset2(void)\r
+{\r
+ if(bDisplayNotSet)\r
+ SetOGLDisplaySettings(1);\r
+\r
+ if(!(dwActFixes&16))\r
+ {\r
+ lx0=(short)(((int)lx0<<SIGNSHIFT)>>SIGNSHIFT);\r
+ lx1=(short)(((int)lx1<<SIGNSHIFT)>>SIGNSHIFT);\r
+ ly0=(short)(((int)ly0<<SIGNSHIFT)>>SIGNSHIFT);\r
+ ly1=(short)(((int)ly1<<SIGNSHIFT)>>SIGNSHIFT);\r
+\r
+ if(CheckCoord2()) return TRUE;\r
+ }\r
+\r
+ vertex[0].x=lx0+PSXDisplay.CumulOffset.x;\r
+ vertex[1].x=lx1+PSXDisplay.CumulOffset.x;\r
+ vertex[0].y=ly0+PSXDisplay.CumulOffset.y;\r
+ vertex[1].y=ly1+PSXDisplay.CumulOffset.y;\r
+\r
+ return FALSE;\r
+}\r
+\r
+///////////////////////////////////////////////////////// \r
+\r
+BOOL offset3(void)\r
+{\r
+ if(bDisplayNotSet)\r
+ SetOGLDisplaySettings(1);\r
+\r
+ if(!(dwActFixes&16))\r
+ {\r
+ lx0=(short)(((int)lx0<<SIGNSHIFT)>>SIGNSHIFT);\r
+ lx1=(short)(((int)lx1<<SIGNSHIFT)>>SIGNSHIFT);\r
+ lx2=(short)(((int)lx2<<SIGNSHIFT)>>SIGNSHIFT);\r
+ ly0=(short)(((int)ly0<<SIGNSHIFT)>>SIGNSHIFT);\r
+ ly1=(short)(((int)ly1<<SIGNSHIFT)>>SIGNSHIFT);\r
+ ly2=(short)(((int)ly2<<SIGNSHIFT)>>SIGNSHIFT);\r
+\r
+ if(CheckCoord3()) return TRUE;\r
+ }\r
+\r
+ vertex[0].x=lx0+PSXDisplay.CumulOffset.x;\r
+ vertex[1].x=lx1+PSXDisplay.CumulOffset.x;\r
+ vertex[2].x=lx2+PSXDisplay.CumulOffset.x;\r
+ vertex[0].y=ly0+PSXDisplay.CumulOffset.y;\r
+ vertex[1].y=ly1+PSXDisplay.CumulOffset.y;\r
+ vertex[2].y=ly2+PSXDisplay.CumulOffset.y;\r
+\r
+ return FALSE;\r
+}\r
+\r
+///////////////////////////////////////////////////////// \r
+\r
+BOOL offset4(void)\r
+{\r
+ if(bDisplayNotSet)\r
+ SetOGLDisplaySettings(1);\r
+\r
+ if(!(dwActFixes&16))\r
+ {\r
+ lx0=(short)(((int)lx0<<SIGNSHIFT)>>SIGNSHIFT);\r
+ lx1=(short)(((int)lx1<<SIGNSHIFT)>>SIGNSHIFT);\r
+ lx2=(short)(((int)lx2<<SIGNSHIFT)>>SIGNSHIFT);\r
+ lx3=(short)(((int)lx3<<SIGNSHIFT)>>SIGNSHIFT);\r
+ ly0=(short)(((int)ly0<<SIGNSHIFT)>>SIGNSHIFT);\r
+ ly1=(short)(((int)ly1<<SIGNSHIFT)>>SIGNSHIFT);\r
+ ly2=(short)(((int)ly2<<SIGNSHIFT)>>SIGNSHIFT);\r
+ ly3=(short)(((int)ly3<<SIGNSHIFT)>>SIGNSHIFT);\r
+\r
+ if(CheckCoord4()) return TRUE;\r
+ }\r
+\r
+ vertex[0].x=lx0+PSXDisplay.CumulOffset.x;\r
+ vertex[1].x=lx1+PSXDisplay.CumulOffset.x;\r
+ vertex[2].x=lx2+PSXDisplay.CumulOffset.x;\r
+ vertex[3].x=lx3+PSXDisplay.CumulOffset.x;\r
+ vertex[0].y=ly0+PSXDisplay.CumulOffset.y;\r
+ vertex[1].y=ly1+PSXDisplay.CumulOffset.y;\r
+ vertex[2].y=ly2+PSXDisplay.CumulOffset.y;\r
+ vertex[3].y=ly3+PSXDisplay.CumulOffset.y;\r
+\r
+ return FALSE;\r
+}\r
+\r
+///////////////////////////////////////////////////////// \r
+\r
+void offsetST(void)\r
+{\r
+ if(bDisplayNotSet)\r
+ SetOGLDisplaySettings(1);\r
+\r
+ if(!(dwActFixes&16))\r
+ {\r
+ lx0=(short)(((int)lx0<<SIGNSHIFT)>>SIGNSHIFT);\r
+ ly0=(short)(((int)ly0<<SIGNSHIFT)>>SIGNSHIFT);\r
+\r
+ if(lx0<-512 && PSXDisplay.DrawOffset.x<=-512)\r
+ lx0+=2048;\r
+\r
+ if(ly0<-512 && PSXDisplay.DrawOffset.y<=-512)\r
+ ly0+=2048;\r
+ }\r
+\r
+ ly1 = ly0;\r
+ ly2 = ly3 = ly0+sprtH;\r
+ lx3 = lx0;\r
+ lx1 = lx2 = lx0+sprtW;\r
+\r
+ vertex[0].x=lx0+PSXDisplay.CumulOffset.x;\r
+ vertex[1].x=lx1+PSXDisplay.CumulOffset.x;\r
+ vertex[2].x=lx2+PSXDisplay.CumulOffset.x;\r
+ vertex[3].x=lx3+PSXDisplay.CumulOffset.x;\r
+ vertex[0].y=ly0+PSXDisplay.CumulOffset.y;\r
+ vertex[1].y=ly1+PSXDisplay.CumulOffset.y;\r
+ vertex[2].y=ly2+PSXDisplay.CumulOffset.y;\r
+ vertex[3].y=ly3+PSXDisplay.CumulOffset.y;\r
+}\r
+\r
+///////////////////////////////////////////////////////// \r
+\r
+void offsetScreenUpload(long Position)\r
+{\r
+ if(bDisplayNotSet)\r
+ SetOGLDisplaySettings(1);\r
+\r
+ if(Position==-1)\r
+ {\r
+ long lmdx,lmdy;\r
+\r
+ lmdx=xrUploadArea.x0;\r
+ lmdy=xrUploadArea.y0;\r
+\r
+ lx0-=lmdx;\r
+ ly0-=lmdy;\r
+ lx1-=lmdx;\r
+ ly1-=lmdy;\r
+ lx2-=lmdx;\r
+ ly2-=lmdy;\r
+ lx3-=lmdx;\r
+ ly3-=lmdy;\r
+ }\r
+ else\r
+ if(Position)\r
+ {\r
+ lx0-=PSXDisplay.DisplayPosition.x;\r
+ ly0-=PSXDisplay.DisplayPosition.y;\r
+ lx1-=PSXDisplay.DisplayPosition.x;\r
+ ly1-=PSXDisplay.DisplayPosition.y;\r
+ lx2-=PSXDisplay.DisplayPosition.x;\r
+ ly2-=PSXDisplay.DisplayPosition.y;\r
+ lx3-=PSXDisplay.DisplayPosition.x;\r
+ ly3-=PSXDisplay.DisplayPosition.y;\r
+ }\r
+ else\r
+ {\r
+ lx0-=PreviousPSXDisplay.DisplayPosition.x;\r
+ ly0-=PreviousPSXDisplay.DisplayPosition.y;\r
+ lx1-=PreviousPSXDisplay.DisplayPosition.x;\r
+ ly1-=PreviousPSXDisplay.DisplayPosition.y;\r
+ lx2-=PreviousPSXDisplay.DisplayPosition.x;\r
+ ly2-=PreviousPSXDisplay.DisplayPosition.y;\r
+ lx3-=PreviousPSXDisplay.DisplayPosition.x;\r
+ ly3-=PreviousPSXDisplay.DisplayPosition.y;\r
+ }\r
+\r
+ vertex[0].x=lx0 + PreviousPSXDisplay.Range.x0;\r
+ vertex[1].x=lx1 + PreviousPSXDisplay.Range.x0;\r
+ vertex[2].x=lx2 + PreviousPSXDisplay.Range.x0;\r
+ vertex[3].x=lx3 + PreviousPSXDisplay.Range.x0;\r
+ vertex[0].y=ly0 + PreviousPSXDisplay.Range.y0;\r
+ vertex[1].y=ly1 + PreviousPSXDisplay.Range.y0;\r
+ vertex[2].y=ly2 + PreviousPSXDisplay.Range.y0;\r
+ vertex[3].y=ly3 + PreviousPSXDisplay.Range.y0;\r
+\r
+ if(iUseMask)\r
+ {\r
+ vertex[0].z=vertex[1].z=vertex[2].z=vertex[3].z=gl_z;\r
+ gl_z+=0.00004f;\r
+ }\r
+}\r
+ \r
+///////////////////////////////////////////////////////// \r
+\r
+void offsetBlk(void)\r
+{\r
+ if(bDisplayNotSet)\r
+ SetOGLDisplaySettings(1);\r
+ \r
+ vertex[0].x=lx0-PSXDisplay.GDrawOffset.x + PreviousPSXDisplay.Range.x0;\r
+ vertex[1].x=lx1-PSXDisplay.GDrawOffset.x + PreviousPSXDisplay.Range.x0;\r
+ vertex[2].x=lx2-PSXDisplay.GDrawOffset.x + PreviousPSXDisplay.Range.x0;\r
+ vertex[3].x=lx3-PSXDisplay.GDrawOffset.x + PreviousPSXDisplay.Range.x0;\r
+ vertex[0].y=ly0-PSXDisplay.GDrawOffset.y + PreviousPSXDisplay.Range.y0;\r
+ vertex[1].y=ly1-PSXDisplay.GDrawOffset.y + PreviousPSXDisplay.Range.y0;\r
+ vertex[2].y=ly2-PSXDisplay.GDrawOffset.y + PreviousPSXDisplay.Range.y0;\r
+ vertex[3].y=ly3-PSXDisplay.GDrawOffset.y + PreviousPSXDisplay.Range.y0;\r
+\r
+ if(iUseMask)\r
+ {\r
+ vertex[0].z=vertex[1].z=vertex[2].z=vertex[3].z=gl_z;\r
+ gl_z+=0.00004f;\r
+ }\r
+}\r
+\r
+////////////////////////////////////////////////////////////////////////\r
+// texture sow/tow calculations\r
+////////////////////////////////////////////////////////////////////////\r
+\r
+void assignTextureVRAMWrite(void)\r
+{\r
+#ifdef OWNSCALE\r
+\r
+ vertex[0].sow=0.5f/ ST_FACVRAMX;\r
+ vertex[0].tow=0.5f/ ST_FACVRAM;\r
+\r
+ vertex[1].sow=(float)gl_ux[1]/ ST_FACVRAMX;\r
+ vertex[1].tow=0.5f/ ST_FACVRAM;\r
+\r
+ vertex[2].sow=(float)gl_ux[2]/ ST_FACVRAMX;\r
+ vertex[2].tow=(float)gl_vy[2]/ ST_FACVRAM;\r
+\r
+ vertex[3].sow=0.5f/ ST_FACVRAMX;\r
+ vertex[3].tow=(float)gl_vy[3]/ ST_FACVRAM;\r
+\r
+#else\r
+\r
+ if(gl_ux[1]==255)\r
+ {\r
+ vertex[0].sow=(gl_ux[0]*255.99f)/255.0f;\r
+ vertex[1].sow=(gl_ux[1]*255.99f)/255.0f;\r
+ vertex[2].sow=(gl_ux[2]*255.99f)/255.0f;\r
+ vertex[3].sow=(gl_ux[3]*255.99f)/255.0f;\r
+ }\r
+ else\r
+ {\r
+ vertex[0].sow=gl_ux[0];\r
+ vertex[1].sow=gl_ux[1];\r
+ vertex[2].sow=gl_ux[2];\r
+ vertex[3].sow=gl_ux[3];\r
+ }\r
+\r
+ vertex[0].tow=gl_vy[0];\r
+ vertex[1].tow=gl_vy[1];\r
+ vertex[2].tow=gl_vy[2];\r
+ vertex[3].tow=gl_vy[3];\r
+\r
+#endif\r
+}\r
+\r
+GLuint gLastTex=0;\r
+GLuint gLastFMode=(GLuint)-1;\r
+\r
+///////////////////////////////////////////////////////// \r
+\r
+void assignTextureSprite(void)\r
+{\r
+ if(bUsingTWin)\r
+ {\r
+ vertex[0].sow=vertex[3].sow=(float)gl_ux[0]/TWin.UScaleFactor;\r
+ vertex[1].sow=vertex[2].sow=(float)sSprite_ux2/TWin.UScaleFactor;\r
+ vertex[0].tow=vertex[1].tow=(float)gl_vy[0]/TWin.VScaleFactor;\r
+ vertex[2].tow=vertex[3].tow=(float)sSprite_vy2/TWin.VScaleFactor;\r
+ gLastTex=gTexName;\r
+ }\r
+ else\r
+ {\r
+#ifdef OWNSCALE\r
+\r
+ vertex[0].sow=vertex[3].sow=(float)gl_ux[0] / ST_FACSPRITE;\r
+ vertex[1].sow=vertex[2].sow=(float)sSprite_ux2 / ST_FACSPRITE;\r
+ vertex[0].tow=vertex[1].tow=(float)gl_vy[0] / ST_FACSPRITE;\r
+ vertex[2].tow=vertex[3].tow=(float)sSprite_vy2 / ST_FACSPRITE;\r
+\r
+#else\r
+ \r
+ vertex[0].sow=vertex[3].sow=gl_ux[0];\r
+ vertex[1].sow=vertex[2].sow=sSprite_ux2;\r
+ vertex[0].tow=vertex[1].tow=gl_vy[0];\r
+ vertex[2].tow=vertex[3].tow=sSprite_vy2;\r
+\r
+#endif\r
+\r
+ if(iFilterType>2) \r
+ {\r
+ if(gLastTex!=gTexName || gLastFMode!=0)\r
+ {\r
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);\r
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);\r
+ gLastTex=gTexName;gLastFMode=0;\r
+ }\r
+ }\r
+ }\r
+\r
+ if(usMirror & 0x1000) \r
+ {\r
+ vertex[0].sow=vertex[1].sow;\r
+ vertex[1].sow=vertex[2].sow=vertex[3].sow;\r
+ vertex[3].sow=vertex[0].sow;\r
+ }\r
+\r
+ if(usMirror & 0x2000) \r
+ {\r
+ vertex[0].tow=vertex[3].tow;\r
+ vertex[2].tow=vertex[3].tow=vertex[1].tow;\r
+ vertex[1].tow=vertex[0].tow;\r
+ }\r
+\r
+}\r
+\r
+///////////////////////////////////////////////////////// \r
+\r
+void assignTexture3(void)\r
+{\r
+ if(bUsingTWin)\r
+ {\r
+ vertex[0].sow=(float)gl_ux[0]/TWin.UScaleFactor;\r
+ vertex[0].tow=(float)gl_vy[0]/TWin.VScaleFactor;\r
+ vertex[1].sow=(float)gl_ux[1]/TWin.UScaleFactor;\r
+ vertex[1].tow=(float)gl_vy[1]/TWin.VScaleFactor;\r
+ vertex[2].sow=(float)gl_ux[2]/TWin.UScaleFactor;\r
+ vertex[2].tow=(float)gl_vy[2]/TWin.VScaleFactor;\r
+ gLastTex=gTexName;\r
+ }\r
+ else\r
+ {\r
+#ifdef OWNSCALE\r
+ vertex[0].sow=(float)gl_ux[0] / ST_FACTRI;\r
+ vertex[0].tow=(float)gl_vy[0] / ST_FACTRI;\r
+ vertex[1].sow=(float)gl_ux[1] / ST_FACTRI;\r
+\r
+ vertex[1].tow=(float)gl_vy[1] / ST_FACTRI;\r
+ vertex[2].sow=(float)gl_ux[2] / ST_FACTRI;\r
+ vertex[2].tow=(float)gl_vy[2] / ST_FACTRI;\r
+#else\r
+ vertex[0].sow=gl_ux[0];\r
+ vertex[0].tow=gl_vy[0];\r
+ vertex[1].sow=gl_ux[1];\r
+ vertex[1].tow=gl_vy[1];\r
+ vertex[2].sow=gl_ux[2];\r
+ vertex[2].tow=gl_vy[2];\r
+#endif\r
+\r
+ if(iFilterType>2) \r
+ {\r
+ if(gLastTex!=gTexName || gLastFMode!=1)\r
+ {\r
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);\r
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);\r
+ gLastTex=gTexName;gLastFMode=1;\r
+ }\r
+ }\r
+\r
+ if(iFilterType) \r
+ {\r
+ float fxmin=256.0f,fxmax=0.0f,fymin=256.0f,fymax=0.0f;int i;\r
+ for(i=0;i<3;i++)\r
+ {\r
+ if(vertex[i].sow<fxmin) fxmin=vertex[i].sow;\r
+ if(vertex[i].tow<fymin) fymin=vertex[i].tow;\r
+ if(vertex[i].sow>fxmax) fxmax=vertex[i].sow;\r
+ if(vertex[i].tow>fymax) fymax=vertex[i].tow; \r
+ }\r
+\r
+ for(i=0;i<3;i++)\r
+ {\r
+ if(vertex[i].sow==fxmin) vertex[i].sow+=ST_BFFACSORT;\r
+ if(vertex[i].sow==fxmax) vertex[i].sow-=ST_BFFACSORT;\r
+ if(vertex[i].tow==fymin) vertex[i].tow+=ST_BFFACSORT;\r
+ if(vertex[i].tow==fymax) vertex[i].tow-=ST_BFFACSORT;\r
+ }\r
+ }\r
+ }\r
+}\r
+\r
+///////////////////////////////////////////////////////// \r
+\r
+void assignTexture4(void)\r
+{\r
+ if(bUsingTWin)\r
+ {\r
+ vertex[0].sow=(float)gl_ux[0]/TWin.UScaleFactor;\r
+ vertex[0].tow=(float)gl_vy[0]/TWin.VScaleFactor;\r
+ vertex[1].sow=(float)gl_ux[1]/TWin.UScaleFactor;\r
+ vertex[1].tow=(float)gl_vy[1]/TWin.VScaleFactor;\r
+ vertex[2].sow=(float)gl_ux[2]/TWin.UScaleFactor;\r
+ vertex[2].tow=(float)gl_vy[2]/TWin.VScaleFactor;\r
+ vertex[3].sow=(float)gl_ux[3]/TWin.UScaleFactor;\r
+ vertex[3].tow=(float)gl_vy[3]/TWin.VScaleFactor;\r
+ gLastTex=gTexName;\r
+ }\r
+ else\r
+ {\r
+#ifdef OWNSCALE\r
+ vertex[0].sow=(float)gl_ux[0] / ST_FAC;\r
+ vertex[0].tow=(float)gl_vy[0] / ST_FAC;\r
+ vertex[1].sow=(float)gl_ux[1] / ST_FAC;\r
+ vertex[1].tow=(float)gl_vy[1] / ST_FAC;\r
+ vertex[2].sow=(float)gl_ux[2] / ST_FAC;\r
+ vertex[2].tow=(float)gl_vy[2] / ST_FAC;\r
+ vertex[3].sow=(float)gl_ux[3] / ST_FAC;\r
+ vertex[3].tow=(float)gl_vy[3] / ST_FAC;\r
+#else\r
+ vertex[0].sow=gl_ux[0];\r
+ vertex[0].tow=gl_vy[0];\r
+ vertex[1].sow=gl_ux[1];\r
+ vertex[1].tow=gl_vy[1];\r
+ vertex[2].sow=gl_ux[2];\r
+ vertex[2].tow=gl_vy[2];\r
+ vertex[3].sow=gl_ux[3];\r
+ vertex[3].tow=gl_vy[3];\r
+#endif\r
+\r
+ if(iFilterType>2) \r
+ {\r
+ if(gLastTex!=gTexName || gLastFMode!=1)\r
+ {\r
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);\r
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);\r
+ gLastTex=gTexName;gLastFMode=1;\r
+ }\r
+ }\r
+\r
+ if(iFilterType) \r
+ {\r
+ float fxmin=256.0f,fxmax=0.0f,fymin=256.0f,fymax=0.0f;int i;\r
+ for(i=0;i<4;i++)\r
+ {\r
+ if(vertex[i].sow<fxmin) fxmin=vertex[i].sow;\r
+ if(vertex[i].tow<fymin) fymin=vertex[i].tow;\r
+ if(vertex[i].sow>fxmax) fxmax=vertex[i].sow;\r
+ if(vertex[i].tow>fymax) fymax=vertex[i].tow; \r
+ }\r
+\r
+ for(i=0;i<4;i++)\r
+ {\r
+ if(vertex[i].sow==fxmin) vertex[i].sow+=ST_BFFACSORT;\r
+ if(vertex[i].sow==fxmax) vertex[i].sow-=ST_BFFACSORT;\r
+ if(vertex[i].tow==fymin) vertex[i].tow+=ST_BFFACSORT;\r
+ if(vertex[i].tow==fymax) vertex[i].tow-=ST_BFFACSORT;\r
+ }\r
+ }\r
+ }\r
+}\r
+\r
+////////////////////////////////////////////////////////////////////////\r
+////////////////////////////////////////////////////////////////////////\r
+////////////////////////////////////////////////////////////////////////\r
+\r
+////////////////////////////////////////////////////////////////////////\r
+// render pos / buffers\r
+////////////////////////////////////////////////////////////////////////\r
+\r
+#ifndef _WINDOWS\r
+#define EqualRect(pr1,pr2) ((pr1)->left==(pr2)->left && (pr1)->top==(pr2)->top && (pr1)->right==(pr2)->right && (pr1)->bottom==(pr2)->bottom)\r
+#endif\r
+\r
+////////////////////////////////////////////////////////////////////////\r
+// SetDisplaySettings: "simply" calcs the new drawing area and updates\r
+// the ogl clipping (scissor) \r
+\r
+BOOL bSetClip=FALSE;\r
+\r
+void SetOGLDisplaySettings(BOOL DisplaySet)\r
+{\r
+ static RECT rprev={0,0,0,0};\r
+ static RECT rC ={0,0,0,0};\r
+ static int iOldX=0;\r
+ static int iOldY=0;\r
+ RECT r;float XS,YS;\r
+\r
+ bDisplayNotSet = FALSE;\r
+\r
+ //----------------------------------------------------// that's a whole screen upload\r
+ if(!DisplaySet)\r
+ {\r
+ RECT rX;\r
+ PSXDisplay.GDrawOffset.x=0;\r
+ PSXDisplay.GDrawOffset.y=0;\r
+\r
+ PSXDisplay.CumulOffset.x = PSXDisplay.DrawOffset.x+PreviousPSXDisplay.Range.x0;\r
+ PSXDisplay.CumulOffset.y = PSXDisplay.DrawOffset.y+PreviousPSXDisplay.Range.y0;\r
+\r
+ rprev.left=rprev.left+1;\r
+\r
+ rX=rRatioRect;\r
+ rX.top=iResY-(rRatioRect.top+rRatioRect.bottom);\r
+\r
+ if(bSetClip || !EqualRect(&rC,&rX))\r
+ {\r
+ rC=rX;\r
+ glScissor(rC.left,rC.top,rC.right,rC.bottom);\r
+ bSetClip=FALSE; \r
+ }\r
+ return;\r
+ }\r
+ //----------------------------------------------------// \r
+\r
+ PSXDisplay.GDrawOffset.y = PreviousPSXDisplay.DisplayPosition.y;\r
+ PSXDisplay.GDrawOffset.x = PreviousPSXDisplay.DisplayPosition.x;\r
+ PSXDisplay.CumulOffset.x = PSXDisplay.DrawOffset.x - PSXDisplay.GDrawOffset.x+PreviousPSXDisplay.Range.x0;\r
+ PSXDisplay.CumulOffset.y = PSXDisplay.DrawOffset.y - PSXDisplay.GDrawOffset.y+PreviousPSXDisplay.Range.y0;\r
+\r
+ r.top =PSXDisplay.DrawArea.y0 - PreviousPSXDisplay.DisplayPosition.y;\r
+ r.bottom=PSXDisplay.DrawArea.y1 - PreviousPSXDisplay.DisplayPosition.y;\r
+\r
+ if(r.bottom<0 || r.top>=PSXDisplay.DisplayMode.y)\r
+ {\r
+ r.top =PSXDisplay.DrawArea.y0 - PSXDisplay.DisplayPosition.y;\r
+ r.bottom=PSXDisplay.DrawArea.y1 - PSXDisplay.DisplayPosition.y;\r
+ }\r
+\r
+ r.left =PSXDisplay.DrawArea.x0 - PreviousPSXDisplay.DisplayPosition.x;\r
+ r.right =PSXDisplay.DrawArea.x1 - PreviousPSXDisplay.DisplayPosition.x;\r
+\r
+ if(r.right<0 || r.left>=PSXDisplay.DisplayMode.x)\r
+ {\r
+ r.left =PSXDisplay.DrawArea.x0 - PSXDisplay.DisplayPosition.x;\r
+ r.right =PSXDisplay.DrawArea.x1 - PSXDisplay.DisplayPosition.x;\r
+ }\r
+\r
+ if(!bSetClip && EqualRect(&r,&rprev) &&\r
+ iOldX == PSXDisplay.DisplayMode.x &&\r
+ iOldY == PSXDisplay.DisplayMode.y)\r
+ return;\r
+\r
+ rprev = r;\r
+ iOldX = PSXDisplay.DisplayMode.x;\r
+ iOldY = PSXDisplay.DisplayMode.y;\r
+\r
+ XS=(float)rRatioRect.right/(float)PSXDisplay.DisplayMode.x;\r
+ YS=(float)rRatioRect.bottom/(float)PSXDisplay.DisplayMode.y;\r
+\r
+ if(PreviousPSXDisplay.Range.x0)\r
+ {\r
+ short s=PreviousPSXDisplay.Range.x0+PreviousPSXDisplay.Range.x1;\r
+\r
+ r.left+=PreviousPSXDisplay.Range.x0+1;\r
+\r
+ r.right+=PreviousPSXDisplay.Range.x0;\r
+\r
+ if(r.left>s) r.left=s;\r
+ if(r.right>s) r.right=s;\r
+ }\r
+\r
+ if(PreviousPSXDisplay.Range.y0)\r
+ {\r
+ short s=PreviousPSXDisplay.Range.y0+PreviousPSXDisplay.Range.y1;\r
+\r
+ r.top+=PreviousPSXDisplay.Range.y0+1;\r
+ r.bottom+=PreviousPSXDisplay.Range.y0;\r
+\r
+ if(r.top>s) r.top=s;\r
+ if(r.bottom>s) r.bottom=s;\r
+ }\r
+\r
+ // Set the ClipArea variables to reflect the new screen,\r
+ // offset from zero (since it is a new display buffer)\r
+ r.left = (int)(((float)(r.left)) *XS);\r
+ r.top = (int)(((float)(r.top)) *YS);\r
+ r.right = (int)(((float)(r.right + 1))*XS);\r
+ r.bottom = (int)(((float)(r.bottom + 1))*YS);\r
+\r
+ // Limit clip area to the screen size\r
+ if (r.left > iResX) r.left = iResX;\r
+ if (r.left < 0) r.left = 0;\r
+ if (r.top > iResY) r.top = iResY;\r
+ if (r.top < 0) r.top = 0;\r
+ if (r.right > iResX) r.right = iResX;\r
+ if (r.right < 0) r.right = 0;\r
+ if (r.bottom > iResY) r.bottom = iResY;\r
+ if (r.bottom < 0) r.bottom = 0;\r
+\r
+ r.right -=r.left;\r
+ r.bottom-=r.top;\r
+ r.top=iResY-(r.top+r.bottom);\r
+\r
+ r.left+=rRatioRect.left;\r
+ r.top -=rRatioRect.top;\r
+\r
+ if(bSetClip || !EqualRect(&r,&rC))\r
+ {\r
+ glScissor(r.left,r.top,r.right,r.bottom);\r
+ rC=r;\r
+ bSetClip=FALSE;\r
+ }\r
+}\r
+\r
+////////////////////////////////////////////////////////////////////////\r
+////////////////////////////////////////////////////////////////////////\r
+////////////////////////////////////////////////////////////////////////\r
+\r