From ce879073e4f228deec8bec5db8a2ff640636c88f Mon Sep 17 00:00:00 2001 From: notaz Date: Fri, 31 Dec 2010 16:57:02 +0200 Subject: [PATCH] gpu-gles from psx4m --- plugins/gpu-gles/gpuDraw.c | 1345 +++++++++ plugins/gpu-gles/gpuDraw.h | 83 + plugins/gpu-gles/gpuExternals.h | 570 ++++ plugins/gpu-gles/gpuFps.c | 991 ++++++ plugins/gpu-gles/gpuFps.h | 66 + plugins/gpu-gles/gpuPlugin.c | 2960 ++++++++++++++++++ plugins/gpu-gles/gpuPlugin.h | 134 + plugins/gpu-gles/gpuPrim.c | 5022 +++++++++++++++++++++++++++++++ plugins/gpu-gles/gpuPrim.h | 58 + plugins/gpu-gles/gpuStdafx.h | 99 + plugins/gpu-gles/gpuTexture.c | 4226 ++++++++++++++++++++++++++ plugins/gpu-gles/gpuTexture.h | 87 + 12 files changed, 15641 insertions(+) create mode 100644 plugins/gpu-gles/gpuDraw.c create mode 100644 plugins/gpu-gles/gpuDraw.h create mode 100644 plugins/gpu-gles/gpuExternals.h create mode 100644 plugins/gpu-gles/gpuFps.c create mode 100644 plugins/gpu-gles/gpuFps.h create mode 100644 plugins/gpu-gles/gpuPlugin.c create mode 100644 plugins/gpu-gles/gpuPlugin.h create mode 100644 plugins/gpu-gles/gpuPrim.c create mode 100644 plugins/gpu-gles/gpuPrim.h create mode 100644 plugins/gpu-gles/gpuStdafx.h create mode 100644 plugins/gpu-gles/gpuTexture.c create mode 100644 plugins/gpu-gles/gpuTexture.h diff --git a/plugins/gpu-gles/gpuDraw.c b/plugins/gpu-gles/gpuDraw.c new file mode 100644 index 00000000..3d09c333 --- /dev/null +++ b/plugins/gpu-gles/gpuDraw.c @@ -0,0 +1,1345 @@ +/*************************************************************************** + draw.c - description + ------------------- + begin : Sun Mar 08 2009 + copyright : (C) 1999-2009 by Pete Bernert + web : www.pbernert.com + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2009/03/08 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + + +#define _IN_DRAW + +#ifdef _WINDOWS +#include "stdafx.h" +#include +#include +#include +#include "externals.h" +#include "gpu.h" +#include "draw.h" +#include "prim.h" +#include "texture.h" +#else +#include "gpuExternals.h" +#include "GPUPlugin.h" +#include "gpuDraw.h" +#include "gpuPrim.h" +#include "gpuTexture.h" +#include "gpuStdafx.h" + +#include +#include +#include +#endif +//#include "menu.h" + +//////////////////////////////////////////////////////////////////////////////////// +// defines + +#define SIGNBIT 0x800 +#define S_MASK 0xf000 +#define L_MASK 0xfffff000 + +// ownscale: some ogl drivers have buggy texture matrix funcs, so it +// is safer to calc sow/tow ourselves + +#ifdef OWNSCALE + +/////////////////////////////////////////////////////////////// + +#define ST_FACSPRITE 255.99f +#define ST_BFFACSPRITE 0.5f/256.0f +#define ST_BFFACSPRITESORT 0.333f/256.0f + +#define ST_OFFSET 0.5f/256.0f; + +#define ST_FAC 255.99f +#define ST_BFFAC 0.5f/256.0f +#define ST_BFFACSORT 0.333f/256.0f + +#define ST_FACTRI 255.99f +#define ST_BFFACTRI 0.5f/256.0f +#define ST_BFFACTRISORT 0.333f/256.0f + +#define ST_FACVRAMX 255.0f +#define ST_FACVRAM 256.0f + +/////////////////////////////////////////////////////////////// + +#else + +#define ST_BFFACSPRITE 0.5f +#define ST_BFFACSPRITESORT 0.333f + +#define ST_BFFAC 0.5f +#define ST_BFFACSORT 0.333f + +#define ST_BFFACTRI 0.5f +#define ST_BFFACTRISORT 0.333f + +#define ST_OFFSET 0.5f; + +#endif + +//////////////////////////////////////////////////////////////////////////////////// +// draw globals + +#ifdef _WINDOWS +HDC dcGlobal=NULL; +HWND hWWindow; +#else +void glBlendEquationEXT(GLenum mode); +void glColorTableEXT(GLenum target, GLenum internalFormat, GLsizei width, GLenum format,GLenum type, const GLvoid *data); +#endif + +// draw globals; most will be initialized again later (by config or checks) + +BOOL bIsFirstFrame=TRUE; + +// resolution/ratio vars + +int iResX; +int iResY; +BOOL bKeepRatio=FALSE; +RECT rRatioRect; + +// psx mask related vars + +BOOL bCheckMask=FALSE; +int iUseMask=0; +int iSetMask=0; +unsigned short sSetMask=0; +unsigned long lSetMask=0; + +// drawing/coord vars + +OGLVertex vertex[4]; +GLubyte gl_ux[8]; +GLubyte gl_vy[8]; +short sprtY,sprtX,sprtH,sprtW; + +// drawing options + +BOOL bOpaquePass; +BOOL bAdvancedBlend; + +// OGL extension support + + +// gfx card buffer infos + +int iDepthFunc=0; +int iZBufferDepth=0; +GLbitfield uiBufferBits=GL_COLOR_BUFFER_BIT; + +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +// Set OGL pixel format +//////////////////////////////////////////////////////////////////////// + +#ifdef _WINDOWS +BOOL bSetupPixelFormat(HDC hDC) +{ + int pixelformat; + static PIXELFORMATDESCRIPTOR pfd = + { + sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd + 1, // version number + PFD_DRAW_TO_WINDOW | // support window + PFD_SUPPORT_OPENGL | // support OpenGL + PFD_DOUBLEBUFFER, // double buffered + PFD_TYPE_RGBA, // RGBA type + 16, // 16-bit color depth (adjusted later) + 0, 0, 0, 0, 0, 0, // color bits ignored + 0, // no alpha buffer + 0, // shift bit ignored + 0, // no accumulation buffer + 0, 0, 0, 0, // accum bits ignored + 0, // z-buffer + 0, + 0, // no auxiliary buffer + PFD_MAIN_PLANE, // main layer + 0, // reserved + 0, 0, 0 // layer masks ignored + }; + + pfd.cColorBits=iColDepth; // set user color depth + pfd.cDepthBits=iZBufferDepth; // set user zbuffer (by psx mask) + + if((pixelformat=ChoosePixelFormat(hDC,&pfd))==0) + { + MessageBox(NULL,"ChoosePixelFormat failed","Error",MB_OK); + return FALSE; + } + + if(SetPixelFormat(hDC,pixelformat, &pfd)==FALSE) + { + MessageBox(NULL,"SetPixelFormat failed","Error",MB_OK); + return FALSE; + } + + return TRUE; +} +#endif + +//////////////////////////////////////////////////////////////////////// +// Get extension infos (f.e. pal textures / packed pixels) +//////////////////////////////////////////////////////////////////////// + +void GetExtInfos(void) +{ + BOOL bPacked=FALSE; // default: no packed pixel support + + if(strstr((s8 *)glGetString(GL_EXTENSIONS), // packed pixels available? + "GL_EXT_packed_pixels")) + bPacked=TRUE; // -> ok + + + #ifdef _WINDOWS + iClampType=GL_CLAMP; +#else + iClampType=GL_CLAMP_TO_EDGE; +#endif +} + +//////////////////////////////////////////////////////////////////////// +// Setup some stuff depending on user settings or in-game toggle +//////////////////////////////////////////////////////////////////////// + +void SetExtGLFuncs(void) +{ + //----------------------------------------------------// + + SetFixes(); // update fix infos + + //----------------------------------------------------// + + { + if(bAdvancedBlend) bUseMultiPass=TRUE; // -> pseudo-advanced with 2 passes + else bUseMultiPass=FALSE; // -> or simple 'bright color' mode +// bGLBlend=FALSE; // -> no ext blending! + + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + } + + if(bOpaquePass) // opaque mode? + { + if(dwActFixes&32) + { + TCF[0]=CP8RGBA_0; + PalTexturedColourFn=CP8RGBA; // -> init col func + } + else + { + TCF[0]=XP8RGBA_0; + PalTexturedColourFn=XP8RGBA; // -> init col func + } + + TCF[1]=XP8RGBA_1; + glAlphaFuncx(GL_GREATER,0.49f); + } + else // no opaque mode? + { + TCF[0]=TCF[1]=P8RGBA; + PalTexturedColourFn=P8RGBA; // -> init col func + glAlphaFuncx(GL_NOTEQUAL,0); // --> set alpha func + } + + //----------------------------------------------------// + + LoadSubTexFn=LoadSubTexturePageSort; // init load tex ptr + + bBlendEnable=FALSE; // init blending: off + glDisable(GL_BLEND); + + SetScanTrans(); // init scan lines (if wanted) +} + +//////////////////////////////////////////////////////////////////////// +// setup scan lines +//////////////////////////////////////////////////////////////////////// + +#define R_TSP 0x00,0x45,0x00,0xff +#define G_TSP 0x00,0x00,0x45,0xff +#define B_TSP 0x45,0x00,0x00,0xff +#define O_TSP 0x45,0x45,0x45,0xff +#define N_TSP 0x00,0x00,0x00,0xff + +GLuint gTexScanName=0; + +GLubyte texscan[4][16]= +{ +{R_TSP, G_TSP, B_TSP, N_TSP}, +{O_TSP, N_TSP, O_TSP, N_TSP}, +{B_TSP, N_TSP, R_TSP, G_TSP}, +{O_TSP, N_TSP, O_TSP, N_TSP} +}; + +void CreateScanLines(void) +{ +} + +//////////////////////////////////////////////////////////////////////// +// Initialize OGL +//////////////////////////////////////////////////////////////////////// + +#ifdef _WINDOWS +HGLRC GLCONTEXT=NULL; +#endif + +#ifdef MAEMO_CHANGES +bool TestEGLError(const char* pszLocation) +{ + /* + eglGetError returns the last error that has happened using egl, + not the status of the last called function. The user has to + check after every single egl call or at least once every frame. + */ + EGLint iErr = eglGetError(); + if (iErr != EGL_SUCCESS) + { + printf("%s failed (%d).\n", pszLocation, iErr); + return false; + } + + return true; +} + +void maemoGLinit(){ + iResX= 800; + iResY =480; + + + printf ("maemo GL init\n"); + long int winxid=GDK_WINDOW_XID(GTK_WIDGET(windowG)->window); + printf ("%d\n",winxid); + + EGLContext context = 0; + EGLConfig eglConfig = 0; + EGLContext eglContext = 0; + display = eglGetDisplay( EGL_DEFAULT_DISPLAY ); + + if( eglInitialize( display, NULL, NULL ) == EGL_FALSE ) + { + printf( "EGL Initialize failed!\n" ); + + } + +const EGLint attributeList[] = { + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, + /*EGL_BUFFER_SIZE, 32, */ + EGL_NONE + }; + + EGLint pi32ConfigAttribs[5]; + pi32ConfigAttribs[0] = EGL_SURFACE_TYPE; + pi32ConfigAttribs[1] = EGL_WINDOW_BIT; + pi32ConfigAttribs[2] = EGL_RENDERABLE_TYPE; + pi32ConfigAttribs[3] = EGL_OPENGL_ES2_BIT; + pi32ConfigAttribs[4] = EGL_NONE; + + EGLint pi32ContextAttribs[3]; + pi32ContextAttribs[0] = EGL_CONTEXT_CLIENT_VERSION; + pi32ContextAttribs[1] = 2; + pi32ContextAttribs[2] = EGL_NONE; + + int iConfigs; + if (!eglChooseConfig(display, attributeList, &eglConfig, 1, &iConfigs) || (iConfigs != 1)) + { + printf("Error: eglChooseConfig() failed.\n"); + } + printf ("%d\n",iConfigs); + surface = eglCreateWindowSurface(display, eglConfig, (void*)winxid, NULL); + printf ("%d\n",surface); + if (!TestEGLError("eglCreateWindowSurface")) + { + printf ("eglCreateWindowSurface fail"); + } + + //context = eglCreateContext(display, eglConfig, NULL, pi32ContextAttribs); + context =eglCreateContext( display, eglConfig, + EGL_NO_CONTEXT, NULL + ); +printf ("%d\n",context); + if (!TestEGLError("eglCreateContext")) + { + printf("error eglCreateContext"); + } + + eglMakeCurrent(display, surface, surface, context); + + if (!TestEGLError("eglMakeCurrent")) + { + printf("error eglMakeCurrent"); + } +} +#endif + +int GLinitialize() +{ + //----------------------------------------------------// +#ifdef _WINDOWS + HGLRC objectRC; + // init + dcGlobal = GetDC(hWWindow); // FIRST: dc/rc stuff + objectRC = wglCreateContext(dcGlobal); + GLCONTEXT=objectRC; + wglMakeCurrent(dcGlobal, objectRC); + // CheckWGLExtensions(dcGlobal); + if(bWindowMode) ReleaseDC(hWWindow,dcGlobal); // win mode: release dc again +#endif +#ifdef MAEMO_CHANGES + maemoGLinit(); +#endif + //----------------------------------------------------// + + glViewport(rRatioRect.left, // init viewport by ratio rect + iResY-(rRatioRect.top+rRatioRect.bottom), + rRatioRect.right, + rRatioRect.bottom); + + glScissor(0, 0, iResX, iResY); // init clipping (fullscreen) + glEnable(GL_SCISSOR_TEST); + +#ifndef OWNSCALE + glMatrixMode(GL_TEXTURE); // init psx tex sow and tow if not "ownscale" + glLoadIdentity(); + glScalef(1.0f/255.99f,1.0f/255.99f,1.0f); // geforce precision hack +#endif + + glMatrixMode(GL_PROJECTION); // init projection with psx resolution + glLoadIdentity(); + glOrtho(0,PSXDisplay.DisplayMode.x, + PSXDisplay.DisplayMode.y, 0, -1, 1); + + if(iZBufferDepth) // zbuffer? + { + uiBufferBits=GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT; + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_ALWAYS); + iDepthFunc=1; + } + else // no zbuffer? + { + uiBufferBits=GL_COLOR_BUFFER_BIT; + glDisable(GL_DEPTH_TEST); + } + + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // first buffer clear + glClear(uiBufferBits); + + GetExtInfos(); // get ext infos + SetExtGLFuncs(); // init all kind of stuff (tex function pointers) + + glEnable(GL_ALPHA_TEST); // wanna alpha test + + { + glDisable(GL_LINE_SMOOTH); + glDisable(GL_POINT_SMOOTH); + } + + ubGloAlpha=127; // init some drawing vars + ubGloColAlpha=127; + TWin.UScaleFactor = 1; + TWin.VScaleFactor = 1; + bDrawMultiPass=FALSE; + bTexEnabled=FALSE; + bUsingTWin=FALSE; + + if(bDrawDither) glEnable(GL_DITHER); // dither mode + else glDisable(GL_DITHER); + + glDisable(GL_FOG); // turn all (currently) unused modes off + glDisable(GL_LIGHTING); + glDisable(GL_STENCIL_TEST); + glDisable(GL_TEXTURE_2D); + glDisable(GL_CULL_FACE); + + glFlush(); // we are done... + glFinish(); + + CreateScanLines(); // setup scanline stuff (if wanted) + + CheckTextureMemory(); // check available tex memory + + if(bKeepRatio) SetAspectRatio(); // set ratio + + + bIsFirstFrame = FALSE; // we have survived the first frame :) + + return 0; +} + +//////////////////////////////////////////////////////////////////////// +// clean up OGL stuff +//////////////////////////////////////////////////////////////////////// + +void GLcleanup() +{ + CleanupTextureStore(); // bye textures + +#ifdef _WINDOWS + wglMakeCurrent(NULL, NULL); // bye context + if(GLCONTEXT) wglDeleteContext(GLCONTEXT); + if(!bWindowMode && dcGlobal) + ReleaseDC(hWWindow,dcGlobal); +#endif +} + +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +// Offset stuff +//////////////////////////////////////////////////////////////////////// + +// please note: it is hardly do-able in a hw/accel plugin to get the +// real psx polygon coord mapping right... the following +// works not to bad with many games, though + +__inline BOOL CheckCoord4() +{ + if(lx0<0) + { + if(((lx1-lx0)>CHKMAX_X) || + ((lx2-lx0)>CHKMAX_X)) + { + if(lx3<0) + { + if((lx1-lx3)>CHKMAX_X) return TRUE; + if((lx2-lx3)>CHKMAX_X) return TRUE; + } + } + } + if(lx1<0) + { + if((lx0-lx1)>CHKMAX_X) return TRUE; + if((lx2-lx1)>CHKMAX_X) return TRUE; + if((lx3-lx1)>CHKMAX_X) return TRUE; + } + if(lx2<0) + { + if((lx0-lx2)>CHKMAX_X) return TRUE; + if((lx1-lx2)>CHKMAX_X) return TRUE; + if((lx3-lx2)>CHKMAX_X) return TRUE; + } + if(lx3<0) + { + if(((lx1-lx3)>CHKMAX_X) || + ((lx2-lx3)>CHKMAX_X)) + { + if(lx0<0) + { + if((lx1-lx0)>CHKMAX_X) return TRUE; + if((lx2-lx0)>CHKMAX_X) return TRUE; + } + } + } + + + if(ly0<0) + { + if((ly1-ly0)>CHKMAX_Y) return TRUE; + if((ly2-ly0)>CHKMAX_Y) return TRUE; + } + if(ly1<0) + { + if((ly0-ly1)>CHKMAX_Y) return TRUE; + if((ly2-ly1)>CHKMAX_Y) return TRUE; + if((ly3-ly1)>CHKMAX_Y) return TRUE; + } + if(ly2<0) + { + if((ly0-ly2)>CHKMAX_Y) return TRUE; + if((ly1-ly2)>CHKMAX_Y) return TRUE; + if((ly3-ly2)>CHKMAX_Y) return TRUE; + } + if(ly3<0) + { + if((ly1-ly3)>CHKMAX_Y) return TRUE; + if((ly2-ly3)>CHKMAX_Y) return TRUE; + } + + return FALSE; +} + +__inline BOOL CheckCoord3() +{ + if(lx0<0) + { + if((lx1-lx0)>CHKMAX_X) return TRUE; + if((lx2-lx0)>CHKMAX_X) return TRUE; + } + if(lx1<0) + { + if((lx0-lx1)>CHKMAX_X) return TRUE; + if((lx2-lx1)>CHKMAX_X) return TRUE; + } + if(lx2<0) + { + if((lx0-lx2)>CHKMAX_X) return TRUE; + if((lx1-lx2)>CHKMAX_X) return TRUE; + } + if(ly0<0) + { + if((ly1-ly0)>CHKMAX_Y) return TRUE; + if((ly2-ly0)>CHKMAX_Y) return TRUE; + } + if(ly1<0) + { + if((ly0-ly1)>CHKMAX_Y) return TRUE; + if((ly2-ly1)>CHKMAX_Y) return TRUE; + } + if(ly2<0) + { + if((ly0-ly2)>CHKMAX_Y) return TRUE; + if((ly1-ly2)>CHKMAX_Y) return TRUE; + } + + return FALSE; +} + + +__inline BOOL CheckCoord2() +{ + if(lx0<0) + { + if((lx1-lx0)>CHKMAX_X) return TRUE; + } + if(lx1<0) + { + if((lx0-lx1)>CHKMAX_X) return TRUE; + } + if(ly0<0) + { + if((ly1-ly0)>CHKMAX_Y) return TRUE; + } + if(ly1<0) + { + if((ly0-ly1)>CHKMAX_Y) return TRUE; + } + + return FALSE; +} + +// Pete's way: a very easy (and hopefully fast) approach for lines +// without sqrt... using a small float -> short cast trick :) + +#define VERTEX_OFFX 0.2f +#define VERTEX_OFFY 0.2f + +BOOL offsetline(void) +{ + short x0,x1,y0,y1,dx,dy;float px,py; + + if(bDisplayNotSet) + SetOGLDisplaySettings(1); + + if(!(dwActFixes&16)) + { + lx0=(short)(((int)lx0<>SIGNSHIFT); + lx1=(short)(((int)lx1<>SIGNSHIFT); + ly0=(short)(((int)ly0<>SIGNSHIFT); + ly1=(short)(((int)ly1<>SIGNSHIFT); + + if(CheckCoord2()) return TRUE; + } + + x0 = (lx0 + PSXDisplay.CumulOffset.x)+1; + x1 = (lx1 + PSXDisplay.CumulOffset.x)+1; + y0 = (ly0 + PSXDisplay.CumulOffset.y)+1; + y1 = (ly1 + PSXDisplay.CumulOffset.y)+1; + + dx=x1-x0; + dy=y1-y0; + + if(dx>=0) + { + if(dy>=0) + { + px=0.5f; + if(dx>dy) py=-0.5f; + else if(dxdy) px= 0.5f; + else if(dx=0) + { + py=0.5f; + dx=-dx; + if(dx>dy) px=-0.5f; + else if(dxdy) py=-0.5f; + else if(dx>SIGNSHIFT); + lx1=(short)(((int)lx1<>SIGNSHIFT); + ly0=(short)(((int)ly0<>SIGNSHIFT); + ly1=(short)(((int)ly1<>SIGNSHIFT); + + if(CheckCoord2()) return TRUE; + } + + vertex[0].x=lx0+PSXDisplay.CumulOffset.x; + vertex[1].x=lx1+PSXDisplay.CumulOffset.x; + vertex[0].y=ly0+PSXDisplay.CumulOffset.y; + vertex[1].y=ly1+PSXDisplay.CumulOffset.y; + + return FALSE; +} + +///////////////////////////////////////////////////////// + +BOOL offset3(void) +{ + if(bDisplayNotSet) + SetOGLDisplaySettings(1); + + if(!(dwActFixes&16)) + { + lx0=(short)(((int)lx0<>SIGNSHIFT); + lx1=(short)(((int)lx1<>SIGNSHIFT); + lx2=(short)(((int)lx2<>SIGNSHIFT); + ly0=(short)(((int)ly0<>SIGNSHIFT); + ly1=(short)(((int)ly1<>SIGNSHIFT); + ly2=(short)(((int)ly2<>SIGNSHIFT); + + if(CheckCoord3()) return TRUE; + } + + vertex[0].x=lx0+PSXDisplay.CumulOffset.x; + vertex[1].x=lx1+PSXDisplay.CumulOffset.x; + vertex[2].x=lx2+PSXDisplay.CumulOffset.x; + vertex[0].y=ly0+PSXDisplay.CumulOffset.y; + vertex[1].y=ly1+PSXDisplay.CumulOffset.y; + vertex[2].y=ly2+PSXDisplay.CumulOffset.y; + + return FALSE; +} + +///////////////////////////////////////////////////////// + +BOOL offset4(void) +{ + if(bDisplayNotSet) + SetOGLDisplaySettings(1); + + if(!(dwActFixes&16)) + { + lx0=(short)(((int)lx0<>SIGNSHIFT); + lx1=(short)(((int)lx1<>SIGNSHIFT); + lx2=(short)(((int)lx2<>SIGNSHIFT); + lx3=(short)(((int)lx3<>SIGNSHIFT); + ly0=(short)(((int)ly0<>SIGNSHIFT); + ly1=(short)(((int)ly1<>SIGNSHIFT); + ly2=(short)(((int)ly2<>SIGNSHIFT); + ly3=(short)(((int)ly3<>SIGNSHIFT); + + if(CheckCoord4()) return TRUE; + } + + vertex[0].x=lx0+PSXDisplay.CumulOffset.x; + vertex[1].x=lx1+PSXDisplay.CumulOffset.x; + vertex[2].x=lx2+PSXDisplay.CumulOffset.x; + vertex[3].x=lx3+PSXDisplay.CumulOffset.x; + vertex[0].y=ly0+PSXDisplay.CumulOffset.y; + vertex[1].y=ly1+PSXDisplay.CumulOffset.y; + vertex[2].y=ly2+PSXDisplay.CumulOffset.y; + vertex[3].y=ly3+PSXDisplay.CumulOffset.y; + + return FALSE; +} + +///////////////////////////////////////////////////////// + +void offsetST(void) +{ + if(bDisplayNotSet) + SetOGLDisplaySettings(1); + + if(!(dwActFixes&16)) + { + lx0=(short)(((int)lx0<>SIGNSHIFT); + ly0=(short)(((int)ly0<>SIGNSHIFT); + + if(lx0<-512 && PSXDisplay.DrawOffset.x<=-512) + lx0+=2048; + + if(ly0<-512 && PSXDisplay.DrawOffset.y<=-512) + ly0+=2048; + } + + ly1 = ly0; + ly2 = ly3 = ly0+sprtH; + lx3 = lx0; + lx1 = lx2 = lx0+sprtW; + + vertex[0].x=lx0+PSXDisplay.CumulOffset.x; + vertex[1].x=lx1+PSXDisplay.CumulOffset.x; + vertex[2].x=lx2+PSXDisplay.CumulOffset.x; + vertex[3].x=lx3+PSXDisplay.CumulOffset.x; + vertex[0].y=ly0+PSXDisplay.CumulOffset.y; + vertex[1].y=ly1+PSXDisplay.CumulOffset.y; + vertex[2].y=ly2+PSXDisplay.CumulOffset.y; + vertex[3].y=ly3+PSXDisplay.CumulOffset.y; +} + +///////////////////////////////////////////////////////// + +void offsetScreenUpload(long Position) +{ + if(bDisplayNotSet) + SetOGLDisplaySettings(1); + + if(Position==-1) + { + long lmdx,lmdy; + + lmdx=xrUploadArea.x0; + lmdy=xrUploadArea.y0; + + lx0-=lmdx; + ly0-=lmdy; + lx1-=lmdx; + ly1-=lmdy; + lx2-=lmdx; + ly2-=lmdy; + lx3-=lmdx; + ly3-=lmdy; + } + else + if(Position) + { + lx0-=PSXDisplay.DisplayPosition.x; + ly0-=PSXDisplay.DisplayPosition.y; + lx1-=PSXDisplay.DisplayPosition.x; + ly1-=PSXDisplay.DisplayPosition.y; + lx2-=PSXDisplay.DisplayPosition.x; + ly2-=PSXDisplay.DisplayPosition.y; + lx3-=PSXDisplay.DisplayPosition.x; + ly3-=PSXDisplay.DisplayPosition.y; + } + else + { + lx0-=PreviousPSXDisplay.DisplayPosition.x; + ly0-=PreviousPSXDisplay.DisplayPosition.y; + lx1-=PreviousPSXDisplay.DisplayPosition.x; + ly1-=PreviousPSXDisplay.DisplayPosition.y; + lx2-=PreviousPSXDisplay.DisplayPosition.x; + ly2-=PreviousPSXDisplay.DisplayPosition.y; + lx3-=PreviousPSXDisplay.DisplayPosition.x; + ly3-=PreviousPSXDisplay.DisplayPosition.y; + } + + vertex[0].x=lx0 + PreviousPSXDisplay.Range.x0; + vertex[1].x=lx1 + PreviousPSXDisplay.Range.x0; + vertex[2].x=lx2 + PreviousPSXDisplay.Range.x0; + vertex[3].x=lx3 + PreviousPSXDisplay.Range.x0; + vertex[0].y=ly0 + PreviousPSXDisplay.Range.y0; + vertex[1].y=ly1 + PreviousPSXDisplay.Range.y0; + vertex[2].y=ly2 + PreviousPSXDisplay.Range.y0; + vertex[3].y=ly3 + PreviousPSXDisplay.Range.y0; + + if(iUseMask) + { + vertex[0].z=vertex[1].z=vertex[2].z=vertex[3].z=gl_z; + gl_z+=0.00004f; + } +} + +///////////////////////////////////////////////////////// + +void offsetBlk(void) +{ + if(bDisplayNotSet) + SetOGLDisplaySettings(1); + + vertex[0].x=lx0-PSXDisplay.GDrawOffset.x + PreviousPSXDisplay.Range.x0; + vertex[1].x=lx1-PSXDisplay.GDrawOffset.x + PreviousPSXDisplay.Range.x0; + vertex[2].x=lx2-PSXDisplay.GDrawOffset.x + PreviousPSXDisplay.Range.x0; + vertex[3].x=lx3-PSXDisplay.GDrawOffset.x + PreviousPSXDisplay.Range.x0; + vertex[0].y=ly0-PSXDisplay.GDrawOffset.y + PreviousPSXDisplay.Range.y0; + vertex[1].y=ly1-PSXDisplay.GDrawOffset.y + PreviousPSXDisplay.Range.y0; + vertex[2].y=ly2-PSXDisplay.GDrawOffset.y + PreviousPSXDisplay.Range.y0; + vertex[3].y=ly3-PSXDisplay.GDrawOffset.y + PreviousPSXDisplay.Range.y0; + + if(iUseMask) + { + vertex[0].z=vertex[1].z=vertex[2].z=vertex[3].z=gl_z; + gl_z+=0.00004f; + } +} + +//////////////////////////////////////////////////////////////////////// +// texture sow/tow calculations +//////////////////////////////////////////////////////////////////////// + +void assignTextureVRAMWrite(void) +{ +#ifdef OWNSCALE + + vertex[0].sow=0.5f/ ST_FACVRAMX; + vertex[0].tow=0.5f/ ST_FACVRAM; + + vertex[1].sow=(float)gl_ux[1]/ ST_FACVRAMX; + vertex[1].tow=0.5f/ ST_FACVRAM; + + vertex[2].sow=(float)gl_ux[2]/ ST_FACVRAMX; + vertex[2].tow=(float)gl_vy[2]/ ST_FACVRAM; + + vertex[3].sow=0.5f/ ST_FACVRAMX; + vertex[3].tow=(float)gl_vy[3]/ ST_FACVRAM; + +#else + + if(gl_ux[1]==255) + { + vertex[0].sow=(gl_ux[0]*255.99f)/255.0f; + vertex[1].sow=(gl_ux[1]*255.99f)/255.0f; + vertex[2].sow=(gl_ux[2]*255.99f)/255.0f; + vertex[3].sow=(gl_ux[3]*255.99f)/255.0f; + } + else + { + vertex[0].sow=gl_ux[0]; + vertex[1].sow=gl_ux[1]; + vertex[2].sow=gl_ux[2]; + vertex[3].sow=gl_ux[3]; + } + + vertex[0].tow=gl_vy[0]; + vertex[1].tow=gl_vy[1]; + vertex[2].tow=gl_vy[2]; + vertex[3].tow=gl_vy[3]; + +#endif +} + +GLuint gLastTex=0; +GLuint gLastFMode=(GLuint)-1; + +///////////////////////////////////////////////////////// + +void assignTextureSprite(void) +{ + if(bUsingTWin) + { + vertex[0].sow=vertex[3].sow=(float)gl_ux[0]/TWin.UScaleFactor; + vertex[1].sow=vertex[2].sow=(float)sSprite_ux2/TWin.UScaleFactor; + vertex[0].tow=vertex[1].tow=(float)gl_vy[0]/TWin.VScaleFactor; + vertex[2].tow=vertex[3].tow=(float)sSprite_vy2/TWin.VScaleFactor; + gLastTex=gTexName; + } + else + { +#ifdef OWNSCALE + + vertex[0].sow=vertex[3].sow=(float)gl_ux[0] / ST_FACSPRITE; + vertex[1].sow=vertex[2].sow=(float)sSprite_ux2 / ST_FACSPRITE; + vertex[0].tow=vertex[1].tow=(float)gl_vy[0] / ST_FACSPRITE; + vertex[2].tow=vertex[3].tow=(float)sSprite_vy2 / ST_FACSPRITE; + +#else + + vertex[0].sow=vertex[3].sow=gl_ux[0]; + vertex[1].sow=vertex[2].sow=sSprite_ux2; + vertex[0].tow=vertex[1].tow=gl_vy[0]; + vertex[2].tow=vertex[3].tow=sSprite_vy2; + +#endif + + if(iFilterType>2) + { + if(gLastTex!=gTexName || gLastFMode!=0) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + gLastTex=gTexName;gLastFMode=0; + } + } + } + + if(usMirror & 0x1000) + { + vertex[0].sow=vertex[1].sow; + vertex[1].sow=vertex[2].sow=vertex[3].sow; + vertex[3].sow=vertex[0].sow; + } + + if(usMirror & 0x2000) + { + vertex[0].tow=vertex[3].tow; + vertex[2].tow=vertex[3].tow=vertex[1].tow; + vertex[1].tow=vertex[0].tow; + } + +} + +///////////////////////////////////////////////////////// + +void assignTexture3(void) +{ + if(bUsingTWin) + { + vertex[0].sow=(float)gl_ux[0]/TWin.UScaleFactor; + vertex[0].tow=(float)gl_vy[0]/TWin.VScaleFactor; + vertex[1].sow=(float)gl_ux[1]/TWin.UScaleFactor; + vertex[1].tow=(float)gl_vy[1]/TWin.VScaleFactor; + vertex[2].sow=(float)gl_ux[2]/TWin.UScaleFactor; + vertex[2].tow=(float)gl_vy[2]/TWin.VScaleFactor; + gLastTex=gTexName; + } + else + { +#ifdef OWNSCALE + vertex[0].sow=(float)gl_ux[0] / ST_FACTRI; + vertex[0].tow=(float)gl_vy[0] / ST_FACTRI; + vertex[1].sow=(float)gl_ux[1] / ST_FACTRI; + + vertex[1].tow=(float)gl_vy[1] / ST_FACTRI; + vertex[2].sow=(float)gl_ux[2] / ST_FACTRI; + vertex[2].tow=(float)gl_vy[2] / ST_FACTRI; +#else + vertex[0].sow=gl_ux[0]; + vertex[0].tow=gl_vy[0]; + vertex[1].sow=gl_ux[1]; + vertex[1].tow=gl_vy[1]; + vertex[2].sow=gl_ux[2]; + vertex[2].tow=gl_vy[2]; +#endif + + if(iFilterType>2) + { + if(gLastTex!=gTexName || gLastFMode!=1) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + gLastTex=gTexName;gLastFMode=1; + } + } + + if(iFilterType) + { + float fxmin=256.0f,fxmax=0.0f,fymin=256.0f,fymax=0.0f;int i; + for(i=0;i<3;i++) + { + if(vertex[i].sowfxmax) fxmax=vertex[i].sow; + if(vertex[i].tow>fymax) fymax=vertex[i].tow; + } + + for(i=0;i<3;i++) + { + if(vertex[i].sow==fxmin) vertex[i].sow+=ST_BFFACSORT; + if(vertex[i].sow==fxmax) vertex[i].sow-=ST_BFFACSORT; + if(vertex[i].tow==fymin) vertex[i].tow+=ST_BFFACSORT; + if(vertex[i].tow==fymax) vertex[i].tow-=ST_BFFACSORT; + } + } + } +} + +///////////////////////////////////////////////////////// + +void assignTexture4(void) +{ + if(bUsingTWin) + { + vertex[0].sow=(float)gl_ux[0]/TWin.UScaleFactor; + vertex[0].tow=(float)gl_vy[0]/TWin.VScaleFactor; + vertex[1].sow=(float)gl_ux[1]/TWin.UScaleFactor; + vertex[1].tow=(float)gl_vy[1]/TWin.VScaleFactor; + vertex[2].sow=(float)gl_ux[2]/TWin.UScaleFactor; + vertex[2].tow=(float)gl_vy[2]/TWin.VScaleFactor; + vertex[3].sow=(float)gl_ux[3]/TWin.UScaleFactor; + vertex[3].tow=(float)gl_vy[3]/TWin.VScaleFactor; + gLastTex=gTexName; + } + else + { +#ifdef OWNSCALE + vertex[0].sow=(float)gl_ux[0] / ST_FAC; + vertex[0].tow=(float)gl_vy[0] / ST_FAC; + vertex[1].sow=(float)gl_ux[1] / ST_FAC; + vertex[1].tow=(float)gl_vy[1] / ST_FAC; + vertex[2].sow=(float)gl_ux[2] / ST_FAC; + vertex[2].tow=(float)gl_vy[2] / ST_FAC; + vertex[3].sow=(float)gl_ux[3] / ST_FAC; + vertex[3].tow=(float)gl_vy[3] / ST_FAC; +#else + vertex[0].sow=gl_ux[0]; + vertex[0].tow=gl_vy[0]; + vertex[1].sow=gl_ux[1]; + vertex[1].tow=gl_vy[1]; + vertex[2].sow=gl_ux[2]; + vertex[2].tow=gl_vy[2]; + vertex[3].sow=gl_ux[3]; + vertex[3].tow=gl_vy[3]; +#endif + + if(iFilterType>2) + { + if(gLastTex!=gTexName || gLastFMode!=1) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + gLastTex=gTexName;gLastFMode=1; + } + } + + if(iFilterType) + { + float fxmin=256.0f,fxmax=0.0f,fymin=256.0f,fymax=0.0f;int i; + for(i=0;i<4;i++) + { + if(vertex[i].sowfxmax) fxmax=vertex[i].sow; + if(vertex[i].tow>fymax) fymax=vertex[i].tow; + } + + for(i=0;i<4;i++) + { + if(vertex[i].sow==fxmin) vertex[i].sow+=ST_BFFACSORT; + if(vertex[i].sow==fxmax) vertex[i].sow-=ST_BFFACSORT; + if(vertex[i].tow==fymin) vertex[i].tow+=ST_BFFACSORT; + if(vertex[i].tow==fymax) vertex[i].tow-=ST_BFFACSORT; + } + } + } +} + +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +// render pos / buffers +//////////////////////////////////////////////////////////////////////// + +#ifndef _WINDOWS +#define EqualRect(pr1,pr2) ((pr1)->left==(pr2)->left && (pr1)->top==(pr2)->top && (pr1)->right==(pr2)->right && (pr1)->bottom==(pr2)->bottom) +#endif + +//////////////////////////////////////////////////////////////////////// +// SetDisplaySettings: "simply" calcs the new drawing area and updates +// the ogl clipping (scissor) + +BOOL bSetClip=FALSE; + +void SetOGLDisplaySettings(BOOL DisplaySet) +{ + static RECT rprev={0,0,0,0}; + static RECT rC ={0,0,0,0}; + static int iOldX=0; + static int iOldY=0; + RECT r;float XS,YS; + + bDisplayNotSet = FALSE; + + //----------------------------------------------------// that's a whole screen upload + if(!DisplaySet) + { + RECT rX; + PSXDisplay.GDrawOffset.x=0; + PSXDisplay.GDrawOffset.y=0; + + PSXDisplay.CumulOffset.x = PSXDisplay.DrawOffset.x+PreviousPSXDisplay.Range.x0; + PSXDisplay.CumulOffset.y = PSXDisplay.DrawOffset.y+PreviousPSXDisplay.Range.y0; + + rprev.left=rprev.left+1; + + rX=rRatioRect; + rX.top=iResY-(rRatioRect.top+rRatioRect.bottom); + + if(bSetClip || !EqualRect(&rC,&rX)) + { + rC=rX; + glScissor(rC.left,rC.top,rC.right,rC.bottom); + bSetClip=FALSE; + } + return; + } + //----------------------------------------------------// + + PSXDisplay.GDrawOffset.y = PreviousPSXDisplay.DisplayPosition.y; + PSXDisplay.GDrawOffset.x = PreviousPSXDisplay.DisplayPosition.x; + PSXDisplay.CumulOffset.x = PSXDisplay.DrawOffset.x - PSXDisplay.GDrawOffset.x+PreviousPSXDisplay.Range.x0; + PSXDisplay.CumulOffset.y = PSXDisplay.DrawOffset.y - PSXDisplay.GDrawOffset.y+PreviousPSXDisplay.Range.y0; + + r.top =PSXDisplay.DrawArea.y0 - PreviousPSXDisplay.DisplayPosition.y; + r.bottom=PSXDisplay.DrawArea.y1 - PreviousPSXDisplay.DisplayPosition.y; + + if(r.bottom<0 || r.top>=PSXDisplay.DisplayMode.y) + { + r.top =PSXDisplay.DrawArea.y0 - PSXDisplay.DisplayPosition.y; + r.bottom=PSXDisplay.DrawArea.y1 - PSXDisplay.DisplayPosition.y; + } + + r.left =PSXDisplay.DrawArea.x0 - PreviousPSXDisplay.DisplayPosition.x; + r.right =PSXDisplay.DrawArea.x1 - PreviousPSXDisplay.DisplayPosition.x; + + if(r.right<0 || r.left>=PSXDisplay.DisplayMode.x) + { + r.left =PSXDisplay.DrawArea.x0 - PSXDisplay.DisplayPosition.x; + r.right =PSXDisplay.DrawArea.x1 - PSXDisplay.DisplayPosition.x; + } + + if(!bSetClip && EqualRect(&r,&rprev) && + iOldX == PSXDisplay.DisplayMode.x && + iOldY == PSXDisplay.DisplayMode.y) + return; + + rprev = r; + iOldX = PSXDisplay.DisplayMode.x; + iOldY = PSXDisplay.DisplayMode.y; + + XS=(float)rRatioRect.right/(float)PSXDisplay.DisplayMode.x; + YS=(float)rRatioRect.bottom/(float)PSXDisplay.DisplayMode.y; + + if(PreviousPSXDisplay.Range.x0) + { + short s=PreviousPSXDisplay.Range.x0+PreviousPSXDisplay.Range.x1; + + r.left+=PreviousPSXDisplay.Range.x0+1; + + r.right+=PreviousPSXDisplay.Range.x0; + + if(r.left>s) r.left=s; + if(r.right>s) r.right=s; + } + + if(PreviousPSXDisplay.Range.y0) + { + short s=PreviousPSXDisplay.Range.y0+PreviousPSXDisplay.Range.y1; + + r.top+=PreviousPSXDisplay.Range.y0+1; + r.bottom+=PreviousPSXDisplay.Range.y0; + + if(r.top>s) r.top=s; + if(r.bottom>s) r.bottom=s; + } + + // Set the ClipArea variables to reflect the new screen, + // offset from zero (since it is a new display buffer) + r.left = (int)(((float)(r.left)) *XS); + r.top = (int)(((float)(r.top)) *YS); + r.right = (int)(((float)(r.right + 1))*XS); + r.bottom = (int)(((float)(r.bottom + 1))*YS); + + // Limit clip area to the screen size + if (r.left > iResX) r.left = iResX; + if (r.left < 0) r.left = 0; + if (r.top > iResY) r.top = iResY; + if (r.top < 0) r.top = 0; + if (r.right > iResX) r.right = iResX; + if (r.right < 0) r.right = 0; + if (r.bottom > iResY) r.bottom = iResY; + if (r.bottom < 0) r.bottom = 0; + + r.right -=r.left; + r.bottom-=r.top; + r.top=iResY-(r.top+r.bottom); + + r.left+=rRatioRect.left; + r.top -=rRatioRect.top; + + if(bSetClip || !EqualRect(&r,&rC)) + { + glScissor(r.left,r.top,r.right,r.bottom); + rC=r; + bSetClip=FALSE; + } +} + +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// + diff --git a/plugins/gpu-gles/gpuDraw.h b/plugins/gpu-gles/gpuDraw.h new file mode 100644 index 00000000..f5f0426a --- /dev/null +++ b/plugins/gpu-gles/gpuDraw.h @@ -0,0 +1,83 @@ +/*************************************************************************** + draw.h - description + ------------------- + begin : Sun Mar 08 2009 + copyright : (C) 1999-2009 by Pete Bernert + web : www.pbernert.com + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2009/03/08 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +#ifndef _GL_DRAW_H_ +#define _GL_DRAW_H_ + + +#ifdef __cplusplus + +extern "C" { +#endif + +#include "minimal.h" +#include + +// internally used defines + +#define GPUCOMMAND(x) ((x>>24) & 0xff) +#define RED(x) (x & 0xff) +#define BLUE(x) ((x>>16) & 0xff) +#define GREEN(x) ((x>>8) & 0xff) +#define COLOR(x) (x & 0xffffff) + +// prototypes + +#ifdef _WINDOWS +BOOL bSetupPixelFormat(HDC hDC); +#endif + +int GLinitialize(); +void GLcleanup(); +#ifdef _WINDOWS +BOOL offset2(void); +BOOL offset3(void); +BOOL offset4(void); +BOOL offsetline(void); +#else +unsigned short offset2(void); +unsigned short offset3(void); +unsigned short offset4(void); +unsigned short offsetline(void); +#endif +void offsetST(void); +void offsetBlk(void); +void offsetScreenUpload(long Position); +void assignTexture3(void); +void assignTexture4(void); +void assignTextureSprite(void); +void assignTextureVRAMWrite(void); +void SetOGLDisplaySettings (unsigned short DisplaySet); +void ReadConfig(void); +void WriteConfig(void); +void SetExtGLFuncs(void); +/////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif // _GL_DRAW_H_ diff --git a/plugins/gpu-gles/gpuExternals.h b/plugins/gpu-gles/gpuExternals.h new file mode 100644 index 00000000..f24c31ad --- /dev/null +++ b/plugins/gpu-gles/gpuExternals.h @@ -0,0 +1,570 @@ +/*************************************************************************** + external.h - description + ------------------- + begin : Sun Mar 08 2009 + copyright : (C) 1999-2009 by Pete Bernert + web : www.pbernert.com + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2009/03/08 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +///////////////////////////////////////////////////////////////////////////// + +#ifndef __GPU_EX__ +#define __GPU_EX__ + +#ifdef __cplusplus +extern "C" { +#endif +#define _GPU_API_ +#ifndef _WINDOWS +#ifdef __NANOGL__ +#include +#include +#else +#ifdef SOFT_LINKAGE +#pragma softfp_linkage +#endif +#include // for opengl es types +#ifdef SOFT_LINKAGE +#pragma no_softfp_linkage +#endif +#endif +#endif + +#ifdef MAEMO_CHANGES + #include "../psxCommon.h" +#else + #include "psxCommon.h" +#endif + +#ifdef __NANOGL__ +#define glTexParameteri(x,y,z) glTexParameterf(x,y,z) +#define glAlphaFuncx(x,y) glAlphaFunc(x,y) +#ifndef APIENTRY +#define APIENTRY +#endif +extern void ( APIENTRY * glPixelStorei )(GLenum pname, GLint param); +#endif + + +#define MIRROR_TEST 1 + +///////////////////////////////////////////////////////////////////////////// + +#define SCISSOR_TEST 1 + +///////////////////////////////////////////////////////////////////////////// + +// for own sow/tow scaling +#define OWNSCALE 1 + +///////////////////////////////////////////////////////////////////////////// + +#define CLUTUSED 0x80000000 +//glColor4ubv(x.c.col) +#define SETCOL(x) if(x.c.lcol!=ulOLDCOL) {ulOLDCOL=x.c.lcol;glColor4ub(x.c.col[0],x.c.col[1],x.c.col[2],x.c.col[3]);} +//#define SETPCOL(x) if(x->c.lcol!=ulOLDCOL) {ulOLDCOL=x->c.lcol;glColor4ub(x->c.col[0],x->c.col[1],x->c.col[2],x->c.col[3]);} + +#define INFO_TW 0 +#define INFO_DRAWSTART 1 +#define INFO_DRAWEND 2 +#define INFO_DRAWOFF 3 + +#define SIGNSHIFT 21 +#define CHKMAX_X 1024 +#define CHKMAX_Y 512 + +///////////////////////////////////////////////////////////////////////////// + +// GPU STATUS REGISTER bit values (c) Lewpy + +#define DR_NORMAL 0 +#define DR_VRAMTRANSFER 1 + +#define GPUSTATUS_ODDLINES 0x80000000 +#define GPUSTATUS_DMABITS 0x60000000 // Two bits +#define GPUSTATUS_READYFORCOMMANDS 0x10000000 +#define GPUSTATUS_READYFORVRAM 0x08000000 +#define GPUSTATUS_IDLE 0x04000000 +#define GPUSTATUS_DISPLAYDISABLED 0x00800000 +#define GPUSTATUS_INTERLACED 0x00400000 +#define GPUSTATUS_RGB24 0x00200000 +#define GPUSTATUS_PAL 0x00100000 +#define GPUSTATUS_DOUBLEHEIGHT 0x00080000 +#define GPUSTATUS_WIDTHBITS 0x00070000 // Three bits +#define GPUSTATUS_MASKENABLED 0x00001000 +#define GPUSTATUS_MASKDRAWN 0x00000800 +#define GPUSTATUS_DRAWINGALLOWED 0x00000400 +#define GPUSTATUS_DITHER 0x00000200 + +#define STATUSREG lGPUstatusRet + +#define GPUIsBusy (STATUSREG &= ~GPUSTATUS_IDLE) +#define GPUIsIdle (STATUSREG |= GPUSTATUS_IDLE) + +#define GPUIsNotReadyForCommands (STATUSREG &= ~GPUSTATUS_READYFORCOMMANDS) +#define GPUIsReadyForCommands (STATUSREG |= GPUSTATUS_READYFORCOMMANDS) + +///////////////////////////////////////////////////////////////////////////// + +#define KEY_RESETTEXSTORE 1 +#define KEY_SHOWFPS 2 +#define KEY_RESETOPAQUE 4 +#define KEY_RESETDITHER 8 +#define KEY_RESETFILTER 16 +#define KEY_RESETADVBLEND 32 +#define KEY_BLACKWHITE 64 +#define KEY_TOGGLEFBTEXTURE 128 +#define KEY_STEPDOWN 256 +#define KEY_TOGGLEFBREAD 512 + +///////////////////////////////////////////////////////////////////////////// +// Linux is missing some stuff, eh? ;) + +#ifndef _WINDOWS +#ifndef FALSE +#define FALSE 0 +#endif +#ifndef TRUE +#define TRUE 1 +#endif +#ifndef BOOL +#define BOOL unsigned short +#endif +#ifndef bool +#define bool unsigned short +#endif +#define LOWORD(l) ((unsigned short)(l)) +#define HIWORD(l) ((unsigned short)(((unsigned long)(l) >> 16) & 0xFFFF)) +#define max(a,b) (((a) > (b)) ? (a) : (b)) +#define min(a,b) (((a) < (b)) ? (a) : (b)) +#define DWORD unsigned long + +typedef struct RECTTAG +{ + int left; + int top; + int right; + int bottom; +}RECT; + +#endif + +///////////////////////////////////////////////////////////////////////////// + +typedef struct VRAMLOADTAG +{ + short x; + short y; + short Width; + short Height; + short RowsRemaining; + short ColsRemaining; + unsigned short *ImagePtr; +} VRAMLoad_t; + +typedef struct PSXPOINTTAG +{ + long x; + long y; +} PSXPoint_t; + +typedef struct PSXSPOINTTAG +{ + short x; + short y; +} PSXSPoint_t; + +typedef struct PSXRECTTAG +{ + short x0; + short x1; + short y0; + short y1; +} PSXRect_t; + +///////////////////////////////////////////////////////////////////////////// + +typedef struct TWINTAG +{ + PSXRect_t Position; + PSXRect_t OPosition; + PSXPoint_t TextureSize; + float UScaleFactor; + float VScaleFactor; +} TWin_t; + +///////////////////////////////////////////////////////////////////////////// + +typedef struct PSXDISPLAYTAG +{ + PSXPoint_t DisplayModeNew; + PSXPoint_t DisplayMode; + PSXPoint_t DisplayPosition; + PSXPoint_t DisplayEnd; + + long Double; + long Height; + long PAL; + long InterlacedNew; + long Interlaced; + long InterlacedTest; + long RGB24New; + long RGB24; + PSXSPoint_t DrawOffset; + PSXRect_t DrawArea; + PSXPoint_t GDrawOffset; + PSXPoint_t CumulOffset; + long Disabled; + PSXRect_t Range; +} PSXDisplay_t; + +///////////////////////////////////////////////////////////////////////////// + +typedef struct OGLVertexTag +{ + GLfloat x; + GLfloat y; + GLfloat z; + + GLfloat sow; + GLfloat tow; + + union +COLTAG + { + u8 col[4]; + unsigned long lcol; + } c; + +} OGLVertex; + +typedef union EXShortTag +{ + u8 c[2]; + unsigned short s; +} EXShort; + +typedef union EXLongTag +{ + u8 c[4]; + unsigned long l; + EXShort s[2]; +} EXLong; + + +///////////////////////////////////////////////////////////////////////////// + +#ifdef _WINDOWS + +extern HINSTANCE hInst; + +#endif + +//-----------------------------------------------------// + +#ifndef _IN_DRAW + +extern int iResX; +extern int iResY; +extern BOOL bKeepRatio; +extern RECT rRatioRect; +extern BOOL bOpaquePass; +extern BOOL bAdvancedBlend; + +//extern PFNGLBLENDEQU glBlendEquationEXTEx; +//extern PFNGLCOLORTABLEEXT glColorTableEXTEx; + +extern u8 gl_ux[8]; +extern u8 gl_vy[8]; +extern OGLVertex vertex[4]; +extern short sprtY,sprtX,sprtH,sprtW; +#ifdef _WINDOWS +extern HWND hWWindow; +#endif +extern BOOL bIsFirstFrame; +extern int iWinSize; +extern int iZBufferDepth; +extern GLbitfield uiBufferBits; +extern int iUseMask; +extern int iSetMask; +extern int iDepthFunc; +extern BOOL bCheckMask; +extern unsigned short sSetMask; +extern unsigned long lSetMask; +extern BOOL bSetClip; +extern GLuint gTexScanName; + +#endif + +//-----------------------------------------------------// + +#ifndef _IN_SOFT + +extern long GlobalTextAddrX,GlobalTextAddrY,GlobalTextTP; +extern long GlobalTextREST,GlobalTextABR,GlobalTextPAGE; +extern short ly0,lx0,ly1,lx1,ly2,lx2,ly3,lx3; +extern short g_m1; +extern short g_m2; +extern short g_m3; +extern short DrawSemiTrans; + +#endif + +//-----------------------------------------------------// + +#ifndef _IN_PRIMDRAW + +extern BOOL bNeedUploadTest; +extern BOOL bNeedUploadAfter; +extern BOOL bTexEnabled; +extern BOOL bBlendEnable; +extern BOOL bDrawDither; +extern int iFilterType; +extern BOOL bFullVRam; +extern BOOL bUseMultiPass; +extern int iOffscreenDrawing; +extern BOOL bOldSmoothShaded; +extern BOOL bUsingTWin; +extern BOOL bUsingMovie; +extern PSXRect_t xrMovieArea; +extern PSXRect_t xrUploadArea; +extern PSXRect_t xrUploadAreaIL; +extern PSXRect_t xrUploadAreaRGB24; +extern GLuint gTexName; +extern BOOL bDrawNonShaded; +extern BOOL bDrawMultiPass; +extern GLubyte ubGloColAlpha; +extern GLubyte ubGloAlpha; +extern short sSprite_ux2; +extern short sSprite_vy2; +extern BOOL bRenderFrontBuffer; +extern unsigned long ulOLDCOL; +extern unsigned long ulClutID; +extern void (*primTableJ[256])(u8 *); +extern void (*primTableSkip[256])(u8 *); +extern unsigned short usMirror; +extern unsigned long dwCfgFixes; +extern unsigned long dwActFixes; +extern unsigned long dwEmuFixes; +extern BOOL bUseFixes; +extern int iSpriteTex; +extern int iDrawnSomething; + +extern long drawX; +extern long drawY; +extern long drawW; +extern long drawH; +extern short sxmin; +extern short sxmax; +extern short symin; +extern short symax; + +#endif + +//-----------------------------------------------------// + +#ifndef _IN_TEXTURE + +extern u8 ubOpaqueDraw; +extern GLint giWantedRGBA; +extern GLint giWantedFMT; +extern GLint giWantedTYPE; +extern void (*LoadSubTexFn) (int,int,short,short); +extern long GlobalTexturePage; +extern unsigned long (*TCF[]) (unsigned long); +extern unsigned short (*PTCF[]) (unsigned short); +extern unsigned long (*PalTexturedColourFn) (unsigned long); +extern BOOL bUseFastMdec; +extern BOOL bUse15bitMdec; +extern int iFrameTexType; +extern int iFrameReadType; +extern int iClampType; +extern int iSortTexCnt; +extern BOOL bFakeFrontBuffer; +extern GLuint gTexFrameName; +extern GLuint gTexBlurName; +extern int iVRamSize; +extern int iTexGarbageCollection; +extern int iFTexA; +extern int iFTexB; +extern BOOL bIgnoreNextTile; + + +#endif + +//-----------------------------------------------------// + +#ifndef _IN_GPU + +extern VRAMLoad_t VRAMWrite; +extern VRAMLoad_t VRAMRead; +extern int iDataWriteMode; +extern int iDataReadMode; +extern int iColDepth; +extern BOOL bChangeRes; +extern BOOL bWindowMode; +extern s8 szDispBuf[]; +extern s8 szGPUKeys[]; +extern PSXDisplay_t PSXDisplay; +extern PSXDisplay_t PreviousPSXDisplay; +//extern unsigned long ulKeybits; +extern TWin_t TWin; +extern BOOL bDisplayNotSet; +extern long lGPUstatusRet; +extern short imageX0,imageX1; +extern short imageY0,imageY1; +extern long lClearOnSwap,lClearOnSwapColor; +extern u8 * psxVub; +extern s8 * psxVsb; +extern unsigned short * psxVuw; +extern signed short * psxVsw; +extern unsigned long * psxVul; +extern signed long * psxVsl; +extern GLfloat gl_z; +extern BOOL bNeedRGB24Update; +extern BOOL bChangeWinMode; +extern GLuint uiScanLine; +extern int iUseScanLines; +extern long lSelectedSlot; +extern int iScanBlend; +extern BOOL bInitCap; +extern int iBlurBuffer; +extern int iLastRGB24; +extern int iRenderFVR; +extern int iNoScreenSaver; +extern unsigned long ulGPUInfoVals[]; +extern BOOL bNeedInterlaceUpdate; +extern BOOL bNeedWriteUpload; +extern BOOL bSkipNextFrame; + + +#ifndef _WINDOWS +extern int bFullScreen; +#endif + +#endif + +//-----------------------------------------------------// + +#ifndef _IN_MENU + +//extern unsigned long dwCoreFlags; +extern GLuint gTexPicName; +//extern PSXPoint_t ptCursorPoint[]; +//extern unsigned short usCursorActive; + +#endif + +//-----------------------------------------------------// + +#ifndef _IN_CFG + +#ifndef _WINDOWS +extern s8 * pConfigFile; +#endif + +#endif + +//-----------------------------------------------------// + +#ifndef _IN_FPS + +extern BOOL bUseFrameLimit; +extern BOOL bUseFrameSkip; +extern float fFrameRate; +extern float fFrameRateHz; +extern int iFrameLimit; +extern float fps_skip; +extern float fps_cur; + +#endif + +//-----------------------------------------------------// + +typedef struct { +u8 r; +u8 g; +u8 b; +u8 a; +} Vec4f; + +/**/ +typedef struct { +float x; +float y; +float z; +} Vec3f; + +typedef struct { +float x; +float y; +} Vec2f; + +/* +typedef struct { +int x; +int y; +int z; +} Vec3f; + +typedef struct { +int x; +int y; +} Vec2f; +/**/ + +typedef struct { + Vec3f xyz; + Vec2f st; +} Vertex; + +typedef struct { + Vec3f xyz; + Vec2f st; + Vec4f rgba; +} Vertex2; + +#ifndef _IN_KEY + +//extern unsigned long ulKeybits; + +#endif + +//-----------------------------------------------------// + +#ifndef _IN_ZN + +extern unsigned long dwGPUVersion; +extern int iGPUHeight; +extern int iGPUHeightMask; +extern int GlobalTextIL; +extern int iTileCheat; + +#endif + +#ifdef __cplusplus +} +#endif + + +#endif + +//-----------------------------------------------------// diff --git a/plugins/gpu-gles/gpuFps.c b/plugins/gpu-gles/gpuFps.c new file mode 100644 index 00000000..1012ecbe --- /dev/null +++ b/plugins/gpu-gles/gpuFps.c @@ -0,0 +1,991 @@ +/*************************************************************************** + fps.c - description + ------------------- + begin : Sun Mar 08 2009 + copyright : (C) 1999-2009 by Pete Bernert + web : www.pbernert.com + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2009/03/08 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +#ifdef _WINDOWS +#include "Stdafx.h" +#include "Externals.h" +#include "plugin.h" +#include "Fps.h" +#include "Prim.h" +#else +#include "gpuStdafx.h" +#include "gpuExternals.h" +//#include "plugins.h" +#include "gpuFps.h" +#include "gpuPrim.h" +#endif + +#define _IN_FPS + +#define CALLBACK + +//////////////////////////////////////////////////////////////////////// +// FPS stuff +//////////////////////////////////////////////////////////////////////// +#ifdef _WINDOWS +LARGE_INTEGER liCPUFrequency; +#endif + +//////////////////////////////////////////////////////////////////////// +// FPS skipping / limit +//////////////////////////////////////////////////////////////////////// + +BOOL bIsPerformanceCounter; +float fFrameRateHz; +DWORD dwFrameRateTicks; +float fFrameRate; +int iFrameLimit; +BOOL bUseFrameLimit; +BOOL bUseFrameSkip; +DWORD dwLaceCnt; + +BOOL bInitCap; +float fps_skip; +float fps_cur; + +#ifdef _WINDOWS + +void FrameCap (void) +{ + static DWORD curticks, lastticks, _ticks_since_last_update; + static DWORD TicksToWait = 0; + static LARGE_INTEGER CurrentTime; + static LARGE_INTEGER LastTime; + static BOOL SkipNextWait = FALSE; + BOOL Waiting = TRUE; + + //--------------------------------------------------------- + // init some static vars... + // bInitCap is TRUE on startup and everytime the user + // is toggling the frame limit + //--------------------------------------------------------- + + if(bInitCap) + { + bInitCap=FALSE; + if (bIsPerformanceCounter) + QueryPerformanceCounter(&LastTime); + lastticks = timeGetTime(); + TicksToWait=0; + return; + } + + //--------------------------------------------------------- + + if(bIsPerformanceCounter) + { + QueryPerformanceCounter(&CurrentTime); + _ticks_since_last_update = CurrentTime.LowPart - LastTime.LowPart; + + //--------------------------------------------------------- + // check if diff > 1/2 sec, if yes: take mm timer value + //--------------------------------------------------------- + + curticks = timeGetTime(); + if(_ticks_since_last_update>(liCPUFrequency.LowPart>>1)) + { + if(curticks < lastticks) + _ticks_since_last_update = dwFrameRateTicks+TicksToWait+1; + else _ticks_since_last_update = (liCPUFrequency.LowPart * (curticks - lastticks))/1000; + } + + //--------------------------------------------------------- + + if ((_ticks_since_last_update > TicksToWait) || + (CurrentTime.LowPart < LastTime.LowPart)) + { + LastTime.HighPart = CurrentTime.HighPart; + LastTime.LowPart = CurrentTime.LowPart; + + lastticks=curticks; + + if((_ticks_since_last_update-TicksToWait) > dwFrameRateTicks) + TicksToWait=0; + else TicksToWait=dwFrameRateTicks-(_ticks_since_last_update-TicksToWait); + } + else + { + while (Waiting) + { + QueryPerformanceCounter(&CurrentTime); + _ticks_since_last_update = CurrentTime.LowPart - LastTime.LowPart; + + //--------------------------------------------------------- + // check if diff > 1/2 sec, if yes: take mm timer value + //--------------------------------------------------------- + curticks = timeGetTime(); + if(_ticks_since_last_update>(liCPUFrequency.LowPart>>1)) + { + if(curticks < lastticks) + _ticks_since_last_update = TicksToWait+1; + else _ticks_since_last_update = (liCPUFrequency.LowPart * (curticks - lastticks))/1000; + } + //--------------------------------------------------------- + + if ((_ticks_since_last_update > TicksToWait) || + (CurrentTime.LowPart < LastTime.LowPart)) + { + Waiting = FALSE; + + lastticks=curticks; + + LastTime.HighPart = CurrentTime.HighPart; + LastTime.LowPart = CurrentTime.LowPart; + TicksToWait = dwFrameRateTicks; + } + } + } + } + else + { + curticks = timeGetTime(); + _ticks_since_last_update = curticks - lastticks; + + if ((_ticks_since_last_update > TicksToWait) || + (curticks < lastticks)) + { + lastticks = curticks; + + if((_ticks_since_last_update-TicksToWait) > dwFrameRateTicks) + TicksToWait=0; + else TicksToWait=dwFrameRateTicks-(_ticks_since_last_update-TicksToWait); + } + else + { + while (Waiting) + { + curticks = timeGetTime(); + _ticks_since_last_update = curticks - lastticks; + if ((_ticks_since_last_update > TicksToWait) || + (curticks < lastticks)) + { + Waiting = FALSE; + lastticks = curticks; + TicksToWait = dwFrameRateTicks; + } + } + } + } +} + +//////////////////////////////////////////////////////////////////////// + +#define MAXSKIP 120 +#define MAXLACE 16 + +void FrameSkip(void) +{ + static int iNumSkips=0,iAdditionalSkip=0; // number of additional frames to skip + static DWORD dwLastLace=0; // helper var for frame limitation + static DWORD curticks, lastticks, _ticks_since_last_update; + static LARGE_INTEGER CurrentTime; + static LARGE_INTEGER LastTime; + + if(!dwLaceCnt) return; // important: if no updatelace happened, we ignore it completely + + if(iNumSkips) // we are in skipping mode? + { + dwLastLace+=dwLaceCnt; // -> calc frame limit helper (number of laces) + bSkipNextFrame = TRUE; // -> we skip next frame + iNumSkips--; // -> ok, one done + } + else // ok, no additional skipping has to be done... + { // we check now, if some limitation is needed, or a new skipping has to get started + DWORD dwWaitTime; + + if(bInitCap || bSkipNextFrame) // first time or we skipped before? + { + if(bUseFrameLimit && !bInitCap) // frame limit wanted and not first time called? + { + DWORD dwT=_ticks_since_last_update; // -> that's the time of the last drawn frame + dwLastLace+=dwLaceCnt; // -> and that's the number of updatelace since the start of the last drawn frame + + if(bIsPerformanceCounter) // -> now we calc the time of the last drawn frame + the time we spent skipping + { + QueryPerformanceCounter(&CurrentTime); + _ticks_since_last_update= dwT+CurrentTime.LowPart - LastTime.LowPart; + } + else + { + curticks = timeGetTime(); + _ticks_since_last_update= dwT+curticks - lastticks; + } + + dwWaitTime=dwLastLace*dwFrameRateTicks; // -> and now we calc the time the real psx would have needed + + if(_ticks_since_last_update we were too fast? + { + if((dwWaitTime-_ticks_since_last_update)> // -> some more security, to prevent + (60*dwFrameRateTicks)) // wrong waiting times + _ticks_since_last_update=dwWaitTime; + + while(_ticks_since_last_update loop until we have reached the real psx time + { // (that's the additional limitation, yup) + if(bIsPerformanceCounter) + { + QueryPerformanceCounter(&CurrentTime); + _ticks_since_last_update = dwT+CurrentTime.LowPart - LastTime.LowPart; + } + else + { + curticks = timeGetTime(); + _ticks_since_last_update = dwT+curticks - lastticks; + } + } + } + else // we were still too slow ?!!? + { + if(iAdditionalSkip well, somewhen we really have to stop skipping on very slow systems + { + iAdditionalSkip++; // -> inc our watchdog var + dwLaceCnt=0; // -> reset lace count + if(bIsPerformanceCounter) // -> ok, start time of the next frame + QueryPerformanceCounter(&LastTime); + lastticks = timeGetTime(); + return; // -> done, we will skip next frame to get more speed + } + } + } + + bInitCap=FALSE; // -> ok, we have inited the frameskip func + iAdditionalSkip=0; // -> init additional skip + bSkipNextFrame=FALSE; // -> we don't skip the next frame + if(bIsPerformanceCounter) // -> we store the start time of the next frame + QueryPerformanceCounter(&LastTime); + lastticks = timeGetTime(); + dwLaceCnt=0; // -> and we start to count the laces + dwLastLace=0; + _ticks_since_last_update=0; + return; // -> done, the next frame will get drawn + } + + bSkipNextFrame=FALSE; // init the frame skip signal to 'no skipping' first + + if(bIsPerformanceCounter) // get the current time (we are now at the end of one drawn frame) + { + QueryPerformanceCounter(&CurrentTime); + _ticks_since_last_update = CurrentTime.LowPart - LastTime.LowPart; + } + else + { + curticks = timeGetTime(); + _ticks_since_last_update = curticks - lastticks; + } + + dwLastLace=dwLaceCnt; // store curr count (frame limitation helper) + dwWaitTime=dwLaceCnt*dwFrameRateTicks; // calc the 'real psx lace time' + + if(_ticks_since_last_update>dwWaitTime) // hey, we needed way too long for that frame... + { + if(bUseFrameLimit) // if limitation, we skip just next frame, + { // and decide after, if we need to do more + iNumSkips=0; + } + else + { + iNumSkips=_ticks_since_last_update/dwWaitTime; // -> calc number of frames to skip to catch up + iNumSkips--; // -> since we already skip next frame, one down + if(iNumSkips>MAXSKIP) iNumSkips=MAXSKIP; // -> well, somewhere we have to draw a line + } + bSkipNextFrame = TRUE; // -> signal for skipping the next frame + } + else // we were faster than real psx? fine :) + if(bUseFrameLimit) // frame limit used? so we wait til the 'real psx time' has been reached + { + if(dwLaceCnt>MAXLACE) // -> security check + _ticks_since_last_update=dwWaitTime; + + while(_ticks_since_last_update(liCPUFrequency.LowPart>>1)) + _ticks_since_last_update = (liCPUFrequency.LowPart * (curticks - lastticks))/1000; + lastticks=curticks; + //--------------------------------------------------// + + if(bUseFrameSkip && !bUseFrameLimit && _ticks_since_last_update) + fps_skip=min(fps_skip,(((float)liCPUFrequency.LowPart) / ((float)_ticks_since_last_update) +1.0f)); + + LastTime.HighPart = CurrentTime.HighPart; + LastTime.LowPart = CurrentTime.LowPart; + } + else + { + curticks = timeGetTime(); + _ticks_since_last_update=curticks-lastticks; + + if(bUseFrameSkip && !bUseFrameLimit && _ticks_since_last_update) + fps_skip=min(fps_skip,((float)1000/(float)_ticks_since_last_update+1.0f)); + + lastticks = curticks; + } + + if(bUseFrameSkip && bUseFrameLimit) + { + fpsskip_tck += _ticks_since_last_update; + + if(++fpsskip_cnt==2) + { + if(bIsPerformanceCounter) + fps_skip = ((float)liCPUFrequency.LowPart) / ((float)fpsskip_tck) *2.0f; + else + fps_skip = (float)2000/(float)fpsskip_tck; + + fps_skip +=6.0f; + + fpsskip_cnt = 0; + fpsskip_tck = 1; + } + } + + fps_tck += _ticks_since_last_update; + + if(++fps_cnt==10) + { + if(bIsPerformanceCounter) + fps_cur = ((float)liCPUFrequency.LowPart) / ((float)fps_tck) *10.0f; + else + fps_cur = (float)10000/(float)fps_tck; + + fps_cnt = 0; + fps_tck = 1; + + if(bUseFrameLimit && fps_cur>fFrameRateHz) // optical adjust ;) avoids flickering fps display + fps_cur=fFrameRateHz; + } +} + +//////////////////////////////////////////////////////////////////////// +// PC FPS skipping / limit +//////////////////////////////////////////////////////////////////////// + +void PCFrameCap(void) +{ + static DWORD curticks, lastticks, _ticks_since_last_update; + static DWORD TicksToWait = 0; + static LARGE_INTEGER CurrentTime; + static LARGE_INTEGER LastTime; + BOOL Waiting = TRUE; + + while (Waiting) + { + if(bIsPerformanceCounter) + { + QueryPerformanceCounter(&CurrentTime); + _ticks_since_last_update = CurrentTime.LowPart - LastTime.LowPart; + + //------------------------------------------------// + curticks = timeGetTime(); + if(_ticks_since_last_update>(liCPUFrequency.LowPart>>1)) + { + if(curticks < lastticks) + _ticks_since_last_update = TicksToWait+1; + else _ticks_since_last_update = (liCPUFrequency.LowPart * (curticks - lastticks))/1000; + } + //------------------------------------------------// + + if ((_ticks_since_last_update > TicksToWait) || + (CurrentTime.LowPart < LastTime.LowPart)) + { + Waiting = FALSE; + + lastticks=curticks; + + LastTime.HighPart = CurrentTime.HighPart; + LastTime.LowPart = CurrentTime.LowPart; + TicksToWait = (liCPUFrequency.LowPart / fFrameRateHz); + } + } + else + { + curticks = timeGetTime(); + _ticks_since_last_update = curticks - lastticks; + if ((_ticks_since_last_update > TicksToWait) || + (curticks < lastticks)) + { + Waiting = FALSE; + lastticks = curticks; + TicksToWait = (1000 / (DWORD)fFrameRateHz); + } + } + } +} + +//////////////////////////////////////////////////////////////////////// + +void PCcalcfps(void) +{ + static DWORD curticks,_ticks_since_last_update,lastticks; + static long fps_cnt = 0; + static float fps_acc = 0; + static LARGE_INTEGER CurrentTime; + static LARGE_INTEGER LastTime; + float CurrentFPS=0; + + if(bIsPerformanceCounter) + { + QueryPerformanceCounter(&CurrentTime); + _ticks_since_last_update=CurrentTime.LowPart-LastTime.LowPart; + + //--------------------------------------------------// + curticks = timeGetTime(); + if(_ticks_since_last_update>(liCPUFrequency.LowPart>>1)) + _ticks_since_last_update = (liCPUFrequency.LowPart * (curticks - lastticks))/1000; + lastticks=curticks; + //--------------------------------------------------// + + if(_ticks_since_last_update) + { + CurrentFPS = ((float)liCPUFrequency.LowPart) / ((float)_ticks_since_last_update); + } + else CurrentFPS = 0; + LastTime.HighPart = CurrentTime.HighPart; + LastTime.LowPart = CurrentTime.LowPart; + } + else + { + curticks = timeGetTime(); + if(_ticks_since_last_update=curticks-lastticks) + CurrentFPS=(float)1000/(float)_ticks_since_last_update; + else CurrentFPS = 0; + lastticks = curticks; + } + + fps_acc += CurrentFPS; + + if(++fps_cnt==10) + { + fps_cur = fps_acc / 10; + fps_acc = 0; + fps_cnt = 0; + } + + fps_skip=CurrentFPS+1.0f; +} + +//////////////////////////////////////////////////////////////////////// + +void SetAutoFrameCap(void) +{ + if(iFrameLimit==1) + { + fFrameRateHz = fFrameRate; + if(bIsPerformanceCounter) + dwFrameRateTicks=(liCPUFrequency.LowPart / fFrameRateHz); + else dwFrameRateTicks=(1000 / (DWORD)fFrameRateHz); + return; + } + + if(dwActFixes&128) + { + if (PSXDisplay.Interlaced) + fFrameRateHz = PSXDisplay.PAL?50.0f:60.0f; + else fFrameRateHz = PSXDisplay.PAL?25.0f:30.0f; + } + else + { + //fFrameRateHz = PSXDisplay.PAL?50.0f:59.94f; + + if(PSXDisplay.PAL) + { + if (STATUSREG&GPUSTATUS_INTERLACED) + fFrameRateHz=33868800.0f/677343.75f; // 50.00238 + else fFrameRateHz=33868800.0f/680595.00f; // 49.76351 + } + else + { + if (STATUSREG&GPUSTATUS_INTERLACED) + fFrameRateHz=33868800.0f/565031.25f; // 59.94146 + else fFrameRateHz=33868800.0f/566107.50f; // 59.82750 + } + + if(bIsPerformanceCounter) + dwFrameRateTicks=(liCPUFrequency.LowPart / fFrameRateHz); + else dwFrameRateTicks=(1000 / (DWORD)fFrameRateHz); + } +} + +//////////////////////////////////////////////////////////////////////// + +void InitFrameCap(void) // inits cpu frequency info (on gpu startup) +{ + if (QueryPerformanceFrequency (&liCPUFrequency)) + bIsPerformanceCounter = TRUE; + else bIsPerformanceCounter = FALSE; +} + +//////////////////////////////////////////////////////////////////////// + +void ReInitFrameCap(void) +{ + BOOL bOldPerformanceCounter=bIsPerformanceCounter; // store curr timer mode + + if(dwActFixes&0x10000) // check game fix... high performance counters are bad on some mb chipsets + bIsPerformanceCounter=FALSE; + else + { + if (QueryPerformanceFrequency (&liCPUFrequency)) + bIsPerformanceCounter = TRUE; + else bIsPerformanceCounter = FALSE; + } + + if(bOldPerformanceCounter!=bIsPerformanceCounter) // changed? + { + bInitCap = TRUE; + SetAutoFrameCap(); + } +} + +//////////////////////////////////////////////////////////////////////// + +void SetFrameRateConfig(void) +{ + if(fFrameRateHz==0) + { + if(iFrameLimit==2) fFrameRateHz=59.94f; // auto framerate? set some init val (no pal/ntsc known yet) + else fFrameRateHz=fFrameRate; // else set user framerate + } + + if(bIsPerformanceCounter) + dwFrameRateTicks=(liCPUFrequency.LowPart / fFrameRateHz); + else dwFrameRateTicks=(1000 / (DWORD)fFrameRateHz); +} + +//////////////////////////////////////////////////////////////////////// + +// LINUX --------------------------------------------- + +#else + +#define TIMEBASE 100000 + +// hehehe... using same func name as with win32 ;) wow, are we genius ;) +unsigned long timeGetTime() +{ + struct timeval tv; + gettimeofday(&tv, 0); // well, maybe there are better ways + return tv.tv_sec * 100000 + tv.tv_usec/10; // to do that in linux, but at least it works +} + +void FrameCap(void) +{ + static unsigned long curticks, lastticks, _ticks_since_last_update; + static unsigned long TicksToWait = 0; + bool Waiting = TRUE; + + { + curticks = timeGetTime(); + _ticks_since_last_update = curticks - lastticks; + + if((_ticks_since_last_update > TicksToWait) || + (curticks dwFrameRateTicks) + TicksToWait=0; + else TicksToWait=dwFrameRateTicks-(_ticks_since_last_update-TicksToWait); + } + else + { + while (Waiting) + { + curticks = timeGetTime(); + _ticks_since_last_update = curticks - lastticks; + if ((_ticks_since_last_update > TicksToWait) || + (curticks < lastticks)) + { + Waiting = FALSE; + lastticks = curticks; + TicksToWait = dwFrameRateTicks; + } + } + } + } +} + +//////////////////////////////////////////////////////////////////////// + +#define MAXSKIP 120 +#define MAXLACE 16 + +void FrameSkip(void) +{ + static int iNumSkips=0,iAdditionalSkip=0; // number of additional frames to skip + static DWORD dwLastLace=0; // helper var for frame limitation + static DWORD curticks, lastticks, _ticks_since_last_update; + + if(!dwLaceCnt) return; // important: if no updatelace happened, we ignore it completely + + if(iNumSkips) // we are in skipping mode? + { + dwLastLace+=dwLaceCnt; // -> calc frame limit helper (number of laces) + bSkipNextFrame = TRUE; // -> we skip next frame + iNumSkips--; // -> ok, one done + } + else // ok, no additional skipping has to be done... + { // we check now, if some limitation is needed, or a new skipping has to get started + DWORD dwWaitTime; + + if(bInitCap || bSkipNextFrame) // first time or we skipped before? + { + if(bUseFrameLimit && !bInitCap) // frame limit wanted and not first time called? + { + DWORD dwT=_ticks_since_last_update; // -> that's the time of the last drawn frame + dwLastLace+=dwLaceCnt; // -> and that's the number of updatelace since the start of the last drawn frame + + curticks = timeGetTime(); + _ticks_since_last_update= dwT+curticks - lastticks; + + dwWaitTime=dwLastLace*dwFrameRateTicks; // -> and now we calc the time the real psx would have needed + + if(_ticks_since_last_update we were too fast? + { + if((dwWaitTime-_ticks_since_last_update)> // -> some more security, to prevent + (60*dwFrameRateTicks)) // wrong waiting times + _ticks_since_last_update=dwWaitTime; + + while(_ticks_since_last_update loop until we have reached the real psx time + { // (that's the additional limitation, yup) + curticks = timeGetTime(); + _ticks_since_last_update = dwT+curticks - lastticks; + } + } + else // we were still too slow ?!!? + { + if(iAdditionalSkip well, somewhen we really have to stop skipping on very slow systems + { + iAdditionalSkip++; // -> inc our watchdog var + dwLaceCnt=0; // -> reset lace count + lastticks = timeGetTime(); + return; // -> done, we will skip next frame to get more speed + } + } + } + + bInitCap=FALSE; // -> ok, we have inited the frameskip func + iAdditionalSkip=0; // -> init additional skip + bSkipNextFrame=FALSE; // -> we don't skip the next frame + lastticks = timeGetTime(); + dwLaceCnt=0; // -> and we start to count the laces + dwLastLace=0; + _ticks_since_last_update=0; + return; // -> done, the next frame will get drawn + } + + bSkipNextFrame=FALSE; // init the frame skip signal to 'no skipping' first + + curticks = timeGetTime(); + _ticks_since_last_update = curticks - lastticks; + + dwLastLace=dwLaceCnt; // store curr count (frame limitation helper) + dwWaitTime=dwLaceCnt*dwFrameRateTicks; // calc the 'real psx lace time' + + if(_ticks_since_last_update>dwWaitTime) // hey, we needed way too long for that frame... + { + if(bUseFrameLimit) // if limitation, we skip just next frame, + { // and decide after, if we need to do more + iNumSkips=0; + } + else + { + iNumSkips=_ticks_since_last_update/dwWaitTime; // -> calc number of frames to skip to catch up + iNumSkips--; // -> since we already skip next frame, one down + if(iNumSkips>MAXSKIP) iNumSkips=MAXSKIP; // -> well, somewhere we have to draw a line + } + bSkipNextFrame = TRUE; // -> signal for skipping the next frame + } + else // we were faster than real psx? fine :) + if(bUseFrameLimit) // frame limit used? so we wait til the 'real psx time' has been reached + { + if(dwLaceCnt>MAXLACE) // -> security check + _ticks_since_last_update=dwWaitTime; + + while(_ticks_since_last_updatefFrameRateHz) // optical adjust ;) avoids flickering fps display + fps_cur=fFrameRateHz; + } +} + +void PCFrameCap (void) +{ + static unsigned long curticks, lastticks, _ticks_since_last_update; + static unsigned long TicksToWait = 0; + bool Waiting = TRUE; + + while (Waiting) + { + curticks = timeGetTime(); + _ticks_since_last_update = curticks - lastticks; + if ((_ticks_since_last_update > TicksToWait) || + (curticks < lastticks)) + { + Waiting = FALSE; + lastticks = curticks; + TicksToWait = (TIMEBASE / (unsigned long)fFrameRateHz); + } + } +} + +//////////////////////////////////////////////////////////////////////// + +void PCcalcfps(void) +{ + static unsigned long curticks,_ticks_since_last_update,lastticks; + static long fps_cnt = 0; + static float fps_acc = 0; + float CurrentFPS=0; + + curticks = timeGetTime(); + _ticks_since_last_update=curticks-lastticks; + if(_ticks_since_last_update) + CurrentFPS=(float)TIMEBASE/(float)_ticks_since_last_update; + else CurrentFPS = 0; + lastticks = curticks; + + fps_acc += CurrentFPS; + + if(++fps_cnt==10) + { + fps_cur = fps_acc / 10; + fps_acc = 0; + fps_cnt = 0; + } + + fps_skip=CurrentFPS+1.0f; +} + +//////////////////////////////////////////////////////////////////////// + +void SetAutoFrameCap(void) +{ + if(iFrameLimit==1) + { + fFrameRateHz = fFrameRate; + dwFrameRateTicks=(TIMEBASE / (unsigned long)fFrameRateHz); + return; + } + + if(dwActFixes&128) + { + if (PSXDisplay.Interlaced) + fFrameRateHz = PSXDisplay.PAL?50.0f:60.0f; + else fFrameRateHz = PSXDisplay.PAL?25.0f:30.0f; + } + else + { + //fFrameRateHz = PSXDisplay.PAL?50.0f:59.94f; + + if(PSXDisplay.PAL) + { + if (STATUSREG&GPUSTATUS_INTERLACED) + fFrameRateHz=33868800.0f/677343.75f; // 50.00238 + else fFrameRateHz=33868800.0f/680595.00f; // 49.76351 + } + else + { + if (STATUSREG&GPUSTATUS_INTERLACED) + fFrameRateHz=33868800.0f/565031.25f; // 59.94146 + else fFrameRateHz=33868800.0f/566107.50f; // 59.82750 + } + + dwFrameRateTicks=(TIMEBASE / (unsigned long)fFrameRateHz); + } +} + +//////////////////////////////////////////////////////////////////////// + +void SetFrameRateConfig(void) +{ + if(!fFrameRate) fFrameRate=200.0f; + + if(fFrameRateHz==0) + { + if(iFrameLimit==2) fFrameRateHz=59.94f; // auto framerate? set some init val (no pal/ntsc known yet) + else fFrameRateHz=fFrameRate; // else set user framerate + } + + dwFrameRateTicks=(TIMEBASE / (unsigned long)fFrameRateHz); + + if(iFrameLimit==2) SetAutoFrameCap(); +} + +//////////////////////////////////////////////////////////////////////// + +void InitFrameCap(void) +{ + // nothing on linux +} + +void ReInitFrameCap(void) +{ + // nothing on linux +} + +//////////////////////////////////////////////////////////////////////// + +#endif + +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// + +void CheckFrameRate(void) // called in updatelace (on every emulated psx vsync) +{ + if(bUseFrameSkip) + { + if(!(dwActFixes&0x100)) + { + dwLaceCnt++; // -> and store cnt of vsync between frames + if(dwLaceCnt>=MAXLACE && bUseFrameLimit) + { + if(dwLaceCnt==MAXLACE) bInitCap=TRUE; + FrameCap(); + } + } + else if(bUseFrameLimit) FrameCap(); + calcfps(); // -> calc fps display in skipping mode + } + else // -> non-skipping mode: + { + if(bUseFrameLimit) FrameCap(); + calcfps(); + } +} + +//////////////////////////////////////////////////////////////////////// + +void CALLBACK GPUsetframelimit(unsigned long option) // new EPSXE interface func: main emu can enable/disable fps limitation this way +{ + bInitCap = TRUE; + + if(option==1) // emu says: limit + { + bUseFrameLimit=TRUE;bUseFrameSkip=FALSE;iFrameLimit=2; + SetAutoFrameCap(); + } + else // emu says: no limit + { + bUseFrameLimit=FALSE; + } +} + +//////////////////////////////////////////////////////////////////////// diff --git a/plugins/gpu-gles/gpuFps.h b/plugins/gpu-gles/gpuFps.h new file mode 100644 index 00000000..a44a05fc --- /dev/null +++ b/plugins/gpu-gles/gpuFps.h @@ -0,0 +1,66 @@ +#ifndef __GPU_FPS__ +#define __GPU_FPS__ + +#ifdef __cplusplus +extern "C" { +#endif + +/*************************************************************************** + fps.h - description + ------------------- + begin : Sun Mar 08 2009 + copyright : (C) 1999-2009 by Pete Bernert + web : www.pbernert.com + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2009/03/08 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + + +extern BOOL bIsPerformanceCounter; +extern float fFrameRateHz; +extern DWORD dwFrameRateTicks; +extern float fFrameRate; +extern int iFrameLimit; +extern BOOL bUseFrameLimit; +extern BOOL bUseFrameSkip; +extern DWORD dwLaceCnt; + +extern BOOL bInitCap; +extern float fps_skip; +extern float fps_cur; + + +void InitFrameCap(void); +void SetFrameRateConfig(void); +void PCFrameCap(void); +void PCcalcfps(void); +void FrameSkip(void); +void CheckFrameRate(void); +void ReInitFrameCap(void); +void SetAutoFrameCap(void); +#ifndef _WINDOWS +unsigned long timeGetTime(); +#endif + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/plugins/gpu-gles/gpuPlugin.c b/plugins/gpu-gles/gpuPlugin.c new file mode 100644 index 00000000..07f158c3 --- /dev/null +++ b/plugins/gpu-gles/gpuPlugin.c @@ -0,0 +1,2960 @@ +/*************************************************************************** + gpu.c - description + ------------------- + begin : Sun Mar 08 2009 + copyright : (C) 1999-2009 by Pete Bernert + email : BlackDove@addcom.de + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2009/03/08 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +//#include "gpuStdafx.h" + +//#include + +#define _IN_GPU + +#ifdef _WINDOWS +#include "stdafx.h" +#include +#include +#include +#include +#include + +#include "externals.h" +#include "gpu.h" +#include "draw.h" +#include "prim.h" +#include "texture.h" +#include "fps.h" +#include "resource.h" +#else +#include +#include +#include +#include +#include "gpuExternals.h" +#include "gpuPlugin.h" +#include "gpuDraw.h" +#include "gpuTexture.h" +#include "gpuFps.h" +#include "gpuPrim.h" + +//#include "NoPic.h" + +#include "gpuStdafx.h" +#endif + +extern void ProcessEvents(); + +short g_m1=255,g_m2=255,g_m3=255; +short DrawSemiTrans=FALSE; +short Ymin; +short Ymax; + +short ly0,lx0,ly1,lx1,ly2,lx2,ly3,lx3; // global psx vertex coords +long GlobalTextAddrX,GlobalTextAddrY,GlobalTextTP; +long GlobalTextREST,GlobalTextABR,GlobalTextPAGE; + +unsigned long dwGPUVersion=0; +int iGPUHeight=512; +int iGPUHeightMask=511; +int GlobalTextIL=0; +int iTileCheat=0; + +//////////////////////////////////////////////////////////////////////// +// memory image of the PSX vram +//////////////////////////////////////////////////////////////////////// + +u8 *psxVSecure; +u8 *psxVub; +signed char *psxVsb; +unsigned short *psxVuw; +unsigned short *psxVuw_eom; +signed short *psxVsw; +unsigned long *psxVul; +signed long *psxVsl; + +// macro for easy access to packet information +#define GPUCOMMAND(x) ((x>>24) & 0xff) + +GLfloat gl_z=0.0f; +BOOL bNeedInterlaceUpdate=FALSE; +BOOL bNeedRGB24Update=FALSE; +BOOL bChangeWinMode=FALSE; + +#ifdef _WINDOWS +extern HGLRC GLCONTEXT; +#endif + +unsigned long ulStatusControl[256]; + +//////////////////////////////////////////////////////////////////////// +// global GPU vars +//////////////////////////////////////////////////////////////////////// + +static long GPUdataRet; +long lGPUstatusRet; +s8 szDispBuf[64]; + +static unsigned long gpuDataM[256]; +static u8 gpuCommand = 0; +static long gpuDataC = 0; +static long gpuDataP = 0; + +VRAMLoad_t VRAMWrite; +VRAMLoad_t VRAMRead; +int iDataWriteMode; +int iDataReadMode; + +long lClearOnSwap; +long lClearOnSwapColor; +BOOL bSkipNextFrame = FALSE; +int iColDepth; +BOOL bChangeRes; +BOOL bWindowMode; +int iWinSize; + +// possible psx display widths +short dispWidths[8] = {256,320,512,640,368,384,512,640}; + +PSXDisplay_t PSXDisplay; +PSXDisplay_t PreviousPSXDisplay; +TWin_t TWin; +short imageX0,imageX1; +short imageY0,imageY1; +BOOL bDisplayNotSet = TRUE; +GLuint uiScanLine=0; +int iUseScanLines=0; +long lSelectedSlot=0; +u8 * pGfxCardScreen=0; +int iBlurBuffer=0; +int iScanBlend=0; +int iRenderFVR=0; +int iNoScreenSaver=0; +unsigned long ulGPUInfoVals[16]; +int iFakePrimBusy = 0; +int iRumbleVal = 0; +int iRumbleTime = 0; + +//////////////////////////////////////////////////////////////////////// +// stuff to make this a true PDK module +//////////////////////////////////////////////////////////////////////// + +#ifdef _WINDOWS +s8 * CALLBACK PSEgetLibName(void) +{ + return "name"; +} + +unsigned long CALLBACK PSEgetLibType(void) +{ + return 1; +} + +unsigned long CALLBACK PSEgetLibVersion(void) +{ + return 1<<16|1<<8|1; +} +#endif + +//////////////////////////////////////////////////////////////////////// +// snapshot funcs (saves screen to bitmap / text infos into file) +//////////////////////////////////////////////////////////////////////// + +void ResizeWindow() +{ + rRatioRect.left = rRatioRect.top=0; + rRatioRect.right = iResX; + rRatioRect.bottom = iResY; + glViewport(rRatioRect.left, // init viewport by ratio rect + iResY-(rRatioRect.top+rRatioRect.bottom), + rRatioRect.right, + rRatioRect.bottom); + + glScissor(0, 0, iResX, iResY); // init clipping (fullscreen) + glEnable(GL_SCISSOR_TEST); + +#ifndef OWNSCALE + glMatrixMode(GL_TEXTURE); // init psx tex sow and tow if not "ownscale" + glLoadIdentity(); + glScalef(1.0f/255.99f,1.0f/255.99f,1.0f); // geforce precision hack +#endif + + glMatrixMode(GL_PROJECTION); // init projection with psx resolution + glLoadIdentity(); + glOrtho(0,PSXDisplay.DisplayMode.x, + PSXDisplay.DisplayMode.y, 0, -1, 1); + if (bKeepRatio) + SetAspectRatio(); +} + +s8 * GetConfigInfos(int hW) +{ +#ifdef _WINDOWS + HDC hdc;HGLRC hglrc; +#endif + s8 szO[2][4]={"off","on "}; + s8 szTxt[256]; + s8 * pB=(s8 *)malloc(32767); +/* + if(!pB) return NULL; + *pB=0; + //----------------------------------------------------// + strcat(pB,szTxt); + strcat(pB,szTxt); +#ifdef _WINDOWS + if(hW) + { + hdc = GetDC(hW); + bSetupPixelFormat(hdc); + hglrc = wglCreateContext(hdc); + wglMakeCurrent(hdc, hglrc); + } +#endif + sprintf(szTxt,"Card vendor: %s\r\n",(char *)glGetString(GL_VENDOR)); + strcat(pB,szTxt); + sprintf(szTxt,"GFX card: %s\r\n",(char *)glGetString(GL_RENDERER)); + strcat(pB,szTxt); + sprintf(szTxt,"OGL version: %s\r\n\r\n",(char *)glGetString(GL_VERSION)); + strcat(pB,szTxt); + //strcat(pB,(s8 *)glGetString(GL_EXTENSIONS)); + //strcat(pB,"\r\n\r\n"); + +#ifdef _WINDOWS + if(hW) + { + wglMakeCurrent(NULL, NULL); + wglDeleteContext(hglrc); + ReleaseDC(hW,hdc); + } + //----------------------------------------------------// +#endif + if(hW && bWindowMode) + sprintf(szTxt,"Resolution/Color:\r\n- %dx%d ",LOWORD(iWinSize),HIWORD(iWinSize)); + else + sprintf(szTxt,"Resolution/Color:\r\n- %dx%d ",iResX,iResY); + strcat(pB,szTxt); + if(bWindowMode) sprintf(szTxt,"Window mode\r\n"); + else + { + sprintf(szTxt,"Fullscreen "); + strcat(pB,szTxt); + if(bChangeRes) sprintf(szTxt,"- Desktop changing [%d Bit]\r\n",iColDepth); + else sprintf(szTxt,"- NO desktop changing\r\n"); + } + strcat(pB,szTxt); + +// if(iForceVSync>=0) sprintf(szTxt,"- V-Sync: %s\r\n",szO[iForceVSync]); +// else strcpy(szTxt,"- V-Sync: Driver\r\n"); + strcat(pB,szTxt); + sprintf(szTxt,"- Keep psx aspect ratio: %s\r\n\r\n",szO[bKeepRatio]); + strcat(pB,szTxt); + //----------------------------------------------------// + strcpy(szTxt,"Textures:\r\n- "); +/*! if(iTexQuality==0) strcat(szTxt,"Default"); + else if(iTexQuality==1) strcat(szTxt,"R4G4B4A4"); + else if(iTexQuality==2) strcat(szTxt,"R5G5B5A1"); + else if(iTexQuality==3) strcat(szTxt,"R8G8A8A8"); + else if(iTexQuality==4) strcat(szTxt,"B8G8R8A8"); + if(!hW && bGLExt) strcat(szTxt," (packed pixels)\r\n"); + else strcat(szTxt,"\r\n"); + strcat(pB,szTxt); + if(!hW) + { + sprintf(szTxt,"- Filtering: %d - edge clamping ",iFilterType); + if(iClampType==GL_TO_EDGE_CLAMP) strcat(szTxt,"supported\r\n"); + else strcat(szTxt,"NOT supported\r\n"); + } + else sprintf(szTxt,"- iFiltering: %d\r\n",iFilterType); + strcat(pB,szTxt); + sprintf(szTxt,"- Hi-Res textures: %d\r\n",iHiResTextures); + strcat(pB,szTxt); + if(!hW) + { + sprintf(szTxt,"- Palettized tex windows: %s\r\n",szO[iUsePalTextures]); + strcat(pB,szTxt); + } + !*/ + /*sprintf(szTxt,"- VRam size: %d MBytes",iVRamSize); + if(!hW) + sprintf(szTxt+strlen(szTxt)," - %d textures usable\r\n\r\n",iSortTexCnt); + else strcat(szTxt,"\r\n\r\n"); + strcat(pB,szTxt); + //----------------------------------------------------// + sprintf(szTxt,"Framerate:\r\n- FPS limitation: %s\r\n",szO[bUseFrameLimit]); + strcat(pB,szTxt); + sprintf(szTxt,"- Frame skipping: %s\r\n",szO[bUseFrameSkip]); + strcat(pB,szTxt); + if(iFrameLimit==2) + strcpy(szTxt,"- FPS limit: Auto\r\n\r\n"); + else sprintf(szTxt,"- FPS limit: %.1f\r\n\r\n",fFrameRate); + strcat(pB,szTxt); + //----------------------------------------------------// + sprintf(szTxt,"Compatibility:\r\n- Offscreen drawing: %d\r\n",iOffscreenDrawing); + strcat(pB,szTxt); + sprintf(szTxt,"- Framebuffer texture: %d",iFrameTexType); + if(!hW && iFrameTexType==2) + { + if(gTexFrameName) strcat(szTxt," - texture created\r\n"); + else strcat(szTxt," - not used yet\r\n"); + } + else strcat(szTxt,"\r\n"); + strcat(pB,szTxt); + sprintf(szTxt,"- Framebuffer access: %d\r\n",iFrameReadType); + strcat(pB,szTxt); +// sprintf(szTxt,"- Alpha multipass: %s\r\n",szO[bOpaquePass]); + strcat(pB,szTxt); + sprintf(szTxt,"- Mask bit: %s\r\n",szO[iUseMask]); + strcat(pB,szTxt); + //sprintf(szTxt,"- Advanced blending: %s",szO[bAdvancedBlend]); + //if(!hW && bAdvancedBlend) +// { +// if(bGLBlend) strcat(szTxt," (hardware)\r\n"); +// else strcat(szTxt," (software)\r\n"); +// } + strcat(szTxt,"\r\n"); + strcat(pB,szTxt); + + if(!hW) + { + strcpy(szTxt,"- Subtractive blending: "); +// if(glBlendEquationEXTEx) +// { +// if(bUseMultiPass) strcat(szTxt,"supported, but not used!"); +// else strcat(szTxt,"activated"); +// } + strcat(szTxt," NOT supported!"); + strcat(szTxt,"\r\n\r\n"); + } + else strcpy(szTxt,"\r\n"); + + strcat(pB,szTxt); + //----------------------------------------------------// + sprintf(szTxt,"Misc:\r\n- Scanlines: %s",szO[iUseScanLines]); + strcat(pB,szTxt); + if(iUseScanLines) sprintf(szTxt," [%d]\r\n",iScanBlend); + else strcpy(szTxt,"\r\n"); + strcat(pB,szTxt); +// sprintf(szTxt,"- Line mode: %s\r\n",szO[bUseLines]); + strcat(pB,szTxt); +// sprintf(szTxt,"- Line AA: %s\r\n",szO[bUseAntiAlias]); +// fwrite(szTxt,lstrlen(szTxt),1,txtfile); + sprintf(szTxt,"- Unfiltered FB: %s\r\n",szO[bUseFastMdec]); + strcat(pB,szTxt); + sprintf(szTxt,"- 15 bit FB: %s\r\n",szO[bUse15bitMdec]); + strcat(pB,szTxt); + sprintf(szTxt,"- Dithering: %s\r\n",szO[bDrawDither]); + strcat(pB,szTxt); + sprintf(szTxt,"- Screen smoothing: %s",szO[iBlurBuffer]); + strcat(pB,szTxt); + if(!hW && iBlurBuffer) + { + if(gTexBlurName) strcat(pB," - supported\r\n"); + else strcat(pB," - not supported\r\n"); + } + else strcat(pB,"\r\n"); + sprintf(szTxt,"- Game fixes: %s [%08lx]\r\n",szO[bUseFixes],dwCfgFixes); + strcat(pB,szTxt); + //----------------------------------------------------// +*/ return pB; +} + +//////////////////////////////////////////////////////////////////////// +// save text infos to file +//////////////////////////////////////////////////////////////////////// + +void DoTextSnapShot(int iNum) +{ +} + +//////////////////////////////////////////////////////////////////////// +// saves screen bitmap to file +//////////////////////////////////////////////////////////////////////// + +void DoSnapShot(void) +{ +} + +#ifdef _WINDOWS +void CALLBACK GPUmakeSnapshot(void) +#else +void CALLBACK GPU_makeSnapshot(void) +#endif +{ + //bSnapShot = TRUE; +} + +//////////////////////////////////////////////////////////////////////// +// GPU INIT... here starts it all (first func called by emu) +//////////////////////////////////////////////////////////////////////// + +#ifdef _WINDOWS +long CALLBACK GPUinit() +#else +long CALLBACK GPU_init() +#endif +{ +memset(ulStatusControl,0,256*sizeof(unsigned long)); + +#ifdef _WINDOWS +iResX=240;iResY=320; +#endif +bChangeRes=FALSE; +#ifdef _WINDOWS +bWindowMode=TRUE; +#else +bWindowMode=FALSE; +#endif +#ifdef _WINDOWS +iWinSize=MAKELONG(iResX,iResY); +#endif + +bKeepRatio = TRUE; +// different ways of accessing PSX VRAM + +psxVSecure=(u8 *)malloc((iGPUHeight*2)*1024 + (1024*1024)); // always alloc one extra MB for soft drawing funcs security +if(!psxVSecure) return -1; + +psxVub=psxVSecure+512*1024; // security offset into double sized psx vram! +psxVsb=(signed char *)psxVub; +psxVsw=(signed short *)psxVub; +psxVsl=(signed long *)psxVub; +psxVuw=(unsigned short *)psxVub; +psxVul=(unsigned long *)psxVub; + +psxVuw_eom=psxVuw+1024*iGPUHeight; // pre-calc of end of vram + +memset(psxVSecure,0x00,(iGPUHeight*2)*1024 + (1024*1024)); +memset(ulGPUInfoVals,0x00,16*sizeof(unsigned long)); + +InitFrameCap(); // init frame rate stuff + +PSXDisplay.RGB24 = 0; // init vars +PreviousPSXDisplay.RGB24= 0; +PSXDisplay.Interlaced = 0; +PSXDisplay.InterlacedTest=0; +PSXDisplay.DrawOffset.x = 0; +PSXDisplay.DrawOffset.y = 0; +PSXDisplay.DrawArea.x0 = 0; +PSXDisplay.DrawArea.y0 = 0; +PSXDisplay.DrawArea.x1 = 320; +PSXDisplay.DrawArea.y1 = 240; +PSXDisplay.DisplayMode.x= 320; +PSXDisplay.DisplayMode.y= 240; +PSXDisplay.Disabled = FALSE; +PreviousPSXDisplay.Range.x0 =0; +PreviousPSXDisplay.Range.x1 =0; +PreviousPSXDisplay.Range.y0 =0; +PreviousPSXDisplay.Range.y1 =0; +PSXDisplay.Range.x0=0; +PSXDisplay.Range.x1=0; +PSXDisplay.Range.y0=0; +PSXDisplay.Range.y1=0; +PreviousPSXDisplay.DisplayPosition.x = 1; +PreviousPSXDisplay.DisplayPosition.y = 1; +PSXDisplay.DisplayPosition.x = 1; +PSXDisplay.DisplayPosition.y = 1; +PreviousPSXDisplay.DisplayModeNew.y=0; +PSXDisplay.Double=1; +GPUdataRet=0x400; + +PSXDisplay.DisplayModeNew.x=0; +PSXDisplay.DisplayModeNew.y=0; + +//PreviousPSXDisplay.Height = PSXDisplay.Height = 239; + +iDataWriteMode = DR_NORMAL; + +// Reset transfer values, to prevent mis-transfer of data +memset(&VRAMWrite,0,sizeof(VRAMLoad_t)); +memset(&VRAMRead,0,sizeof(VRAMLoad_t)); + +// device initialised already ! +//lGPUstatusRet = 0x74000000; + +STATUSREG = 0x14802000; +GPUIsIdle; +GPUIsReadyForCommands; + +return 0; +} + + +//////////////////////////////////////////////////////////////////////// +// GPU OPEN: funcs to open up the gpu display (Windows) +//////////////////////////////////////////////////////////////////////// + +#ifdef _WINDOWS + +void ChangeDesktop() // change destop resolution +{ + DEVMODE dv;long lRes,iTry=0; + + while(iTry<10) // keep on hammering... + { + memset(&dv,0,sizeof(DEVMODE)); + dv.dmSize=sizeof(DEVMODE); + dv.dmBitsPerPel=iColDepth; + dv.dmPelsWidth=iResX; + dv.dmPelsHeight=iResY; + + dv.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT; + + lRes=ChangeDisplaySettings(&dv,0); // ...hammering the anvil + + if(lRes==DISP_CHANGE_SUCCESSFUL) return; + iTry++;Sleep(10); + } +} + +//////////////////////////////////////////////////////////////////////// +// OPEN interface func: attention! +// some emus are calling this func in their main Window thread, +// but all other interface funcs (to draw stuff) in a different thread! +// that's a problem, since OGL is thread safe! Therefore we cannot +// initialize the OGL stuff right here, we simply set a "bIsFirstFrame = TRUE" +// flag, to initialize OGL on the first real draw call. +// btw, we also call this open func ourselfes, each time when the user +// is changing between fullscreen/window mode (ENTER key) +// btw part 2: in windows the plugin gets the window handle from the +// main emu, and doesn't create it's own window (if it would do it, +// some PAD or SPU plugins would not work anymore) +//////////////////////////////////////////////////////////////////////// + +HMENU hPSEMenu=NULL; + +long CALLBACK GPUopen(HWND hwndGPU) +#else +long CALLBACK GPU_open(int hwndGPU) +#endif +{ + #ifdef _WINDOWS + HDC hdc;RECT r;DEVMODE dv; + + hWWindow = hwndGPU; // store hwnd globally + #endif + // InitKeyHandler(); // init key handler (subclass window) + + + + + + #ifdef _WINDOWS + iResX=240;iResY=320; + #endif + iColDepth=32; + bChangeRes=FALSE; + #ifdef _WINDOWS + bWindowMode=TRUE; + #else + bWindowMode=FALSE; + #endif + bFullVRam=FALSE; + iFilterType=0; + // bAdvancedBlend=FALSE; + bDrawDither=FALSE; + // bUseLines=FALSE; + bUseFrameLimit=FALSE; + bUseFrameSkip=FALSE; + iFrameLimit=0; + fFrameRate=50.0f; + iOffscreenDrawing=0; + //bOpaquePass=FALSE; + //bUseAntiAlias=FALSE; + //iTexQuality=0; + #ifdef _WINDOWS + iWinSize=MAKELONG(iResX,iResY); + #endif + iUseMask=0; + iZBufferDepth=0; + bUseFastMdec=FALSE; + bUse15bitMdec=FALSE; + dwCfgFixes=0; + bUseFixes=FALSE; + // iUseScanLines=0; + iFrameTexType=0; + iFrameReadType=0; + //iShowFPS=0; + bKeepRatio=TRUE; + iScanBlend=0; + iVRamSize=0; + iTexGarbageCollection=0; + iBlurBuffer=0; + //iHiResTextures=0; + iNoScreenSaver=0; + //iForceVSync=0; + + + +#ifdef _WINDOWS + memset(&dv,0,sizeof(DEVMODE)); + dv.dmSize=sizeof(DEVMODE); + EnumDisplaySettings(NULL,ENUM_CURRENT_SETTINGS,&dv); +#endif + bIsFirstFrame = TRUE; // flag: we have to init OGL later in windows! + +#ifdef _WINDOWS + if(bWindowMode) // win mode? + { + DWORD dw=GetWindowLong(hWWindow, GWL_STYLE); // -> adjust wnd style (owndc needed by some stupid ogl drivers) + dw&=~WS_THICKFRAME; + dw|=WS_BORDER|WS_CAPTION|CS_OWNDC; + SetWindowLong(hWWindow, GWL_STYLE, dw); + + hPSEMenu=GetMenu(hWWindow); // -> hide emu menu (if any) + if(hPSEMenu!=NULL) SetMenu(hWWindow,NULL); + + iResX=LOWORD(iWinSize);iResY=HIWORD(iWinSize); + ShowWindow(hWWindow,SW_SHOWNORMAL); + + MoveWindow(hWWindow, // -> center wnd + GetSystemMetrics(SM_CXFULLSCREEN)/2-iResX/2, + GetSystemMetrics(SM_CYFULLSCREEN)/2-iResY/2, + iResX+GetSystemMetrics(SM_CXFIXEDFRAME)+3, + iResY+GetSystemMetrics(SM_CYFIXEDFRAME)+GetSystemMetrics(SM_CYCAPTION)+3, + TRUE); + UpdateWindow(hWWindow); // -> let windows do some update + + if(dv.dmBitsPerPel==16 || dv.dmBitsPerPel==32) // -> overwrite user color info with desktop color info + iColDepth=dv.dmBitsPerPel; + } + else // fullscreen mode: + { + if(dv.dmBitsPerPel!=(unsigned int)iColDepth || // -> check, if we have to change resolution + dv.dmPelsWidth !=(unsigned int)iResX || + dv.dmPelsHeight!=(unsigned int)iResY) + bChangeRes=TRUE; else bChangeRes=FALSE; + + if(bChangeRes) ChangeDesktop(); // -> change the res (had to do an own func because of some MS 'optimizations') + + SetWindowLong(hWWindow, GWL_STYLE, CS_OWNDC); // -> adjust wnd style as well (to be sure) + + hPSEMenu=GetMenu(hWWindow); // -> hide menu + if(hPSEMenu!=NULL) SetMenu(hWWindow,NULL); + ShowWindow(hWWindow,SW_SHOWMAXIMIZED); // -> max mode + } +#endif + rRatioRect.left = rRatioRect.top=0; + rRatioRect.right = iResX; + rRatioRect.bottom = iResY; + +#ifdef _WINDOWS + r.left=r.top=0;r.right=iResX;r.bottom=iResY; // hack for getting a clean black window until OGL gets initialized + hdc = GetDC(hWWindow); + FillRect(hdc,&r,(HBRUSH)GetStockObject(BLACK_BRUSH)); + bSetupPixelFormat(hdc); + ReleaseDC(hWWindow,hdc); +#endif + bDisplayNotSet = TRUE; + bSetClip=TRUE; + + SetFixes(); // setup game fixes + + InitializeTextureStore(); // init texture mem + +// lGPUstatusRet = 0x74000000; + +// with some emus, we could do the OGL init right here... oh my +// if(bIsFirstFrame) GLinitialize(); + + return 0; +} + +//////////////////////////////////////////////////////////////////////// +// close +//////////////////////////////////////////////////////////////////////// + +#ifdef _WINDOWS +long CALLBACK GPUclose() // WINDOWS CLOSE +{ +// ExitKeyHandler(); + + GLcleanup(); // close OGL + + if(bChangeRes) // change res back + ChangeDisplaySettings(NULL,0); + + if(hPSEMenu) // set menu again + SetMenu(hWWindow,hPSEMenu); + + if(pGfxCardScreen) free(pGfxCardScreen); // free helper memory + pGfxCardScreen=0; + +// if(iNoScreenSaver) EnableScreenSaver(TRUE); // enable screen saver again + + return 0; +} + +#else + +long GPU_close() // LINUX CLOSE +{ + GLcleanup(); // close OGL + + if(pGfxCardScreen) free(pGfxCardScreen); // free helper memory + pGfxCardScreen=0; + +// osd_close_display(); // destroy display + + return 0; +} +#endif + +//////////////////////////////////////////////////////////////////////// +// I shot the sheriff... last function called from emu +//////////////////////////////////////////////////////////////////////// + +#ifdef _WINDOWS +long CALLBACK GPUshutdown() +#else +long CALLBACK GPU_shutdown() +#endif +{ + if(psxVSecure) free(psxVSecure); // kill emulated vram memory + psxVSecure=0; + + return 0; +} + +//////////////////////////////////////////////////////////////////////// +// paint it black: simple func to clean up optical border garbage +//////////////////////////////////////////////////////////////////////// + +void PaintBlackBorders(void) +{ + short s; + + glDisable(GL_SCISSOR_TEST); + if(bTexEnabled) {glDisable(GL_TEXTURE_2D);bTexEnabled=FALSE;} + if(bOldSmoothShaded) {glShadeModel(GL_FLAT);bOldSmoothShaded=FALSE;} + if(bBlendEnable) {glDisable(GL_BLEND);bBlendEnable=FALSE;} + glDisable(GL_ALPHA_TEST); + + glEnable(GL_ALPHA_TEST); + glEnable(GL_SCISSOR_TEST); +} + +//////////////////////////////////////////////////////////////////////// +// helper to draw scanlines +//////////////////////////////////////////////////////////////////////// + +__inline void XPRIMdrawTexturedQuad(OGLVertex* vertex1, OGLVertex* vertex2, + OGLVertex* vertex3, OGLVertex* vertex4) +{ + +} + +//////////////////////////////////////////////////////////////////////// +// scanlines +//////////////////////////////////////////////////////////////////////// + +void SetScanLines(void) +{ +} + +//////////////////////////////////////////////////////////////////////// +// blur, babe, blur (heavy performance hit for a so-so fullscreen effect) +//////////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////////// +// Update display (swap buffers)... called in interlaced mode on +// every emulated vsync, otherwise whenever the displayed screen region +// has been changed +//////////////////////////////////////////////////////////////////////// + +int iLastRGB24=0; // special vars for checking when to skip two display updates +int iSkipTwo=0; +void GPU_vSinc(void){ +updateDisplay(); +} +void updateDisplay(void) // UPDATE DISPLAY +{ +BOOL bBlur=FALSE; + +#ifdef _WINDOWS +HDC hdc=GetDC(hWWindow); // windows: +wglMakeCurrent(hdc,GLCONTEXT); // -> make context current again +#endif + +bFakeFrontBuffer=FALSE; +bRenderFrontBuffer=FALSE; + +if(iRenderFVR) // frame buffer read fix mode still active? + { + iRenderFVR--; // -> if some frames in a row without read access: turn off mode + if(!iRenderFVR) bFullVRam=FALSE; + } + +if(iLastRGB24 && iLastRGB24!=PSXDisplay.RGB24+1) // (mdec) garbage check + { + iSkipTwo=2; // -> skip two frames to avoid garbage if color mode changes + } +iLastRGB24=0; + +if(PSXDisplay.RGB24)// && !bNeedUploadAfter) // (mdec) upload wanted? + { + PrepareFullScreenUpload(-1); + UploadScreen(PSXDisplay.Interlaced); // -> upload whole screen from psx vram + bNeedUploadTest=FALSE; + bNeedInterlaceUpdate=FALSE; + bNeedUploadAfter=FALSE; + bNeedRGB24Update=FALSE; + } +else +if(bNeedInterlaceUpdate) // smaller upload? + { + bNeedInterlaceUpdate=FALSE; + xrUploadArea=xrUploadAreaIL; // -> upload this rect + UploadScreen(TRUE); + } + +if(dwActFixes&512) bCheckFF9G4(NULL); // special game fix for FF9 + +if(PreviousPSXDisplay.Range.x0|| // paint black borders around display area, if needed + PreviousPSXDisplay.Range.y0) + PaintBlackBorders(); + +if(PSXDisplay.Disabled) // display disabled? + { + // moved here + glDisable(GL_SCISSOR_TEST); + glClearColor(0,0,0,128); // -> clear whole backbuffer + glClear(uiBufferBits); + glEnable(GL_SCISSOR_TEST); + gl_z=0.0f; + bDisplayNotSet = TRUE; + } + +if(iSkipTwo) // we are in skipping mood? + { + iSkipTwo--; + iDrawnSomething=0; // -> simply lie about something drawn + } + +//if(iBlurBuffer && !bSkipNextFrame) // "blur display" activated? +// {BlurBackBuffer();bBlur=TRUE;} // -> blur it + +// if(iUseScanLines) SetScanLines(); // "scan lines" activated? do it + +// if(usCursorActive) ShowGunCursor(); // "gun cursor" wanted? show 'em + +if(dwActFixes&128) // special FPS limitation mode? + { + if(bUseFrameLimit) PCFrameCap(); // -> ok, do it +// if(bUseFrameSkip || ulKeybits&KEY_SHOWFPS) + PCcalcfps(); + } + +// if(gTexPicName) DisplayPic(); // some gpu info picture active? display it + +// if(bSnapShot) DoSnapShot(); // snapshot key pressed? cheeeese :) + +// if(ulKeybits&KEY_SHOWFPS) // wanna see FPS? + { +// sprintf(szDispBuf,"%06.1f",fps_cur); +// DisplayText(); // -> show it + } + +//----------------------------------------------------// +// main buffer swapping (well, or skip it) + +if(bUseFrameSkip) // frame skipping active ? + { + if(!bSkipNextFrame) + { + if(iDrawnSomething) +#ifdef _WINDOWS + SwapBuffers(wglGetCurrentDC()); // -> to skip or not to skip +#else + eglSwapBuffers(display,surface); +#endif + } + if(dwActFixes&0x180) // -> special old frame skipping: skip max one in a row + { + if((fps_skip < fFrameRateHz) && !(bSkipNextFrame)) + {bSkipNextFrame = TRUE; fps_skip=fFrameRateHz;} + else bSkipNextFrame = FALSE; + } + else FrameSkip(); + } +else // no skip ? + { + if(iDrawnSomething) +#ifdef _WINDOWS + SwapBuffers(wglGetCurrentDC()); // -> swap +#else + eglSwapBuffers(display,surface); +#endif + } + +iDrawnSomething=0; + +//----------------------------------------------------// + +if(lClearOnSwap) // clear buffer after swap? + { + GLclampf g,b,r; + + if(bDisplayNotSet) // -> set new vals + SetOGLDisplaySettings(1); + + g=((GLclampf)GREEN(lClearOnSwapColor))/255.0f; // -> get col + b=((GLclampf)BLUE(lClearOnSwapColor))/255.0f; + r=((GLclampf)RED(lClearOnSwapColor))/255.0f; + + glDisable(GL_SCISSOR_TEST); + glClearColor(r,g,b,128); // -> clear + glClear(uiBufferBits); + glEnable(GL_SCISSOR_TEST); + lClearOnSwap=0; // -> done + } +else + { +// if(bBlur) UnBlurBackBuffer(); // unblur buff, if blurred before + + if(iZBufferDepth) // clear zbuffer as well (if activated) + { + glDisable(GL_SCISSOR_TEST); + glClear(GL_DEPTH_BUFFER_BIT); + glEnable(GL_SCISSOR_TEST); + } + } +gl_z=0.0f; + +//----------------------------------------------------// +// additional uploads immediatly after swapping + +if(bNeedUploadAfter) // upload wanted? + { + bNeedUploadAfter=FALSE; + bNeedUploadTest=FALSE; + UploadScreen(-1); // -> upload + } + +if(bNeedUploadTest) + { + bNeedUploadTest=FALSE; + if(PSXDisplay.InterlacedTest && + //iOffscreenDrawing>2 && + PreviousPSXDisplay.DisplayPosition.x==PSXDisplay.DisplayPosition.x && + PreviousPSXDisplay.DisplayEnd.x==PSXDisplay.DisplayEnd.x && + PreviousPSXDisplay.DisplayPosition.y==PSXDisplay.DisplayPosition.y && + PreviousPSXDisplay.DisplayEnd.y==PSXDisplay.DisplayEnd.y) + { + PrepareFullScreenUpload(TRUE); + UploadScreen(TRUE); + } + } + +//----------------------------------------------------// +// rumbling (main emu pad effect) + +if(iRumbleTime) // shake screen by modifying view port + { + int i1=0,i2=0,i3=0,i4=0; + + iRumbleTime--; + if(iRumbleTime) + { + i1=((rand()*iRumbleVal)/RAND_MAX)-(iRumbleVal/2); + i2=((rand()*iRumbleVal)/RAND_MAX)-(iRumbleVal/2); + i3=((rand()*iRumbleVal)/RAND_MAX)-(iRumbleVal/2); + i4=((rand()*iRumbleVal)/RAND_MAX)-(iRumbleVal/2); + } + + glViewport(rRatioRect.left+i1, + iResY-(rRatioRect.top+rRatioRect.bottom)+i2, + rRatioRect.right+i3, + rRatioRect.bottom+i4); + } + +//----------------------------------------------------// + + + +// if(ulKeybits&KEY_RESETTEXSTORE) ResetStuff(); // reset on gpu mode changes? do it before next frame is filled +} + +//////////////////////////////////////////////////////////////////////// +// update front display: smaller update func, if something has changed +// in the frontbuffer... dirty, but hey... real men know no pain +//////////////////////////////////////////////////////////////////////// + +void updateFrontDisplay(void) +{ +if(PreviousPSXDisplay.Range.x0|| + PreviousPSXDisplay.Range.y0) + PaintBlackBorders(); + +//if(iBlurBuffer) BlurBackBuffer(); + +//if(iUseScanLines) SetScanLines(); + +// if(usCursorActive) ShowGunCursor(); + +bFakeFrontBuffer=FALSE; +bRenderFrontBuffer=FALSE; + +// if(gTexPicName) DisplayPic(); +// if(ulKeybits&KEY_SHOWFPS) DisplayText(); + +#ifdef _WINDOWS + { // windows: + HDC hdc=GetDC(hWWindow); + wglMakeCurrent(hdc,GLCONTEXT); // -> make current again + if(iDrawnSomething) + SwapBuffers(wglGetCurrentDC()); // -> swap + ReleaseDC(hWWindow,hdc); // -> ! important ! + } +#else +if(iDrawnSomething) // linux: + eglSwapBuffers(display,surface); +#endif + +//if(iBlurBuffer) UnBlurBackBuffer(); +} + +//////////////////////////////////////////////////////////////////////// +// check if update needed +//////////////////////////////////////////////////////////////////////// +void ChangeDispOffsetsX(void) // CENTER X +{ +long lx,l;short sO; + +if(!PSXDisplay.Range.x1) return; // some range given? + +l=PSXDisplay.DisplayMode.x; + +l*=(long)PSXDisplay.Range.x1; // some funky calculation +l/=2560;lx=l;l&=0xfffffff8; + +if(l==PreviousPSXDisplay.Range.x1) return; // some change? + +sO=PreviousPSXDisplay.Range.x0; // store old + +if(lx>=PSXDisplay.DisplayMode.x) // range bigger? + { + PreviousPSXDisplay.Range.x1= // -> take display width + PSXDisplay.DisplayMode.x; + PreviousPSXDisplay.Range.x0=0; // -> start pos is 0 + } +else // range smaller? center it + { + PreviousPSXDisplay.Range.x1=l; // -> store width (8 pixel aligned) + PreviousPSXDisplay.Range.x0= // -> calc start pos + (PSXDisplay.Range.x0-500)/8; + if(PreviousPSXDisplay.Range.x0<0) // -> we don't support neg. values yet + PreviousPSXDisplay.Range.x0=0; + + if((PreviousPSXDisplay.Range.x0+lx)> // -> uhuu... that's too much + PSXDisplay.DisplayMode.x) + { + PreviousPSXDisplay.Range.x0= // -> adjust start + PSXDisplay.DisplayMode.x-lx; + PreviousPSXDisplay.Range.x1+=lx-l; // -> adjust width + } + } + +if(sO!=PreviousPSXDisplay.Range.x0) // something changed? + { + bDisplayNotSet=TRUE; // -> recalc display stuff + } +} + +//////////////////////////////////////////////////////////////////////// + +void ChangeDispOffsetsY(void) // CENTER Y +{ +int iT;short sO; // store previous y size + +if(PSXDisplay.PAL) iT=48; else iT=28; // different offsets on PAL/NTSC + +if(PSXDisplay.Range.y0>=iT) // crossed the security line? :) + { + PreviousPSXDisplay.Range.y1= // -> store width + PSXDisplay.DisplayModeNew.y; + + sO=(PSXDisplay.Range.y0-iT-4)*PSXDisplay.Double; // -> calc offset + if(sO<0) sO=0; + + PSXDisplay.DisplayModeNew.y+=sO; // -> add offset to y size, too + } +else sO=0; // else no offset + +if(sO!=PreviousPSXDisplay.Range.y0) // something changed? + { + PreviousPSXDisplay.Range.y0=sO; + bDisplayNotSet=TRUE; // -> recalc display stuff + } +} + +//////////////////////////////////////////////////////////////////////// +// Aspect ratio of ogl screen: simply adjusting ogl view port +//////////////////////////////////////////////////////////////////////// + +void SetAspectRatio(void) +{ +float xs,ys,s;RECT r; + +if(!PSXDisplay.DisplayModeNew.x) return; +if(!PSXDisplay.DisplayModeNew.y) return; + +xs=(float)iResX/(float)PSXDisplay.DisplayModeNew.x; +ys=(float)iResY/(float)PSXDisplay.DisplayModeNew.y; + +s=min(xs,ys); +r.right =(int)((float)PSXDisplay.DisplayModeNew.x*s); +r.bottom=(int)((float)PSXDisplay.DisplayModeNew.y*s); +if(r.right > iResX) r.right = iResX; +if(r.bottom > iResY) r.bottom = iResY; +if(r.right < 1) r.right = 1; +if(r.bottom < 1) r.bottom = 1; + +r.left = (iResX-r.right)/2; +r.top = (iResY-r.bottom)/2; + +if(r.bottom new psx resolution + PSXDisplay.DisplayModeNew.y, 0, -1, 1); + if(bKeepRatio) SetAspectRatio(); + } + +bDisplayNotSet = TRUE; // re-calc offsets/display area + +bUp=FALSE; +if(PSXDisplay.RGB24!=PSXDisplay.RGB24New) // clean up textures, if rgb mode change (usually mdec on/off) + { + PreviousPSXDisplay.RGB24=0; // no full 24 frame uploaded yet + ResetTextureArea(FALSE); + bUp=TRUE; + } + +PSXDisplay.RGB24 = PSXDisplay.RGB24New; // get new infos +PSXDisplay.DisplayMode.y = PSXDisplay.DisplayModeNew.y; +PSXDisplay.DisplayMode.x = PSXDisplay.DisplayModeNew.x; +PSXDisplay.Interlaced = PSXDisplay.InterlacedNew; + +PSXDisplay.DisplayEnd.x= // calc new ends + PSXDisplay.DisplayPosition.x+ PSXDisplay.DisplayMode.x; +PSXDisplay.DisplayEnd.y= + PSXDisplay.DisplayPosition.y+ PSXDisplay.DisplayMode.y+PreviousPSXDisplay.DisplayModeNew.y; +PreviousPSXDisplay.DisplayEnd.x= + PreviousPSXDisplay.DisplayPosition.x+ PSXDisplay.DisplayMode.x; +PreviousPSXDisplay.DisplayEnd.y= + PreviousPSXDisplay.DisplayPosition.y+ PSXDisplay.DisplayMode.y+PreviousPSXDisplay.DisplayModeNew.y; + +ChangeDispOffsetsX(); + +if(iFrameLimit==2) SetAutoFrameCap(); // set new fps limit vals (depends on interlace) + +if(bUp) updateDisplay(); // yeah, real update (swap buffer) +} + +//////////////////////////////////////////////////////////////////////// +// window mode <-> fullscreen mode (windows) +//////////////////////////////////////////////////////////////////////// + +#ifdef _WINDOWS +void ChangeWindowMode(void) +{ + GPUclose(); + bWindowMode=!bWindowMode; + GPUopen(hWWindow); + bChangeWinMode=FALSE; +} +#endif + +//////////////////////////////////////////////////////////////////////// +// swap update check (called by psx vsync function) +//////////////////////////////////////////////////////////////////////// + +BOOL bSwapCheck(void) +{ +static int iPosCheck=0; +static PSXPoint_t pO; +static PSXPoint_t pD; +static int iDoAgain=0; + +if(PSXDisplay.DisplayPosition.x==pO.x && + PSXDisplay.DisplayPosition.y==pO.y && + PSXDisplay.DisplayEnd.x==pD.x && + PSXDisplay.DisplayEnd.y==pD.y) + iPosCheck++; +else iPosCheck=0; + +pO=PSXDisplay.DisplayPosition; +pD=PSXDisplay.DisplayEnd; + +if(iPosCheck<=4) return FALSE; + +iPosCheck=4; + +if(PSXDisplay.Interlaced) return FALSE; + +if (bNeedInterlaceUpdate|| + bNeedRGB24Update || + bNeedUploadAfter|| + bNeedUploadTest || + iDoAgain + ) + { + iDoAgain=0; + if(bNeedUploadAfter) + iDoAgain=1; + if(bNeedUploadTest && PSXDisplay.InterlacedTest) + iDoAgain=1; + + bDisplayNotSet = TRUE; + updateDisplay(); + + PreviousPSXDisplay.DisplayPosition.x=PSXDisplay.DisplayPosition.x; + PreviousPSXDisplay.DisplayPosition.y=PSXDisplay.DisplayPosition.y; + PreviousPSXDisplay.DisplayEnd.x=PSXDisplay.DisplayEnd.x; + PreviousPSXDisplay.DisplayEnd.y=PSXDisplay.DisplayEnd.y; + pO=PSXDisplay.DisplayPosition; + pD=PSXDisplay.DisplayEnd; + + return TRUE; + } + +return FALSE; +} +//////////////////////////////////////////////////////////////////////// +// gun cursor func: player=0-7, x=0-511, y=0-255 +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +// update lace is called every VSync. Basically we limit frame rate +// here, and in interlaced mode we swap ogl display buffers. +//////////////////////////////////////////////////////////////////////// + +static unsigned short usFirstPos=2; + +#ifdef _WINDOWS +void CALLBACK GPUupdateLace(void) +#else +void CALLBACK GPU_updateLace(void) +#endif +{ +if(!(dwActFixes&0x1000)) + STATUSREG^=0x80000000; // interlaced bit toggle, if the CC game fix is not active (see gpuReadStatus) + +if(!(dwActFixes&128)) // normal frame limit func + CheckFrameRate(); + +if(iOffscreenDrawing==4) // special check if high offscreen drawing is on + { + if(bSwapCheck()) return; + } + +if(PSXDisplay.Interlaced) // interlaced mode? + { + if(PSXDisplay.DisplayMode.x>0 && PSXDisplay.DisplayMode.y>0) + { + updateDisplay(); // -> swap buffers (new frame) + } + } +else if(bRenderFrontBuffer) // no interlace mode? and some stuff in front has changed? + { + updateFrontDisplay(); // -> update front buffer + } +else if(usFirstPos==1) // initial updates (after startup) + { + updateDisplay(); + } + +#ifdef _WINDOWS +if(bChangeWinMode) ChangeWindowMode(); +#endif +} + +//////////////////////////////////////////////////////////////////////// +// process read request from GPU status register +//////////////////////////////////////////////////////////////////////// + +#ifdef _WINDOWS +unsigned long CALLBACK GPUreadStatus(void) +#else +unsigned long CALLBACK GPU_readStatus(void) +#endif +{ +if(dwActFixes&0x1000) // CC game fix + { + static int iNumRead=0; + if((iNumRead++)==2) + { + iNumRead=0; + STATUSREG^=0x80000000; // interlaced bit toggle... we do it on every second read status... needed by some games (like ChronoCross) + } + } + +if(iFakePrimBusy) // 27.10.2007 - emulating some 'busy' while drawing... pfff... not perfect, but since our emulated dma is not done in an extra thread... + { + iFakePrimBusy--; + + if(iFakePrimBusy&1) // we do a busy-idle-busy-idle sequence after/while drawing prims + { + GPUIsBusy; + GPUIsNotReadyForCommands; + } + else + { + GPUIsIdle; + GPUIsReadyForCommands; + } + } + +return STATUSREG; +} + +//////////////////////////////////////////////////////////////////////// +// processes data send to GPU status register +// these are always single packet commands. +//////////////////////////////////////////////////////////////////////// + +#ifdef _WINDOWS +void CALLBACK GPUwriteStatus(unsigned long gdata) +#else +void CALLBACK GPU_writeStatus(unsigned long gdata) +#endif +{ +unsigned long lCommand=(gdata>>24)&0xff; + +#ifdef _WINDOWS +if(bIsFirstFrame) GLinitialize(); // real ogl startup (needed by some emus) +#endif + +ulStatusControl[lCommand]=gdata; + +switch(lCommand) + { + //--------------------------------------------------// + // reset gpu + case 0x00: + memset(ulGPUInfoVals,0x00,16*sizeof(unsigned long)); + lGPUstatusRet=0x14802000; + PSXDisplay.Disabled=1; + iDataWriteMode=iDataReadMode=DR_NORMAL; + PSXDisplay.DrawOffset.x=PSXDisplay.DrawOffset.y=0; + drawX=drawY=0;drawW=drawH=0; + sSetMask=0;lSetMask=0;bCheckMask=FALSE;iSetMask=0; + usMirror=0; + GlobalTextAddrX=0;GlobalTextAddrY=0; + GlobalTextTP=0;GlobalTextABR=0; + PSXDisplay.RGB24=FALSE; + PSXDisplay.Interlaced=FALSE; + bUsingTWin = FALSE; + return; + + // dis/enable display + case 0x03: + PreviousPSXDisplay.Disabled = PSXDisplay.Disabled; + PSXDisplay.Disabled = (gdata & 1); + + if(PSXDisplay.Disabled) + STATUSREG|=GPUSTATUS_DISPLAYDISABLED; + else STATUSREG&=~GPUSTATUS_DISPLAYDISABLED; + + if (iOffscreenDrawing==4 && + PreviousPSXDisplay.Disabled && + !(PSXDisplay.Disabled)) + { + + if(!PSXDisplay.RGB24) + { + PrepareFullScreenUpload(TRUE); + UploadScreen(TRUE); + updateDisplay(); + } + } + + return; + + // setting transfer mode + case 0x04: + gdata &= 0x03; // only want the lower two bits + + iDataWriteMode=iDataReadMode=DR_NORMAL; + if(gdata==0x02) iDataWriteMode=DR_VRAMTRANSFER; + if(gdata==0x03) iDataReadMode =DR_VRAMTRANSFER; + + STATUSREG&=~GPUSTATUS_DMABITS; // clear the current settings of the DMA bits + STATUSREG|=(gdata << 29); // set the DMA bits according to the received data + + return; + + // setting display position + case 0x05: + { + short sx=(short)(gdata & 0x3ff); + short sy; + + if(iGPUHeight==1024) + { + if(dwGPUVersion==2) + sy = (short)((gdata>>12)&0x3ff); + else sy = (short)((gdata>>10)&0x3ff); + } + else sy = (short)((gdata>>10)&0x3ff); // really: 0x1ff, but we adjust it later + + if (sy & 0x200) + { + sy|=0xfc00; + PreviousPSXDisplay.DisplayModeNew.y=sy/PSXDisplay.Double; + sy=0; + } + else PreviousPSXDisplay.DisplayModeNew.y=0; + + if(sx>1000) sx=0; + + if(usFirstPos) + { + usFirstPos--; + if(usFirstPos) + { + PreviousPSXDisplay.DisplayPosition.x = sx; + PreviousPSXDisplay.DisplayPosition.y = sy; + PSXDisplay.DisplayPosition.x = sx; + PSXDisplay.DisplayPosition.y = sy; + } + } + + if(dwActFixes&8) + { + if((!PSXDisplay.Interlaced) && + PreviousPSXDisplay.DisplayPosition.x == sx && + PreviousPSXDisplay.DisplayPosition.y == sy) + return; + + PSXDisplay.DisplayPosition.x = PreviousPSXDisplay.DisplayPosition.x; + PSXDisplay.DisplayPosition.y = PreviousPSXDisplay.DisplayPosition.y; + PreviousPSXDisplay.DisplayPosition.x = sx; + PreviousPSXDisplay.DisplayPosition.y = sy; + } + else + { + if((!PSXDisplay.Interlaced) && + PSXDisplay.DisplayPosition.x == sx && + PSXDisplay.DisplayPosition.y == sy) + return; + PreviousPSXDisplay.DisplayPosition.x = PSXDisplay.DisplayPosition.x; + PreviousPSXDisplay.DisplayPosition.y = PSXDisplay.DisplayPosition.y; + PSXDisplay.DisplayPosition.x = sx; + PSXDisplay.DisplayPosition.y = sy; + } + + PSXDisplay.DisplayEnd.x= + PSXDisplay.DisplayPosition.x+ PSXDisplay.DisplayMode.x; + PSXDisplay.DisplayEnd.y= + PSXDisplay.DisplayPosition.y+ PSXDisplay.DisplayMode.y+PreviousPSXDisplay.DisplayModeNew.y; + + PreviousPSXDisplay.DisplayEnd.x= + PreviousPSXDisplay.DisplayPosition.x+ PSXDisplay.DisplayMode.x; + PreviousPSXDisplay.DisplayEnd.y= + PreviousPSXDisplay.DisplayPosition.y+ PSXDisplay.DisplayMode.y+PreviousPSXDisplay.DisplayModeNew.y; + + bDisplayNotSet = TRUE; + + if (!(PSXDisplay.Interlaced)) + { + updateDisplay(); + } + else + if(PSXDisplay.InterlacedTest && + ((PreviousPSXDisplay.DisplayPosition.x != PSXDisplay.DisplayPosition.x)|| + (PreviousPSXDisplay.DisplayPosition.y != PSXDisplay.DisplayPosition.y))) + PSXDisplay.InterlacedTest--; + + return; + } + + // setting width + case 0x06: + + PSXDisplay.Range.x0=gdata & 0x7ff; //0x3ff; + PSXDisplay.Range.x1=(gdata>>12) & 0xfff;//0x7ff; + + PSXDisplay.Range.x1-=PSXDisplay.Range.x0; + + ChangeDispOffsetsX(); + + return; + + // setting height + case 0x07: + + PreviousPSXDisplay.Height = PSXDisplay.Height; + + PSXDisplay.Range.y0=gdata & 0x3ff; + PSXDisplay.Range.y1=(gdata>>10) & 0x3ff; + + PSXDisplay.Height = PSXDisplay.Range.y1 - + PSXDisplay.Range.y0 + + PreviousPSXDisplay.DisplayModeNew.y; + + if (PreviousPSXDisplay.Height != PSXDisplay.Height) + { + PSXDisplay.DisplayModeNew.y=PSXDisplay.Height*PSXDisplay.Double; + ChangeDispOffsetsY(); + updateDisplayIfChanged(); + } + return; + + // setting display infos + case 0x08: + + PSXDisplay.DisplayModeNew.x = dispWidths[(gdata & 0x03) | ((gdata & 0x40) >> 4)]; + + if (gdata&0x04) PSXDisplay.Double=2; + else PSXDisplay.Double=1; + PSXDisplay.DisplayModeNew.y = PSXDisplay.Height*PSXDisplay.Double; + + ChangeDispOffsetsY(); + + PSXDisplay.PAL = (gdata & 0x08)?TRUE:FALSE; // if 1 - PAL mode, else NTSC + PSXDisplay.RGB24New = (gdata & 0x10)?TRUE:FALSE; // if 1 - TrueColor + PSXDisplay.InterlacedNew = (gdata & 0x20)?TRUE:FALSE; // if 1 - Interlace + + STATUSREG&=~GPUSTATUS_WIDTHBITS; // clear the width bits + + STATUSREG|= + (((gdata & 0x03) << 17) | + ((gdata & 0x40) << 10)); // set the width bits + + PreviousPSXDisplay.InterlacedNew=FALSE; + if (PSXDisplay.InterlacedNew) + { + if(!PSXDisplay.Interlaced) + { + PSXDisplay.InterlacedTest=2; + PreviousPSXDisplay.DisplayPosition.x = PSXDisplay.DisplayPosition.x; + PreviousPSXDisplay.DisplayPosition.y = PSXDisplay.DisplayPosition.y; + PreviousPSXDisplay.InterlacedNew=TRUE; + } + + STATUSREG|=GPUSTATUS_INTERLACED; + } + else + { + PSXDisplay.InterlacedTest=0; + STATUSREG&=~GPUSTATUS_INTERLACED; + } + + if (PSXDisplay.PAL) + STATUSREG|=GPUSTATUS_PAL; + else STATUSREG&=~GPUSTATUS_PAL; + + if (PSXDisplay.Double==2) + STATUSREG|=GPUSTATUS_DOUBLEHEIGHT; + else STATUSREG&=~GPUSTATUS_DOUBLEHEIGHT; + + if (PSXDisplay.RGB24New) + STATUSREG|=GPUSTATUS_RGB24; + else STATUSREG&=~GPUSTATUS_RGB24; + + updateDisplayIfChanged(); + + return; + + //--------------------------------------------------// + // ask about GPU version and other stuff + case 0x10: + + gdata&=0xff; + + switch(gdata) + { + case 0x02: + GPUdataRet=ulGPUInfoVals[INFO_TW]; // tw infos + return; + case 0x03: + GPUdataRet=ulGPUInfoVals[INFO_DRAWSTART]; // draw start + return; + case 0x04: + GPUdataRet=ulGPUInfoVals[INFO_DRAWEND]; // draw end + return; + case 0x05: + case 0x06: + GPUdataRet=ulGPUInfoVals[INFO_DRAWOFF]; // draw offset + return; + case 0x07: + if(dwGPUVersion==2) + GPUdataRet=0x01; + else GPUdataRet=0x02; // gpu type + return; + case 0x08: + case 0x0F: // some bios addr? + GPUdataRet=0xBFC03720; + return; + } + return; + //--------------------------------------------------// + } +} + +//////////////////////////////////////////////////////////////////////// +// vram read/write helpers +//////////////////////////////////////////////////////////////////////// + +BOOL bNeedWriteUpload=FALSE; + +__inline void FinishedVRAMWrite(void) +{ + if(bNeedWriteUpload) + { + bNeedWriteUpload=FALSE; + CheckWriteUpdate(); + } + + // set register to NORMAL operation + iDataWriteMode = DR_NORMAL; + + // reset transfer values, to prevent mis-transfer of data + VRAMWrite.ColsRemaining = 0; + VRAMWrite.RowsRemaining = 0; +} + +__inline void FinishedVRAMRead(void) +{ + // set register to NORMAL operation + iDataReadMode = DR_NORMAL; + // reset transfer values, to prevent mis-transfer of data + VRAMRead.x = 0; + VRAMRead.y = 0; + VRAMRead.Width = 0; + VRAMRead.Height = 0; + VRAMRead.ColsRemaining = 0; + VRAMRead.RowsRemaining = 0; + + // indicate GPU is no longer ready for VRAM data in the STATUS REGISTER + STATUSREG&=~GPUSTATUS_READYFORVRAM; +} + +//////////////////////////////////////////////////////////////////////// +// vram read check ex (reading from card's back/frontbuffer if needed... +// slow!) +//////////////////////////////////////////////////////////////////////// + +void CheckVRamReadEx(int x, int y, int dx, int dy) +{ + unsigned short sArea; + int ux,uy,udx,udy,wx,wy; + unsigned short * p1, *p2; + float XS,YS; + u8 * ps; + u8 * px; + unsigned short s,sx; + + if(STATUSREG&GPUSTATUS_RGB24) return; + + if(((dx > PSXDisplay.DisplayPosition.x) && + (x < PSXDisplay.DisplayEnd.x) && + (dy > PSXDisplay.DisplayPosition.y) && + (y < PSXDisplay.DisplayEnd.y))) + sArea=0; + else + if((!(PSXDisplay.InterlacedTest) && + (dx > PreviousPSXDisplay.DisplayPosition.x) && + (x < PreviousPSXDisplay.DisplayEnd.x) && + (dy > PreviousPSXDisplay.DisplayPosition.y) && + (y < PreviousPSXDisplay.DisplayEnd.y))) + sArea=1; + else + { + return; + } + + ////////////// + + if(iRenderFVR) + { + bFullVRam=TRUE;iRenderFVR=2;return; + } + bFullVRam=TRUE;iRenderFVR=2; + + ////////////// + + p2=0; + + if(sArea==0) + { + ux=PSXDisplay.DisplayPosition.x; + uy=PSXDisplay.DisplayPosition.y; + udx=PSXDisplay.DisplayEnd.x-ux; + udy=PSXDisplay.DisplayEnd.y-uy; + if((PreviousPSXDisplay.DisplayEnd.x- + PreviousPSXDisplay.DisplayPosition.x)==udx && + (PreviousPSXDisplay.DisplayEnd.y- + PreviousPSXDisplay.DisplayPosition.y)==udy) + p2=(psxVuw + (1024*PreviousPSXDisplay.DisplayPosition.y) + + PreviousPSXDisplay.DisplayPosition.x); + } + else + { + ux=PreviousPSXDisplay.DisplayPosition.x; + uy=PreviousPSXDisplay.DisplayPosition.y; + udx=PreviousPSXDisplay.DisplayEnd.x-ux; + udy=PreviousPSXDisplay.DisplayEnd.y-uy; + if((PSXDisplay.DisplayEnd.x- + PSXDisplay.DisplayPosition.x)==udx && + (PSXDisplay.DisplayEnd.y- + PSXDisplay.DisplayPosition.y)==udy) + p2=(psxVuw + (1024*PSXDisplay.DisplayPosition.y) + + PSXDisplay.DisplayPosition.x); + } + + p1=(psxVuw + (1024*uy) + ux); + if(p1==p2) p2=0; + + x=0;y=0; + wx=dx=udx;wy=dy=udy; + + if(udx<=0) return; + if(udy<=0) return; + if(dx<=0) return; + if(dy<=0) return; + if(wx<=0) return; + if(wy<=0) return; + + XS=(float)rRatioRect.right/(float)wx; + YS=(float)rRatioRect.bottom/(float)wy; + + dx=(int)((float)(dx)*XS); + dy=(int)((float)(dy)*YS); + + if(dx>iResX) dx=iResX; + if(dy>iResY) dy=iResY; + + if(dx<=0) return; + if(dy<=0) return; + + // ogl y adjust + y=iResY-y-dy; + + x+=rRatioRect.left; + y-=rRatioRect.top; + + if(y<0) y=0; if((y+dy)>iResY) dy=iResY-y; + + if(!pGfxCardScreen) + { + glPixelStorei(GL_PACK_ALIGNMENT,1); + pGfxCardScreen=(u8 *)malloc(iResX*iResY*4); + } + + ps=pGfxCardScreen; + + //if(!sArea) glReadBuffer(GL_FRONT); + + glReadPixels(x,y,dx,dy,GL_RGB,GL_UNSIGNED_BYTE,ps); + + //if(!sArea) glReadBuffer(GL_BACK); + + s=0; + + XS=(float)dx/(float)(udx); + YS=(float)dy/(float)(udy+1); + + for(y=udy;y>0;y--) + { + for(x=0;x=psxVuw && p1>3;px++; + s=sx; + sx=(*px)>>3;px++; + s|=sx<<5; + sx=(*px)>>3; + s|=sx<<10; + s&=~0x8000; + *p1=s; + } + if(p2>=psxVuw && p2 PSXDisplay.DisplayPosition.x) && + (x < PSXDisplay.DisplayEnd.x) && + (dy > PSXDisplay.DisplayPosition.y) && + (y < PSXDisplay.DisplayEnd.y))) + sArea=0; + else + if((!(PSXDisplay.InterlacedTest) && + (dx > PreviousPSXDisplay.DisplayPosition.x) && + (x < PreviousPSXDisplay.DisplayEnd.x) && + (dy > PreviousPSXDisplay.DisplayPosition.y) && + (y < PreviousPSXDisplay.DisplayEnd.y))) + sArea=1; + else + { + return; + } + + if(dwActFixes&0x40) + { + if(iRenderFVR) + { + bFullVRam=TRUE;iRenderFVR=2;return; + } + bFullVRam=TRUE;iRenderFVR=2; + } + + ux=x;uy=y;udx=dx;udy=dy; + + if(sArea==0) + { + x -=PSXDisplay.DisplayPosition.x; + dx-=PSXDisplay.DisplayPosition.x; + y -=PSXDisplay.DisplayPosition.y; + dy-=PSXDisplay.DisplayPosition.y; + wx=PSXDisplay.DisplayEnd.x-PSXDisplay.DisplayPosition.x; + wy=PSXDisplay.DisplayEnd.y-PSXDisplay.DisplayPosition.y; + } + else + { + x -=PreviousPSXDisplay.DisplayPosition.x; + dx-=PreviousPSXDisplay.DisplayPosition.x; + y -=PreviousPSXDisplay.DisplayPosition.y; + dy-=PreviousPSXDisplay.DisplayPosition.y; + wx=PreviousPSXDisplay.DisplayEnd.x-PreviousPSXDisplay.DisplayPosition.x; + wy=PreviousPSXDisplay.DisplayEnd.y-PreviousPSXDisplay.DisplayPosition.y; + } + if(x<0) {ux-=x;x=0;} + if(y<0) {uy-=y;y=0;} + if(dx>wx) {udx-=(dx-wx);dx=wx;} + if(dy>wy) {udy-=(dy-wy);dy=wy;} + udx-=ux; + udy-=uy; + + p=(psxVuw + (1024*uy) + ux); + + if(udx<=0) return; + if(udy<=0) return; + if(dx<=0) return; + if(dy<=0) return; + if(wx<=0) return; + if(wy<=0) return; + + XS=(float)rRatioRect.right/(float)wx; + YS=(float)rRatioRect.bottom/(float)wy; + + dx=(int)((float)(dx)*XS); + dy=(int)((float)(dy)*YS); + x=(int)((float)x*XS); + y=(int)((float)y*YS); + + dx-=x; + dy-=y; + + if(dx>iResX) dx=iResX; + if(dy>iResY) dy=iResY; + + if(dx<=0) return; + if(dy<=0) return; + + // ogl y adjust + y=iResY-y-dy; + + x+=rRatioRect.left; + y-=rRatioRect.top; + + if(y<0) y=0; if((y+dy)>iResY) dy=iResY-y; + + if(!pGfxCardScreen) + { + glPixelStorei(GL_PACK_ALIGNMENT,1); + pGfxCardScreen=(u8 *)malloc(iResX*iResY*4); + } + + ps=pGfxCardScreen; + +// if(bFront) glReadBuffer(GL_FRONT); + + glReadPixels(x,y,dx,dy,GL_RGB,GL_UNSIGNED_BYTE,ps); + +// if(bFront) glReadBuffer(GL_BACK); + + XS=(float)dx/(float)(udx); + YS=(float)dy/(float)(udy+1); + + for(y=udy;y>0;y--) + { + for(x=0;x=psxVuw && p>3;px++; + s=sx; + sx=(*px)>>3;px++; + s|=sx<<5; + sx=(*px)>>3; + s|=sx<<10; + s&=~0x8000; + *p=s; + } + p++; + } + p += 1024 - udx; + } +} + +//////////////////////////////////////////////////////////////////////// +// core read from vram +//////////////////////////////////////////////////////////////////////// + +#ifdef _WINDOWS +void CALLBACK GPUreadDataMem(unsigned int * pMem, int iSize) +#else +void CALLBACK GPU_readDataMem(unsigned long * pMem, int iSize) +#endif +{ +int i; + +if(iDataReadMode!=DR_VRAMTRANSFER) return; + +GPUIsBusy; + +// adjust read ptr, if necessary +while(VRAMRead.ImagePtr>=psxVuw_eom) + VRAMRead.ImagePtr-=iGPUHeight*1024; +while(VRAMRead.ImagePtr1) && + !(iDrawnSomething==2 && + VRAMRead.x == VRAMWrite.x && + VRAMRead.y == VRAMWrite.y && + VRAMRead.Width == VRAMWrite.Width && + VRAMRead.Height == VRAMWrite.Height)) + CheckVRamRead(VRAMRead.x,VRAMRead.y, + VRAMRead.x+VRAMRead.RowsRemaining, + VRAMRead.y+VRAMRead.ColsRemaining, + TRUE); + +for(i=0;i 0) && (VRAMRead.RowsRemaining > 0)) + { + // lower 16 bit + GPUdataRet=(unsigned long)*VRAMRead.ImagePtr; + + VRAMRead.ImagePtr++; + if(VRAMRead.ImagePtr>=psxVuw_eom) VRAMRead.ImagePtr-=iGPUHeight*1024; + VRAMRead.RowsRemaining --; + + if(VRAMRead.RowsRemaining<=0) + { + VRAMRead.RowsRemaining = VRAMRead.Width; + VRAMRead.ColsRemaining--; + VRAMRead.ImagePtr += 1024 - VRAMRead.Width; + if(VRAMRead.ImagePtr>=psxVuw_eom) VRAMRead.ImagePtr-=iGPUHeight*1024; + } + + // higher 16 bit (always, even if it's an odd width) + GPUdataRet|=(unsigned long)(*VRAMRead.ImagePtr)<<16; + *pMem++=GPUdataRet; + + if(VRAMRead.ColsRemaining <= 0) + {FinishedVRAMRead();goto ENDREAD;} + + VRAMRead.ImagePtr++; + if(VRAMRead.ImagePtr>=psxVuw_eom) VRAMRead.ImagePtr-=iGPUHeight*1024; + VRAMRead.RowsRemaining--; + if(VRAMRead.RowsRemaining<=0) + { + VRAMRead.RowsRemaining = VRAMRead.Width; + VRAMRead.ColsRemaining--; + VRAMRead.ImagePtr += 1024 - VRAMRead.Width; + if(VRAMRead.ImagePtr>=psxVuw_eom) VRAMRead.ImagePtr-=iGPUHeight*1024; + } + if(VRAMRead.ColsRemaining <= 0) + {FinishedVRAMRead();goto ENDREAD;} + } + else {FinishedVRAMRead();goto ENDREAD;} + } + +ENDREAD: +GPUIsIdle; +} + +#ifdef _WINDOWS +unsigned long CALLBACK GPUreadData(void) +#else +unsigned long CALLBACK GPU_readData(void) +#endif +{ + unsigned long l; +#ifdef _WINDOWS + GPUreadDataMem(&l,1); +#else + GPU_readDataMem(&l,1); +#endif + return GPUdataRet; +} + +//////////////////////////////////////////////////////////////////////// +// helper table to know how much data is used by drawing commands +//////////////////////////////////////////////////////////////////////// + +const u8 primTableCX[256] = +{ + // 00 + 0,0,3,0,0,0,0,0, + // 08 + 0,0,0,0,0,0,0,0, + // 10 + 0,0,0,0,0,0,0,0, + // 18 + 0,0,0,0,0,0,0,0, + // 20 + 4,4,4,4,7,7,7,7, + // 28 + 5,5,5,5,9,9,9,9, + // 30 + 6,6,6,6,9,9,9,9, + // 38 + 8,8,8,8,12,12,12,12, + // 40 + 3,3,3,3,0,0,0,0, + // 48 +// 5,5,5,5,6,6,6,6, //FLINE + 254,254,254,254,254,254,254,254, + // 50 + 4,4,4,4,0,0,0,0, + // 58 +// 7,7,7,7,9,9,9,9, // LINEG3 LINEG4 + 255,255,255,255,255,255,255,255, + // 60 + 3,3,3,3,4,4,4,4, // TILE SPRT + // 68 + 2,2,2,2,3,3,3,3, // TILE1 + // 70 + 2,2,2,2,3,3,3,3, + // 78 + 2,2,2,2,3,3,3,3, + // 80 + 4,0,0,0,0,0,0,0, + // 88 + 0,0,0,0,0,0,0,0, + // 90 + 0,0,0,0,0,0,0,0, + // 98 + 0,0,0,0,0,0,0,0, + // a0 + 3,0,0,0,0,0,0,0, + // a8 + 0,0,0,0,0,0,0,0, + // b0 + 0,0,0,0,0,0,0,0, + // b8 + 0,0,0,0,0,0,0,0, + // c0 + 3,0,0,0,0,0,0,0, + // c8 + 0,0,0,0,0,0,0,0, + // d0 + 0,0,0,0,0,0,0,0, + // d8 + 0,0,0,0,0,0,0,0, + // e0 + 0,1,1,1,1,1,1,0, + // e8 + 0,0,0,0,0,0,0,0, + // f0 + 0,0,0,0,0,0,0,0, + // f8 + 0,0,0,0,0,0,0,0 +}; + +//////////////////////////////////////////////////////////////////////// +// processes data send to GPU data register +//////////////////////////////////////////////////////////////////////// + +#ifdef _WINDOWS +void CALLBACK GPUwriteDataMem(unsigned long * pMem, int iSize) +#else +void CALLBACK GPU_writeDataMem(unsigned long * pMem, int iSize) +#endif +{ +u8 command; +unsigned long gdata=0; +int i=0; +GPUIsBusy; +GPUIsNotReadyForCommands; + +STARTVRAM: + +if(iDataWriteMode==DR_VRAMTRANSFER) + { + // make sure we are in vram + while(VRAMWrite.ImagePtr>=psxVuw_eom) + VRAMWrite.ImagePtr-=iGPUHeight*1024; + while(VRAMWrite.ImagePtr0) + { + while(VRAMWrite.RowsRemaining>0) + { + if(i>=iSize) {goto ENDVRAM;} + i++; + + gdata=*pMem++; + + *VRAMWrite.ImagePtr++ = (unsigned short)gdata; + if(VRAMWrite.ImagePtr>=psxVuw_eom) VRAMWrite.ImagePtr-=iGPUHeight*1024; + VRAMWrite.RowsRemaining --; + + if(VRAMWrite.RowsRemaining <= 0) + { + VRAMWrite.ColsRemaining--; + if (VRAMWrite.ColsRemaining <= 0) // last pixel is odd width + { + gdata=(gdata&0xFFFF)|(((unsigned long)(*VRAMWrite.ImagePtr))<<16); + FinishedVRAMWrite(); + goto ENDVRAM; + } + VRAMWrite.RowsRemaining = VRAMWrite.Width; + VRAMWrite.ImagePtr += 1024 - VRAMWrite.Width; + } + + *VRAMWrite.ImagePtr++ = (unsigned short)(gdata>>16); + if(VRAMWrite.ImagePtr>=psxVuw_eom) VRAMWrite.ImagePtr-=iGPUHeight*1024; + VRAMWrite.RowsRemaining --; + } + + VRAMWrite.RowsRemaining = VRAMWrite.Width; + VRAMWrite.ColsRemaining--; + VRAMWrite.ImagePtr += 1024 - VRAMWrite.Width; + } + + FinishedVRAMWrite(); + } + +ENDVRAM: + +if(iDataWriteMode==DR_NORMAL) + { + void (* *primFunc)(u8 *); + if(bSkipNextFrame) primFunc=primTableSkip; + else primFunc=primTableJ; + + for(;i>24) & 0xff); + + if(primTableCX[command]) + { + gpuDataC = primTableCX[command]; + gpuCommand = command; + gpuDataM[0] = gdata; + gpuDataP = 1; + } + else continue; + } + else + { + gpuDataM[gpuDataP] = gdata; + if(gpuDataC>128) + { + if((gpuDataC==254 && gpuDataP>=3) || + (gpuDataC==255 && gpuDataP>=4 && !(gpuDataP&1))) + { + if((gpuDataM[gpuDataP] & 0xF000F000) == 0x50005000) + gpuDataP=gpuDataC-1; + } + } + gpuDataP++; + } + + if(gpuDataP == gpuDataC) + { + gpuDataC=gpuDataP=0; + primFunc[gpuCommand]((u8 *)gpuDataM); + + if(dwEmuFixes&0x0001 || dwActFixes&0x20000) // hack for emulating "gpu busy" in some games + iFakePrimBusy=4; + } + } + } + +GPUdataRet=gdata; + +GPUIsReadyForCommands; +GPUIsIdle; +} + +//////////////////////////////////////////////////////////////////////// + +#ifdef _WINDOWS +void CALLBACK GPUwriteData(unsigned long gdata) +#else +void CALLBACK GPU_writeData(unsigned long gdata) +#endif +{ +#ifdef _WINDOWS + GPUwriteDataMem(&gdata,1); +#else + GPU_writeDataMem(&gdata,1); +#endif +} + +//////////////////////////////////////////////////////////////////////// +// this function will be removed soon (or 'soonish') (or never) +//////////////////////////////////////////////////////////////////////// + +void CALLBACK GPUsetMode(unsigned int gdata) +{ + // ignore old psemu setmode: + + // imageTransfer = gdata; + // iDataWriteMode=(gdata&1)?DR_VRAMTRANSFER:DR_NORMAL; + // iDataReadMode =(gdata&2)?DR_VRAMTRANSFER:DR_NORMAL; +} + +// and this function will be removed soon as well, hehehe... +long CALLBACK GPUgetMode(void) +{ + // ignore old psemu setmode + // return imageTransfer; + +long iT=0; + +if(iDataWriteMode==DR_VRAMTRANSFER) iT|=0x1; +if(iDataReadMode ==DR_VRAMTRANSFER) iT|=0x2; + +return iT; +} + +//////////////////////////////////////////////////////////////////////// +// call config dlg (Windows + Linux) +//////////////////////////////////////////////////////////////////////// + +#ifndef _WINDOWS + +/*#include + +void StartCfgTool(s8 * pCmdLine) // linux: start external cfg tool +{ + FILE * cf;s8 filename[255],t[255]; + + strcpy(filename,"cfg/cfgPeopsMesaGL"); // look in cfg sub folder first + cf=fopen(filename,"rb"); + if(cf!=NULL) + { + fclose(cf); + getcwd(t,255); + chdir("cfg"); + sprintf(filename,"./cfgPeopsMesaGL %s",pCmdLine); + system(filename); + chdir(t); + } + else + { + strcpy(filename,"cfgPeopsMesaGL"); // look in current folder + cf=fopen(filename,"rb"); + if(cf!=NULL) + { + fclose(cf); + sprintf(filename,"./cfgPeopsMesaGL %s",pCmdLine); + system(filename); + } + else + { + sprintf(filename,"%s/cfgPeopsMesaGL",getenv("HOME")); // look in home folder + cf=fopen(filename,"rb"); + if(cf!=NULL) + { + fclose(cf); + getcwd(t,255); + chdir(getenv("HOME")); + sprintf(filename,"./cfgPeopsMesaGL %s",pCmdLine); + system(filename); + chdir(t); + } + else printf("cfgPeopsMesaGL not found!\n"); + } + } +} +*/ +#endif + + +#ifdef _WINDOWS +long CALLBACK GPUconfigure(void) +#else +long CALLBACK GPU_configure(void) +#endif +{ + +#ifdef _WINDOWS +// HWND hWP=GetActiveWindow(); +// DialogBox(hInst,MAKEINTRESOURCE(IDD_CFGDLG), +// hWP,(DLGPROC)CfgDlgProc); +#else + +// StartCfgTool("CFG"); + +#endif + + return 0; +} + +//////////////////////////////////////////////////////////////////////// +// sets all kind of act fixes +//////////////////////////////////////////////////////////////////////// + +void SetFixes(void) +{ + ReInitFrameCap(); + + if(dwActFixes & 0x2000) + dispWidths[4]=384; + else dispWidths[4]=368; +} + +//////////////////////////////////////////////////////////////////////// +// Pete Special: make an 'intelligent' dma chain check (<-Tekken3) +//////////////////////////////////////////////////////////////////////// + +unsigned long lUsedAddr[3]; + +__inline BOOL CheckForEndlessLoop(unsigned long laddr) +{ +if(laddr==lUsedAddr[1]) return TRUE; +if(laddr==lUsedAddr[2]) return TRUE; + +if(laddr 2000000) break; + if(CheckForEndlessLoop(addr)) break; + + count = baseAddrB[addr+3]; + + dmaMem=addr+4; + +#ifdef _WINDOWS + if(count>0) GPUwriteDataMem(&baseAddrL[dmaMem>>2],count); +#else + if(count>0) GPU_writeDataMem(&baseAddrL[dmaMem>>2],count); +#endif + + addr = baseAddrL[addr>>2]&0xffffff; + } +while (addr != 0xffffff); + +GPUIsIdle; + +return 0; +} + +//////////////////////////////////////////////////////////////////////// +// show about dlg +//////////////////////////////////////////////////////////////////////// + +#ifdef _WINDOWS +void CALLBACK GPUabout(void) +#else +void CALLBACK GPU_about(void) +#endif +{ + +} + +//////////////////////////////////////////////////////////////////////// +// We are ever fine ;) +//////////////////////////////////////////////////////////////////////// + +#ifdef _WINDOWS +long CALLBACK GPUtest(void) +#else +long CALLBACK GPU_test(void) +#endif +{ + // if test fails this function should return negative value for error (unable to continue) + // and positive value for warning (can continue but output might be crappy) + + return 0; +} + +//////////////////////////////////////////////////////////////////////// +// save state funcs +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// + +#ifdef _WINDOWS +long CALLBACK GPUfreeze(unsigned long ulGetFreezeData,GPUFreeze_t * pF) +#else +long CALLBACK GPU_freeze(unsigned long ulGetFreezeData,GPUFreeze_t * pF) +#endif +{ +if(ulGetFreezeData==2) + { + long lSlotNum=*((long *)pF); + if(lSlotNum<0) return 0; + if(lSlotNum>8) return 0; + lSelectedSlot=lSlotNum+1; + return 1; + } + +if(!pF) return 0; +if(pF->ulFreezeVersion!=1) return 0; + +if(ulGetFreezeData==1) + { + pF->ulStatus=STATUSREG; + memcpy(pF->ulControl,ulStatusControl,256*sizeof(unsigned long)); + memcpy(pF->psxVRam, psxVub, 1024*iGPUHeight*2); + + return 1; + } + +if(ulGetFreezeData!=0) return 0; + +STATUSREG=pF->ulStatus; +memcpy(ulStatusControl,pF->ulControl,256*sizeof(unsigned long)); +memcpy(psxVub, pF->psxVRam, 1024*iGPUHeight*2); + +ResetTextureArea(TRUE); + +#ifdef _WINDOWS + GPUwriteStatus(ulStatusControl[0]); + GPUwriteStatus(ulStatusControl[1]); + GPUwriteStatus(ulStatusControl[2]); + GPUwriteStatus(ulStatusControl[3]); + GPUwriteStatus(ulStatusControl[8]); + GPUwriteStatus(ulStatusControl[6]); + GPUwriteStatus(ulStatusControl[7]); + GPUwriteStatus(ulStatusControl[5]); + GPUwriteStatus(ulStatusControl[4]); +#else + GPU_writeStatus(ulStatusControl[0]); + GPU_writeStatus(ulStatusControl[1]); + GPU_writeStatus(ulStatusControl[2]); + GPU_writeStatus(ulStatusControl[3]); + GPU_writeStatus(ulStatusControl[8]); + GPU_writeStatus(ulStatusControl[6]); + GPU_writeStatus(ulStatusControl[7]); + GPU_writeStatus(ulStatusControl[5]); + GPU_writeStatus(ulStatusControl[4]); +#endif + return 1; +} + +//////////////////////////////////////////////////////////////////////// +// special "emu infos" / "emu effects" functions +//////////////////////////////////////////////////////////////////////// + +//00 = black +//01 = white +//10 = red +//11 = transparent + +u8 cFont[10][120]= +{ +// 0 +{0xaa,0xaa,0xaa,0xaa,0xaa,0xaa, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x05,0x54,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x05,0x54,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa +}, +// 1 +{0xaa,0xaa,0xaa,0xaa,0xaa,0xaa, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x50,0x00,0x00, + 0x80,0x00,0x05,0x50,0x00,0x00, + 0x80,0x00,0x00,0x50,0x00,0x00, + 0x80,0x00,0x00,0x50,0x00,0x00, + 0x80,0x00,0x00,0x50,0x00,0x00, + 0x80,0x00,0x00,0x50,0x00,0x00, + 0x80,0x00,0x00,0x50,0x00,0x00, + 0x80,0x00,0x00,0x50,0x00,0x00, + 0x80,0x00,0x00,0x50,0x00,0x00, + 0x80,0x00,0x05,0x55,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa +}, +// 2 +{0xaa,0xaa,0xaa,0xaa,0xaa,0xaa, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x05,0x54,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x00,0x05,0x00,0x00, + 0x80,0x00,0x00,0x05,0x00,0x00, + 0x80,0x00,0x00,0x14,0x00,0x00, + 0x80,0x00,0x00,0x50,0x00,0x00, + 0x80,0x00,0x01,0x40,0x00,0x00, + 0x80,0x00,0x05,0x00,0x00,0x00, + 0x80,0x00,0x14,0x00,0x00,0x00, + 0x80,0x00,0x15,0x55,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa +}, +// 3 +{0xaa,0xaa,0xaa,0xaa,0xaa,0xaa, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x05,0x54,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x00,0x05,0x00,0x00, + 0x80,0x00,0x00,0x05,0x00,0x00, + 0x80,0x00,0x01,0x54,0x00,0x00, + 0x80,0x00,0x00,0x05,0x00,0x00, + 0x80,0x00,0x00,0x05,0x00,0x00, + 0x80,0x00,0x00,0x05,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x05,0x54,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa +}, +// 4 +{0xaa,0xaa,0xaa,0xaa,0xaa,0xaa, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x14,0x00,0x00, + 0x80,0x00,0x00,0x54,0x00,0x00, + 0x80,0x00,0x01,0x54,0x00,0x00, + 0x80,0x00,0x01,0x54,0x00,0x00, + 0x80,0x00,0x05,0x14,0x00,0x00, + 0x80,0x00,0x14,0x14,0x00,0x00, + 0x80,0x00,0x15,0x55,0x00,0x00, + 0x80,0x00,0x00,0x14,0x00,0x00, + 0x80,0x00,0x00,0x14,0x00,0x00, + 0x80,0x00,0x00,0x55,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa +}, +// 5 +{0xaa,0xaa,0xaa,0xaa,0xaa,0xaa, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x15,0x55,0x00,0x00, + 0x80,0x00,0x14,0x00,0x00,0x00, + 0x80,0x00,0x14,0x00,0x00,0x00, + 0x80,0x00,0x14,0x00,0x00,0x00, + 0x80,0x00,0x15,0x54,0x00,0x00, + 0x80,0x00,0x00,0x05,0x00,0x00, + 0x80,0x00,0x00,0x05,0x00,0x00, + 0x80,0x00,0x00,0x05,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x05,0x54,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa +}, +// 6 +{0xaa,0xaa,0xaa,0xaa,0xaa,0xaa, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x01,0x54,0x00,0x00, + 0x80,0x00,0x05,0x00,0x00,0x00, + 0x80,0x00,0x14,0x00,0x00,0x00, + 0x80,0x00,0x14,0x00,0x00,0x00, + 0x80,0x00,0x15,0x54,0x00,0x00, + 0x80,0x00,0x15,0x05,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x05,0x54,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa +}, +// 7 +{0xaa,0xaa,0xaa,0xaa,0xaa,0xaa, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x15,0x55,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x00,0x14,0x00,0x00, + 0x80,0x00,0x00,0x14,0x00,0x00, + 0x80,0x00,0x00,0x50,0x00,0x00, + 0x80,0x00,0x00,0x50,0x00,0x00, + 0x80,0x00,0x01,0x40,0x00,0x00, + 0x80,0x00,0x01,0x40,0x00,0x00, + 0x80,0x00,0x05,0x00,0x00,0x00, + 0x80,0x00,0x05,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa +}, +// 8 +{0xaa,0xaa,0xaa,0xaa,0xaa,0xaa, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x05,0x54,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x05,0x54,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x05,0x54,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa +}, +// 9 +{0xaa,0xaa,0xaa,0xaa,0xaa,0xaa, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x05,0x54,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x14,0x05,0x00,0x00, + 0x80,0x00,0x14,0x15,0x00,0x00, + 0x80,0x00,0x05,0x55,0x00,0x00, + 0x80,0x00,0x00,0x05,0x00,0x00, + 0x80,0x00,0x00,0x05,0x00,0x00, + 0x80,0x00,0x00,0x14,0x00,0x00, + 0x80,0x00,0x05,0x50,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0x80,0x00,0x00,0x00,0x00,0x00, + 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa +} +}; + +//////////////////////////////////////////////////////////////////////// + +void PaintPicDot(u8 * p,u8 c) +{ + if(c==0) {*p++=0x00;*p++=0x00;*p=0x00;return;} + if(c==1) {*p++=0xff;*p++=0xff;*p=0xff;return;} + if(c==2) {*p++=0x00;*p++=0x00;*p=0xff;return;} +} + +//////////////////////////////////////////////////////////////////////// + +#ifdef _WINDOWS +void CALLBACK GPUgetScreenPic(u8 * pMem) +#else +long CALLBACK GPU_getScreenPic(u8 * pMem) +#endif +{ + float XS,YS;int x,y,v; + u8 * ps, * px, * pf; + u8 c; + + if(!pGfxCardScreen) + { + glPixelStorei(GL_PACK_ALIGNMENT,1); + pGfxCardScreen=(u8 *)malloc(iResX*iResY*4); + } + + ps=pGfxCardScreen; + +// glReadBuffer(GL_FRONT); + + glReadPixels(0,0,iResX,iResY,GL_RGB,GL_UNSIGNED_BYTE,ps); + +// glReadBuffer(GL_BACK); + + XS=(float)iResX/128; + YS=(float)iResY/96; + pf=pMem; + + for(y=96;y>0;y--) + { + for(x=0;x<128;x++) + { + px=ps+(3*((int)((float)x * XS))+ + (3*iResX)*((int)((float)y*YS))); + *(pf+0)=*(px+2); + *(pf+1)=*(px+1); + *(pf+2)=*(px+0); + pf+=3; + } + } + + ///////////////////////////////////////////////////////////////////// + // generic number/border painter + + pf=pMem+(103*3); + + for(y=0;y<20;y++) + { + for(x=0;x<6;x++) + { + c=cFont[lSelectedSlot][x+y*6]; + v=(c&0xc0)>>6; + PaintPicDot(pf,(u8)v);pf+=3; // paint the dots into the rect + v=(c&0x30)>>4; + PaintPicDot(pf,(u8)v);pf+=3; + v=(c&0x0c)>>2; + PaintPicDot(pf,(u8)v);pf+=3; + v=c&0x03; + PaintPicDot(pf,(u8)v);pf+=3; + } + pf+=104*3; + } + + pf=pMem; + for(x=0;x<128;x++) + { + *(pf+(95*128*3))=0x00;*pf++=0x00; + *(pf+(95*128*3))=0x00;*pf++=0x00; + *(pf+(95*128*3))=0xff;*pf++=0xff; + } + pf=pMem; + for(y=0;y<96;y++) + { + *(pf+(127*3))=0x00;*pf++=0x00; + *(pf+(127*3))=0x00;*pf++=0x00; + *(pf+(127*3))=0xff;*pf++=0xff; + pf+=127*3; + } + +} + +//////////////////////////////////////////////////////////////////////// + +#ifdef _WINDOWS +void CALLBACK GPUshowScreenPic(u8 * pMem) +#else +long CALLBACK GPU_showScreenPic(u8 * pMem) +#endif +{ +// DestroyPic(); +// if(pMem==0) return; +// CreatePic(pMem); +} + +//////////////////////////////////////////////////////////////////////// + +void CALLBACK GPUsetfix(unsigned long dwFixBits) +{ + dwEmuFixes=dwFixBits; +} + +//////////////////////////////////////////////////////////////////////// + +void CALLBACK GPUvisualVibration(unsigned long iSmall, unsigned long iBig) +{ + int iVibVal; + + if(PSXDisplay.DisplayModeNew.x) // calc min "shake pixel" from screen width + iVibVal=max(1,iResX/PSXDisplay.DisplayModeNew.x); + else iVibVal=1; + // big rumble: 4...15 sp ; small rumble 1...3 sp + if(iBig) iRumbleVal=max(4*iVibVal,min(15*iVibVal,((int)iBig *iVibVal)/10)); + else iRumbleVal=max(1*iVibVal,min( 3*iVibVal,((int)iSmall*iVibVal)/10)); + + srand(timeGetTime()); // init rand (will be used in BufferSwap) + + iRumbleTime=15; // let the rumble last 16 buffer swaps +} + +//////////////////////////////////////////////////////////////////////// +// main emu can set display infos (A/M/G/D) +//////////////////////////////////////////////////////////////////////// + +void CALLBACK GPUdisplayFlags(unsigned long dwFlags) +{ +// dwCoreFlags=dwFlags; +} diff --git a/plugins/gpu-gles/gpuPlugin.h b/plugins/gpu-gles/gpuPlugin.h new file mode 100644 index 00000000..c4520322 --- /dev/null +++ b/plugins/gpu-gles/gpuPlugin.h @@ -0,0 +1,134 @@ +/*************************************************************************** + gpu.h - description + ------------------- + begin : Sun Mar 08 2009 + copyright : (C) 1999-2009 by Pete Bernert + web : www.pbernert.com + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2009/03/08 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +#ifndef _GPU_PLUGIN_H +#define _GPU_PLUGIN_H + +///////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(_WINDOWS) && !defined(__NANOGL__) +#define glOrtho(x,y,z,xx,yy,zz) glOrthof(x,y,z,xx,yy,zz) +#endif + +#define PRED(x) ((x << 3) & 0xF8) +#define PBLUE(x) ((x >> 2) & 0xF8) +#define PGREEN(x) ((x >> 7) & 0xF8) + +#define RED(x) (x & 0xff) +#define BLUE(x) ((x>>16) & 0xff) +#define GREEN(x) ((x>>8) & 0xff) +#define COLOR(x) (x & 0xffffff) + +#ifdef _WINDOWS +#include "Externals.h" +#include "plugin.h" +#include +#else +#ifndef MAEMO_CHANGES + #include "psxCommon.h" +#else + #include "../psxCommon.h" +#endif +#include "gpuExternals.h" +#ifdef __NANOGL__ +#include +#else +#ifdef SOFT_LINKAGE +#pragma softfp_linkage +#endif +#ifndef MAEMO_CHANGES + #include // for opengl es types + #include +#else +#include "gpuStdafx.h" +#endif +#ifdef SOFT_LINKAGE +#pragma no_softfp_linkage +#endif +#endif +#endif +///////////////////////////////////////////////////////////////////////////// + +#define CALLBACK + +#define bool unsigned short + +typedef struct { + u32 ulFreezeVersion; + u32 ulStatus; + u32 ulControl[256]; + u8 psxVRam[1024*1024*2]; +} GPUFreeze_t; + +long CALLBACK GPU_init(); +long CALLBACK GPU_shutdown(); +long CALLBACK GPU_open(int hwndGPU); +long CALLBACK GPU_close(); +unsigned long CALLBACK GPU_readData(void); +void CALLBACK GPU_readDataMem(unsigned long * pMem, int iSize); +unsigned long CALLBACK GPU_readStatus(void); +void CALLBACK GPU_writeData(unsigned long gdata); +void CALLBACK GPU_writeDataMem(unsigned long * pMem, int iSize); +void CALLBACK GPU_writeStatus(unsigned long gdata); +long CALLBACK GPU_dmaChain(unsigned long * baseAddrL, unsigned long addr); +void CALLBACK GPU_updateLace(void); +void CALLBACK GPU_makeSnapshot(void); +long CALLBACK GPU_freeze(unsigned long ulGetFreezeData,GPUFreeze_t * pF); +long CALLBACK GPU_getScreenPic(u8 * pMem); +long CALLBACK GPU_showScreenPic(u8 * pMem); +//void CALLBACK GPU_keypressed(int keycode); +//void CALLBACK GPU_displayText(s8 * pText); +//void CALLBACK GPU_clearDynarec(void (CALLBACK *callback)(void)); +long CALLBACK GPU_configure(void); +long CALLBACK GPU_test(void); +void CALLBACK GPU_about(void); + + +void DoSnapShot(void); +void GPU_vSinc(void); +void updateDisplay(void); +void updateFrontDisplay(void); +void SetAutoFrameCap(void); +void SetAspectRatio(void); +void CheckVRamRead(int x, int y, int dx, int dy, bool bFront); +void CheckVRamReadEx(int x, int y, int dx, int dy); +void SetFixes(void); + +void PaintPicDot(u8 * p,u8 c); +//void DrawNumBorPic(u8 *pMem, int lSelectedSlot); +void ResizeWindow(); + +//////////////////////////////////////////////////////////////////////////// +#ifdef __cplusplus +} +#endif + + +#endif // _GPU_INTERNALS_H diff --git a/plugins/gpu-gles/gpuPrim.c b/plugins/gpu-gles/gpuPrim.c new file mode 100644 index 00000000..9b718a5f --- /dev/null +++ b/plugins/gpu-gles/gpuPrim.c @@ -0,0 +1,5022 @@ +/*************************************************************************** + prim.c - description + ------------------- + begin : Sun Mar 08 2009 + copyright : (C) 1999-2009 by Pete Bernert + web : www.pbernert.com + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2009/03/08 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +#define _IN_PRIMDRAW + +#ifdef _WINDOWS +#include "stdafx.h" +#include "externals.h" +#include "gpu.h" +#include "draw.h" +#include "texture.h" +#else +#include "gpuStdafx.h" +#include "gpuExternals.h" +#include "gpuPlugin.h" +#include "gpuDraw.h" +#include "gpuTexture.h" +#include "gpuPrim.h" + +#endif + +//////////////////////////////////////////////////////////////////////// +// defines +//////////////////////////////////////////////////////////////////////// + +#define DEFOPAQUEON glAlphaFunc(GL_EQUAL,0.0f);bBlendEnable=FALSE;glDisable(GL_BLEND); +#define DEFOPAQUEOFF glAlphaFunc(GL_GREATER,0.49f); +#define fpoint(x) x +//////////////////////////////////////////////////////////////////////// +// globals +//////////////////////////////////////////////////////////////////////// + +#ifndef _WINDOWS +EGLSurface surface; +EGLDisplay display; +#endif + +BOOL bDrawTextured; // current active drawing states +BOOL bDrawSmoothShaded; +BOOL bOldSmoothShaded; +BOOL bDrawNonShaded; +BOOL bDrawMultiPass; +int iOffscreenDrawing; +int iDrawnSomething=0; + +BOOL bRenderFrontBuffer=FALSE; // flag for front buffer rendering + +GLubyte ubGloAlpha; // texture alpha +GLubyte ubGloColAlpha; // color alpha +int iFilterType; // type of filter +BOOL bFullVRam=FALSE; // sign for tex win +BOOL bDrawDither; // sign for dither +BOOL bUseMultiPass; // sign for multi pass +GLuint gTexName; // binded texture +BOOL bTexEnabled; // texture enable flag +BOOL bBlendEnable; // blend enable flag +PSXRect_t xrUploadArea; // rect to upload +PSXRect_t xrUploadAreaIL; // rect to upload +PSXRect_t xrUploadAreaRGB24; // rect to upload rgb24 +int iSpriteTex=0; // flag for "hey, it's a sprite" +unsigned short usMirror; // mirror, mirror on the wall + +BOOL bNeedUploadAfter=FALSE; // sign for uploading in next frame +BOOL bNeedUploadTest=FALSE; // sign for upload test +BOOL bUsingTWin=FALSE; // tex win active flag +BOOL bUsingMovie=FALSE; // movie active flag +PSXRect_t xrMovieArea; // rect for movie upload +short sSprite_ux2; // needed for sprire adjust +short sSprite_vy2; // +unsigned long ulOLDCOL=0; // active color +unsigned long ulClutID; // clut + +unsigned long dwCfgFixes; // game fixes +unsigned long dwActFixes=0; +unsigned long dwEmuFixes=0; +BOOL bUseFixes; + +long drawX,drawY,drawW,drawH; // offscreen drawing checkers +short sxmin,sxmax,symin,symax; + +//////////////////////////////////////////////////////////////////////// +// Update global TP infos +//////////////////////////////////////////////////////////////////////// + +void UpdateGlobalTP(unsigned short gdata) +{ + GlobalTextAddrX = (gdata << 6) & 0x3c0; + + if(iGPUHeight==1024) // ZN mode + { + if(dwGPUVersion==2) // very special zn gpu + { + GlobalTextAddrY =((gdata & 0x60 ) << 3); + GlobalTextIL =(gdata & 0x2000) >> 13; + GlobalTextABR = (unsigned short)((gdata >> 7) & 0x3); + GlobalTextTP = (gdata >> 9) & 0x3; + if(GlobalTextTP==3) GlobalTextTP=2; + GlobalTexturePage = (GlobalTextAddrX>>6)+(GlobalTextAddrY>>4); + usMirror =0; + STATUSREG = (STATUSREG & 0xffffe000 ) | (gdata & 0x1fff ); + return; + } + else // "enhanced" psx gpu + { + GlobalTextAddrY = (unsigned short)(((gdata << 4) & 0x100) | ((gdata >> 2) & 0x200)); + } + } + else GlobalTextAddrY = (gdata << 4) & 0x100; // "normal" psx gpu + + usMirror=gdata&0x3000; + + GlobalTextTP = (gdata >> 7) & 0x3; // tex mode (4,8,15) + if(GlobalTextTP==3) GlobalTextTP=2; // seen in Wild9 :( + GlobalTextABR = (gdata >> 5) & 0x3; // blend mode + + GlobalTexturePage = (GlobalTextAddrX>>6)+(GlobalTextAddrY>>4); + + STATUSREG&=~0x07ff; // Clear the necessary bits + STATUSREG|=(gdata & 0x07ff); // set the necessary bits +} + +//////////////////////////////////////////////////////////////////////// +// Some ASM color convertion... Lewpy's special... +//////////////////////////////////////////////////////////////////////// + +#ifdef _WINDOWS +#pragma warning (disable : 4035) + +unsigned long DoubleBGR2RGB (unsigned long BGR) +{ + + __asm + { + mov eax, BGR /* this can hold the G value */ + mov ebx, eax /* this can hold the R value */ + mov edx, eax /* this can hold the B value */ + and ebx, 000000ffh /* mask the R value */ + shl ebx, 1 + test ebx, 00000100h + jz RSKIP + mov ebx, 000000ffh + +RSKIP: + and eax, 0000ff00h /* mask the G value */ + shl eax, 1 + test eax, 00010000h + jz GSKIP + mov eax, 0000ff00h + +GSKIP: + and edx, 00ff0000h /* mask the B value */ + shl edx, 1 + test edx, 01000000h + jz BSKIP + mov edx, 00ff0000h + +BSKIP: + or eax, ebx /* add R to G value */ + or eax, edx /* add B to RG value */ + } + /* Result returned in EAX */ +} + +unsigned short BGR24to16 (unsigned long BGR) +{ + __asm + { + mov eax, BGR /* this can hold the G value */ + mov ebx, eax /* this can hold the R value */ + mov edx, eax /* this can hold the B value */ + shr ebx, 3 /* move the R value */ + and edx, 00f80000h /* mask the B value */ + shr edx, 9 /* move the B value */ + and eax, 00f800h /* mask the G value */ + shr eax, 6 /* move the G value */ + and ebx, 0000001fh /* mask the R value */ + or eax, ebx /* add R to G value */ + or eax, edx /* add B to RG value */ + } + /* Result returned in AX */ +} + +#pragma warning (default : 4035) + +#else + +unsigned long DoubleBGR2RGB (unsigned long BGR) +{ + unsigned long ebx,eax,edx; + + ebx=(BGR&0x000000ff)<<1; + if(ebx&0x00000100) ebx=0x000000ff; + + eax=(BGR&0x0000ff00)<<1; + if(eax&0x00010000) eax=0x0000ff00; + + edx=(BGR&0x00ff0000)<<1; + if(edx&0x01000000) edx=0x00ff0000; + + return (ebx|eax|edx); +} + +unsigned short BGR24to16 (unsigned long BGR) +{ + return ((BGR>>3)&0x1f)|((BGR&0xf80000)>>9)|((BGR&0xf800)>>6); +} + +#endif + +//////////////////////////////////////////////////////////////////////// +// OpenGL primitive drawing commands +//////////////////////////////////////////////////////////////////////// + +__inline void PRIMdrawTexturedQuad(OGLVertex* vertex1, OGLVertex* vertex2, + OGLVertex* vertex3, OGLVertex* vertex4) +{ + + +Vertex v[4]; + +v[0].xyz.x = fpoint(vertex1->x); +v[0].xyz.y = fpoint(vertex1->y); +v[0].xyz.z = fpoint(vertex1->z); +v[0].st.x = fpoint(vertex1->sow); +v[0].st.y = fpoint(vertex1->tow); + +v[1].xyz.x = fpoint(vertex2->x); +v[1].xyz.y = fpoint(vertex2->y); +v[1].xyz.z = fpoint(vertex2->z); +v[1].st.x = fpoint(vertex2->sow); +v[1].st.y = fpoint(vertex2->tow); + +v[2].xyz.x = fpoint(vertex4->x); +v[2].xyz.y = fpoint(vertex4->y); +v[2].xyz.z = fpoint(vertex4->z); +v[2].st.x = fpoint(vertex4->sow); +v[2].st.y = fpoint(vertex4->tow); + +v[3].xyz.x = fpoint(vertex3->x); +v[3].xyz.y = fpoint(vertex3->y); +v[3].xyz.z = fpoint(vertex3->z); +v[3].st.x = fpoint(vertex3->sow); +v[3].st.y = fpoint(vertex3->tow); + +glEnableClientState(GL_TEXTURE_COORD_ARRAY); +glEnableClientState(GL_VERTEX_ARRAY); +glTexCoordPointer(2, GL_FLOAT, sizeof(v[0]), &v[0].st); +glVertexPointer(3, GL_FLOAT, sizeof(v[0]), &v[0].xyz); +glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); +glDisableClientState(GL_TEXTURE_COORD_ARRAY); +glDisableClientState(GL_VERTEX_ARRAY); +} + +///////////////////////////////////////////////////////// + +__inline void PRIMdrawTexturedTri(OGLVertex* vertex1, OGLVertex* vertex2, + OGLVertex* vertex3) +{ +Vertex v[3]; + +v[0].xyz.x = fpoint(vertex1->x); +v[0].xyz.y = fpoint(vertex1->y); +v[0].xyz.z = fpoint(vertex1->z); +v[0].st.x = fpoint(vertex1->sow); +v[0].st.y = fpoint(vertex1->tow); + +v[1].xyz.x = fpoint(vertex2->x); +v[1].xyz.y = fpoint(vertex2->y); +v[1].xyz.z = fpoint(vertex2->z); +v[1].st.x = fpoint(vertex2->sow); +v[1].st.y = fpoint(vertex2->tow); + +v[2].xyz.x = fpoint(vertex3->x); +v[2].xyz.y = fpoint(vertex3->y); +v[2].xyz.z = fpoint(vertex3->z); +v[2].st.x = fpoint(vertex3->sow); +v[2].st.y = fpoint(vertex3->tow); + +glEnableClientState(GL_TEXTURE_COORD_ARRAY); +glEnableClientState(GL_VERTEX_ARRAY); +glTexCoordPointer(2, GL_FLOAT, sizeof(v[0]), &v[0].st); +glVertexPointer(3, GL_FLOAT, sizeof(v[0]), &v[0].xyz); +glDrawArrays(GL_TRIANGLES, 0, 3); +glDisableClientState(GL_TEXTURE_COORD_ARRAY); +glDisableClientState(GL_VERTEX_ARRAY); + +} + +///////////////////////////////////////////////////////// + +__inline void PRIMdrawTexGouraudTriColor(OGLVertex* vertex1, OGLVertex* vertex2, + OGLVertex* vertex3) +{ + +Vertex2 v[3]; + +v[0].xyz.x = fpoint(vertex1->x); +v[0].xyz.y = fpoint(vertex1->y); +v[0].xyz.z = fpoint(vertex1->z); +v[0].st.x = fpoint(vertex1->sow); +v[0].st.y = fpoint(vertex1->tow); +v[0].rgba.r = vertex1->c.col[0]; +v[0].rgba.g = vertex1->c.col[1]; +v[0].rgba.b = vertex1->c.col[2]; +v[0].rgba.a = vertex1->c.col[3]; + +v[1].xyz.x = fpoint(vertex2->x); +v[1].xyz.y = fpoint(vertex2->y); +v[1].xyz.z = fpoint(vertex2->z); +v[1].st.x = fpoint(vertex2->sow); +v[1].st.y = fpoint(vertex2->tow); +v[1].rgba.r = vertex2->c.col[0]; +v[1].rgba.g = vertex2->c.col[1]; +v[1].rgba.b = vertex2->c.col[2]; +v[1].rgba.a = vertex2->c.col[3]; + +v[2].xyz.x = fpoint(vertex3->x); +v[2].xyz.y = fpoint(vertex3->y); +v[2].xyz.z = fpoint(vertex3->z); +v[2].st.x = fpoint(vertex3->sow); +v[2].st.y = fpoint(vertex3->tow); +v[2].rgba.r = vertex3->c.col[0]; +v[2].rgba.g = vertex3->c.col[1]; +v[2].rgba.b = vertex3->c.col[2]; +v[2].rgba.a = vertex3->c.col[3]; + +glEnableClientState(GL_TEXTURE_COORD_ARRAY); +glEnableClientState(GL_VERTEX_ARRAY); +glEnableClientState(GL_COLOR_ARRAY); + +glTexCoordPointer(2, GL_FLOAT, sizeof(v[0]), &v[0].st); +glVertexPointer(3, GL_FLOAT, sizeof(v[0]), &v[0].xyz); +glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(v[0]), &v[0].rgba); + +glDrawArrays(GL_TRIANGLES, 0, 3); +glDisableClientState(GL_TEXTURE_COORD_ARRAY); +glDisableClientState(GL_VERTEX_ARRAY); +glDisableClientState(GL_COLOR_ARRAY); +} + +///////////////////////////////////////////////////////// + +__inline void PRIMdrawTexGouraudTriColorQuad(OGLVertex* vertex1, OGLVertex* vertex2, + OGLVertex* vertex3, OGLVertex* vertex4) +{ +Vertex2 v[4]; + +v[0].xyz.x = fpoint(vertex1->x); +v[0].xyz.y = fpoint(vertex1->y); +v[0].xyz.z = fpoint(vertex1->z); +v[0].st.x = fpoint(vertex1->sow); +v[0].st.y = fpoint(vertex1->tow); +v[0].rgba.r = vertex1->c.col[0]; +v[0].rgba.g = vertex1->c.col[1]; +v[0].rgba.b = vertex1->c.col[2]; +v[0].rgba.a = vertex1->c.col[3]; + +v[1].xyz.x = fpoint(vertex2->x); +v[1].xyz.y = fpoint(vertex2->y); +v[1].xyz.z = fpoint(vertex2->z); +v[1].st.x = fpoint(vertex2->sow); +v[1].st.y = fpoint(vertex2->tow); +v[1].rgba.r = vertex2->c.col[0]; +v[1].rgba.g = vertex2->c.col[1]; +v[1].rgba.b = vertex2->c.col[2]; +v[1].rgba.a = vertex2->c.col[3]; + +v[2].xyz.x = fpoint(vertex4->x); +v[2].xyz.y = fpoint(vertex4->y); +v[2].xyz.z = fpoint(vertex4->z); +v[2].st.x = fpoint(vertex4->sow); +v[2].st.y = fpoint(vertex4->tow); +v[2].rgba.r = vertex4->c.col[0]; +v[2].rgba.g = vertex4->c.col[1]; +v[2].rgba.b = vertex4->c.col[2]; +v[2].rgba.a = vertex4->c.col[3]; + +v[3].xyz.x = fpoint(vertex3->x); +v[3].xyz.y = fpoint(vertex3->y); +v[3].xyz.z = fpoint(vertex3->z); +v[3].st.x = fpoint(vertex3->sow); +v[3].st.y = fpoint(vertex3->tow); +v[3].rgba.r = vertex3->c.col[0]; +v[3].rgba.g = vertex3->c.col[1]; +v[3].rgba.b = vertex3->c.col[2]; +v[3].rgba.a = vertex3->c.col[3]; + +glEnableClientState(GL_TEXTURE_COORD_ARRAY); +glEnableClientState(GL_VERTEX_ARRAY); +glEnableClientState(GL_COLOR_ARRAY); + +glTexCoordPointer(2, GL_FLOAT, sizeof(v[0]), &v[0].st); +glVertexPointer(3, GL_FLOAT, sizeof(v[0]), &v[0].xyz); +glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(v[0]), &v[0].rgba); + +glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); +glDisableClientState(GL_TEXTURE_COORD_ARRAY); +glDisableClientState(GL_VERTEX_ARRAY); +glDisableClientState(GL_COLOR_ARRAY); +} + +///////////////////////////////////////////////////////// + +__inline void PRIMdrawTri(OGLVertex* vertex1, OGLVertex* vertex2, OGLVertex* vertex3) +{ +Vec3f v[3]; + +v[0].x = fpoint(vertex1->x); +v[0].y = fpoint(vertex1->y); +v[0].z = fpoint(vertex1->z); + +v[1].x = fpoint(vertex2->x); +v[1].y = fpoint(vertex2->y); +v[1].z = fpoint(vertex2->z); + +v[2].x = fpoint(vertex3->x); +v[2].y = fpoint(vertex3->y); +v[2].z = fpoint(vertex3->z); + +glEnableClientState(GL_VERTEX_ARRAY); +glVertexPointer(3, GL_FLOAT, sizeof(v[0]), &v[0]); +glDrawArrays(GL_TRIANGLES, 0, 3); +glDisableClientState(GL_VERTEX_ARRAY); +} + +///////////////////////////////////////////////////////// + +__inline void PRIMdrawTri2(OGLVertex* vertex1, OGLVertex* vertex2, + OGLVertex* vertex3, OGLVertex* vertex4) +{ +Vec3f v[4]; + +v[0].x = fpoint(vertex1->x); +v[0].y = fpoint(vertex1->y); +v[0].z = fpoint(vertex1->z); + +v[1].x = fpoint(vertex3->x); +v[1].y = fpoint(vertex3->y); +v[1].z = fpoint(vertex3->z); + +v[2].x = fpoint(vertex2->x); +v[2].y = fpoint(vertex2->y); +v[2].z = fpoint(vertex2->z); + +v[3].x = fpoint(vertex4->x); +v[3].y = fpoint(vertex4->y); +v[3].z = fpoint(vertex4->z); + +glEnableClientState(GL_VERTEX_ARRAY); +glVertexPointer(3, GL_FLOAT, sizeof(v[0]), &v[0]); +glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); +glDisableClientState(GL_VERTEX_ARRAY); +} + +///////////////////////////////////////////////////////// + +__inline void PRIMdrawGouraudTriColor(OGLVertex* vertex1, OGLVertex* vertex2, + OGLVertex* vertex3) +{ +Vertex2 v[3]; + +v[0].xyz.x = fpoint(vertex1->x); +v[0].xyz.y = fpoint(vertex1->y); +v[0].xyz.z = fpoint(vertex1->z); +v[0].rgba.r = vertex1->c.col[0]; +v[0].rgba.g = vertex1->c.col[1]; +v[0].rgba.b = vertex1->c.col[2]; +v[0].rgba.a = vertex1->c.col[3]; + +v[1].xyz.x = fpoint(vertex2->x); +v[1].xyz.y = fpoint(vertex2->y); +v[1].xyz.z = fpoint(vertex2->z); +v[1].rgba.r = vertex2->c.col[0]; +v[1].rgba.g = vertex2->c.col[1]; +v[1].rgba.b = vertex2->c.col[2]; +v[1].rgba.a = vertex2->c.col[3]; + +v[2].xyz.x = fpoint(vertex3->x); +v[2].xyz.y = fpoint(vertex3->y); +v[2].xyz.z = fpoint(vertex3->z); +v[2].rgba.r = vertex3->c.col[0]; +v[2].rgba.g = vertex3->c.col[1]; +v[2].rgba.b = vertex3->c.col[2]; +v[2].rgba.a = vertex3->c.col[3]; + +glEnableClientState(GL_VERTEX_ARRAY); +glEnableClientState(GL_COLOR_ARRAY); + +glVertexPointer(3, GL_FLOAT, sizeof(v[0]), &v[0].xyz); +glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(v[0]), &v[0].rgba); + +glDrawArrays(GL_TRIANGLES, 0, 3); +glDisableClientState(GL_VERTEX_ARRAY); +glDisableClientState(GL_COLOR_ARRAY); +} + +///////////////////////////////////////////////////////// + +__inline void PRIMdrawGouraudTri2Color(OGLVertex* vertex1, OGLVertex* vertex2, + OGLVertex* vertex3, OGLVertex* vertex4) +{ +Vertex2 v[4]; + +v[0].xyz.x = fpoint(vertex1->x); +v[0].xyz.y = fpoint(vertex1->y); +v[0].xyz.z = fpoint(vertex1->z); +v[0].rgba.r = vertex1->c.col[0]; +v[0].rgba.g = vertex1->c.col[1]; +v[0].rgba.b = vertex1->c.col[2]; +v[0].rgba.a = vertex1->c.col[3]; + +v[1].xyz.x = fpoint(vertex2->x); +v[1].xyz.y = fpoint(vertex2->y); +v[1].xyz.z = fpoint(vertex2->z); +v[1].rgba.r = vertex2->c.col[0]; +v[1].rgba.g = vertex2->c.col[1]; +v[1].rgba.b = vertex2->c.col[2]; +v[1].rgba.a = vertex2->c.col[3]; + +v[2].xyz.x = fpoint(vertex3->x); +v[2].xyz.y = fpoint(vertex3->y); +v[2].xyz.z = fpoint(vertex3->z); +v[2].rgba.r = vertex3->c.col[0]; +v[2].rgba.g = vertex3->c.col[1]; +v[2].rgba.b = vertex3->c.col[2]; +v[2].rgba.a = vertex3->c.col[3]; + +v[3].xyz.x = fpoint(vertex4->x); +v[3].xyz.y = fpoint(vertex4->y); +v[3].xyz.z = fpoint(vertex4->z); +v[3].rgba.r = vertex4->c.col[0]; +v[3].rgba.g = vertex4->c.col[1]; +v[3].rgba.b = vertex4->c.col[2]; +v[3].rgba.a = vertex4->c.col[3]; + +glEnableClientState(GL_VERTEX_ARRAY); +glEnableClientState(GL_COLOR_ARRAY); + +glVertexPointer(3, GL_FLOAT, sizeof(v[0]), &v[0].xyz); +glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(v[0]), &v[0].rgba); + +glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); +glDisableClientState(GL_VERTEX_ARRAY); +glDisableClientState(GL_COLOR_ARRAY); +} + +///////////////////////////////////////////////////////// + +__inline void PRIMdrawFlatLine(OGLVertex* vertex1, OGLVertex* vertex2,OGLVertex* vertex3, OGLVertex* vertex4) +{ +Vertex2 v[4]; + +v[0].xyz.x = fpoint(vertex1->x); +v[0].xyz.y = fpoint(vertex1->y); +v[0].xyz.z = fpoint(vertex1->z); +v[0].rgba.r = vertex1->c.col[0]; +v[0].rgba.g = vertex1->c.col[1]; +v[0].rgba.b = vertex1->c.col[2]; +v[0].rgba.a = vertex1->c.col[3]; + +v[1].xyz.x = fpoint(vertex2->x); +v[1].xyz.y = fpoint(vertex2->y); +v[1].xyz.z = fpoint(vertex2->z); +v[1].rgba.r = vertex1->c.col[0]; +v[1].rgba.g = vertex1->c.col[1]; +v[1].rgba.b = vertex1->c.col[2]; +v[1].rgba.a = vertex1->c.col[3]; + +v[2].xyz.x = fpoint(vertex4->x); +v[2].xyz.y = fpoint(vertex4->y); +v[2].xyz.z = fpoint(vertex4->z); +v[2].rgba.r = vertex1->c.col[0]; +v[2].rgba.g = vertex1->c.col[1]; +v[2].rgba.b = vertex1->c.col[2]; +v[2].rgba.a = vertex1->c.col[3]; + +v[3].xyz.x = fpoint(vertex3->x); +v[3].xyz.y = fpoint(vertex3->y); +v[3].xyz.z = fpoint(vertex3->z); +v[3].rgba.r = vertex1->c.col[0]; +v[3].rgba.g = vertex1->c.col[1]; +v[3].rgba.b = vertex1->c.col[2]; +v[3].rgba.a = vertex1->c.col[3]; + +glEnableClientState(GL_VERTEX_ARRAY); +glEnableClientState(GL_COLOR_ARRAY); + +glVertexPointer(3, GL_FLOAT, sizeof(v[0]), &v[0].xyz); +glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(v[0]), &v[0].rgba); + +glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); +glDisableClientState(GL_VERTEX_ARRAY); +glDisableClientState(GL_COLOR_ARRAY); + + +} + +///////////////////////////////////////////////////////// + +__inline void PRIMdrawGouraudLine(OGLVertex* vertex1, OGLVertex* vertex2,OGLVertex* vertex3, OGLVertex* vertex4) +{ + Vertex2 v[4]; + +v[0].xyz.x = fpoint(vertex1->x); +v[0].xyz.y = fpoint(vertex1->y); +v[0].xyz.z = fpoint(vertex1->z); +v[0].rgba.r = vertex1->c.col[0]; +v[0].rgba.g = vertex1->c.col[1]; +v[0].rgba.b = vertex1->c.col[2]; +v[0].rgba.a = vertex1->c.col[3]; + +v[1].xyz.x = fpoint(vertex2->x); +v[1].xyz.y = fpoint(vertex2->y); +v[1].xyz.z = fpoint(vertex2->z); +v[1].rgba.r = vertex2->c.col[0]; +v[1].rgba.g = vertex2->c.col[1]; +v[1].rgba.b = vertex2->c.col[2]; +v[1].rgba.a = vertex2->c.col[3]; + +v[3].xyz.x = fpoint(vertex3->x); +v[3].xyz.y = fpoint(vertex3->y); +v[3].xyz.z = fpoint(vertex3->z); +v[3].rgba.r = vertex3->c.col[0]; +v[3].rgba.g = vertex3->c.col[1]; +v[3].rgba.b = vertex3->c.col[2]; +v[3].rgba.a = vertex3->c.col[3]; + +v[2].xyz.x = fpoint(vertex4->x); +v[2].xyz.y = fpoint(vertex4->y); +v[2].xyz.z = fpoint(vertex4->z); +v[2].rgba.r = vertex4->c.col[0]; +v[2].rgba.g = vertex4->c.col[1]; +v[2].rgba.b = vertex4->c.col[2]; +v[2].rgba.a = vertex4->c.col[3]; + +glEnableClientState(GL_VERTEX_ARRAY); +glEnableClientState(GL_COLOR_ARRAY); + +glVertexPointer(3, GL_FLOAT, sizeof(v[0]), &v[0].xyz); +glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(v[0]), &v[0].rgba); + +glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); +glDisableClientState(GL_VERTEX_ARRAY); +glDisableClientState(GL_COLOR_ARRAY); +} + +///////////////////////////////////////////////////////// + +__inline void PRIMdrawQuad(OGLVertex* vertex1, OGLVertex* vertex2, + OGLVertex* vertex3, OGLVertex* vertex4) +{ +Vec3f v[4]; + +v[0].x = fpoint(vertex1->x); +v[0].y = fpoint(vertex1->y); +v[0].z = fpoint(vertex1->z); + +v[1].x = fpoint(vertex2->x); +v[1].y = fpoint(vertex2->y); +v[1].z = fpoint(vertex2->z); + +v[2].x = fpoint(vertex4->x); +v[2].y = fpoint(vertex4->y); +v[2].z = fpoint(vertex4->z); + +v[3].x = fpoint(vertex3->x); +v[3].y = fpoint(vertex3->y); +v[3].z = fpoint(vertex3->z); + +glEnableClientState(GL_VERTEX_ARRAY); +glVertexPointer(3, GL_FLOAT, sizeof(v[0]), &v[0]); +glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); +glDisableClientState(GL_VERTEX_ARRAY); +} + +//////////////////////////////////////////////////////////////////////// +// Transparent blending settings +//////////////////////////////////////////////////////////////////////// + +static GLenum obm1=GL_ZERO; +static GLenum obm2=GL_ZERO; + +typedef struct SEMITRANSTAG +{ + GLenum srcFac; + GLenum dstFac; + GLubyte alpha; +} SemiTransParams; + +SemiTransParams TransSets[4]= +{ + {GL_SRC_ALPHA,GL_SRC_ALPHA, 127}, + {GL_ONE, GL_ONE, 255}, + {GL_ZERO, GL_ONE_MINUS_SRC_COLOR,255}, + {GL_ONE_MINUS_SRC_ALPHA,GL_ONE, 192} +}; + +//////////////////////////////////////////////////////////////////////// + +void SetSemiTrans(void) +{ +/* +* 0.5 x B + 0.5 x F +* 1.0 x B + 1.0 x F +* 1.0 x B - 1.0 x F +* 1.0 x B +0.25 x F +*/ + + if(!DrawSemiTrans) // no semi trans at all? + { + if(bBlendEnable) + {glDisable(GL_BLEND);bBlendEnable=FALSE;} // -> don't wanna blend + ubGloAlpha=ubGloColAlpha=255; // -> full alpha + return; // -> and bye + } + + ubGloAlpha=ubGloColAlpha=TransSets[GlobalTextABR].alpha; + + if(!bBlendEnable) + {glEnable(GL_BLEND);bBlendEnable=TRUE;} // wanna blend + + if(TransSets[GlobalTextABR].srcFac!=obm1 || + TransSets[GlobalTextABR].dstFac!=obm2) + { + //if(glBlendEquationEXTEx==NULL) + { + obm1=TransSets[GlobalTextABR].srcFac; + obm2=TransSets[GlobalTextABR].dstFac; + glBlendFunc(obm1,obm2); // set blend func + } + /*else + if(TransSets[GlobalTextABR].dstFac !=GL_ONE_MINUS_SRC_COLOR) + { + if(obm2==GL_ONE_MINUS_SRC_COLOR) + glBlendEquationEXTEx(FUNC_ADD_EXT); + obm1=TransSets[GlobalTextABR].srcFac; + obm2=TransSets[GlobalTextABR].dstFac; + glBlendFunc(obm1,obm2); // set blend func + } + else + { + glBlendEquationEXTEx(FUNC_REVERSESUBTRACT_EXT); + obm1=TransSets[GlobalTextABR].srcFac; + obm2=TransSets[GlobalTextABR].dstFac; + glBlendFunc(GL_ONE,GL_ONE); // set blend func + }*/ + } +} + +void SetScanTrans(void) // blending for scan lines +{ +/* if(glBlendEquationEXTEx!=NULL) + { + if(obm2==GL_ONE_MINUS_SRC_COLOR) + glBlendEquationEXTEx(FUNC_ADD_EXT); + } +*/ + obm1=TransSets[0].srcFac; + obm2=TransSets[0].dstFac; + glBlendFunc(obm1,obm2); // set blend func +} + +void SetScanTexTrans(void) // blending for scan mask texture +{ +/* if(glBlendEquationEXTEx!=NULL) + { + if(obm2==GL_ONE_MINUS_SRC_COLOR) + glBlendEquationEXTEx(FUNC_ADD_EXT); + } +*/ + obm1=TransSets[2].srcFac; + obm2=TransSets[2].dstFac; + glBlendFunc(obm1,obm2); // set blend func +} + +//////////////////////////////////////////////////////////////////////// +// multi pass in old 'Advanced blending' mode... got it from Lewpy :) +//////////////////////////////////////////////////////////////////////// + +SemiTransParams MultiTexTransSets[4][2]= +{ + { + {GL_ONE ,GL_SRC_ALPHA, 127}, + {GL_SRC_ALPHA,GL_ONE, 127} + }, + { + {GL_ONE, GL_SRC_ALPHA, 255}, + {GL_SRC_ALPHA,GL_ONE, 255} + }, + { + {GL_ZERO, GL_ONE_MINUS_SRC_COLOR,255}, + {GL_ZERO, GL_ONE_MINUS_SRC_COLOR,255} + }, + { + {GL_SRC_ALPHA,GL_ONE, 127}, + {GL_ONE_MINUS_SRC_ALPHA,GL_ONE, 255} + } +}; + +//////////////////////////////////////////////////////////////////////// + +SemiTransParams MultiColTransSets[4]= +{ + {GL_ONE_MINUS_SRC_ALPHA,GL_SRC_ALPHA,127}, + {GL_ONE, GL_ONE, 255}, + {GL_ZERO, GL_ONE_MINUS_SRC_COLOR,255}, + {GL_SRC_ALPHA,GL_ONE, 127} +}; + +//////////////////////////////////////////////////////////////////////// + +void SetSemiTransMulti(int Pass) +{ + static GLenum bm1=GL_ZERO; + static GLenum bm2=GL_ONE; + + ubGloAlpha=255; + ubGloColAlpha=255; + + // are we enabling SemiTransparent mode? + if(DrawSemiTrans) + { + if(bDrawTextured) + { + bm1=MultiTexTransSets[GlobalTextABR][Pass].srcFac; + bm2=MultiTexTransSets[GlobalTextABR][Pass].dstFac; + ubGloAlpha=MultiTexTransSets[GlobalTextABR][Pass].alpha; + } + // no texture + else + { + bm1=MultiColTransSets[GlobalTextABR].srcFac; + bm2=MultiColTransSets[GlobalTextABR].dstFac; + ubGloColAlpha=MultiColTransSets[GlobalTextABR].alpha; + } + } + // no shading + else + { + if(Pass==0) + { + // disable blending + bm1=GL_ONE;bm2=GL_ZERO; + } + else + { + // disable blending, but add src col a second time + bm1=GL_ONE;bm2=GL_ONE; + } + } + + if(!bBlendEnable) + {glEnable(GL_BLEND);bBlendEnable=TRUE;} // wanna blend + + if(bm1!=obm1 || bm2!=obm2) + { + glBlendFunc(bm1,bm2); // set blend func + obm1=bm1;obm2=bm2; + } +} + +//////////////////////////////////////////////////////////////////////// +// Set several rendering stuff including blending +//////////////////////////////////////////////////////////////////////// + +__inline void SetZMask3O(void) +{ + if(iUseMask && DrawSemiTrans && !iSetMask) + { + vertex[0].z=vertex[1].z=vertex[2].z=gl_z; + gl_z+=0.00004f; + } +} + +__inline void SetZMask3(void) +{ + if(iUseMask) + { + if(iSetMask || DrawSemiTrans) + {vertex[0].z=vertex[1].z=vertex[2].z=0.95f;} + else + { + vertex[0].z=vertex[1].z=vertex[2].z=gl_z; + gl_z+=0.00004f; + } + } +} + +__inline void SetZMask3NT(void) +{ + if(iUseMask) + { + if(iSetMask) + {vertex[0].z=vertex[1].z=vertex[2].z=0.95f;} + else + { + vertex[0].z=vertex[1].z=vertex[2].z=gl_z; + gl_z+=0.00004f; + } + } +} + +//////////////////////////////////////////////////////////////////////// + +__inline void SetZMask4O(void) +{ + if(iUseMask && DrawSemiTrans && !iSetMask) + { + vertex[0].z=vertex[1].z=vertex[2].z=vertex[3].z=gl_z; + gl_z+=0.00004f; + } +} + +__inline void SetZMask4(void) +{ + if(iUseMask) + { + if(iSetMask || DrawSemiTrans) + {vertex[0].z=vertex[1].z=vertex[2].z=vertex[3].z=0.95f;} + else + { + vertex[0].z=vertex[1].z=vertex[2].z=vertex[3].z=gl_z; + gl_z+=0.00004f; + } + } +} + +__inline void SetZMask4NT(void) +{ + if(iUseMask) + { + if(iSetMask==1) + {vertex[0].z=vertex[1].z=vertex[2].z=vertex[3].z=0.95f;} + else + { + vertex[0].z=vertex[1].z=vertex[2].z=vertex[3].z=gl_z; + gl_z+=0.00004f; + } + } +} + +__inline void SetZMask4SP(void) +{ + if(iUseMask) + { + if(iSetMask==1) + {vertex[0].z=vertex[1].z=vertex[2].z=vertex[3].z=0.95f;} + else + { + if(bCheckMask) + { + vertex[0].z=vertex[1].z=vertex[2].z=vertex[3].z=gl_z; + gl_z+=0.00004f; + } + else + {vertex[0].z=vertex[1].z=vertex[2].z=vertex[3].z=0.95f;} + } + } +} + +//////////////////////////////////////////////////////////////////////// + +__inline void SetRenderState(unsigned long DrawAttributes) +{ + bDrawNonShaded = (SHADETEXBIT(DrawAttributes)) ? TRUE : FALSE; + DrawSemiTrans = (SEMITRANSBIT(DrawAttributes)) ? TRUE : FALSE; +} + +//////////////////////////////////////////////////////////////////////// + +__inline void SetRenderColor(unsigned long DrawAttributes) +{ + if(bDrawNonShaded) {g_m1=g_m2=g_m3=128;} + else + { + g_m1=DrawAttributes&0xff; + g_m2=(DrawAttributes>>8)&0xff; + g_m3=(DrawAttributes>>16)&0xff; + } +} + +//////////////////////////////////////////////////////////////////////// + +void SetRenderMode(unsigned long DrawAttributes,BOOL bSCol) +{ + if((bUseMultiPass) && (bDrawTextured) && !(bDrawNonShaded)) + {bDrawMultiPass = TRUE; SetSemiTransMulti(0);} + else {bDrawMultiPass = FALSE;SetSemiTrans();} + + if(bDrawTextured) // texture ? build it/get it from cache + { + GLuint currTex; + if(bUsingTWin) currTex=LoadTextureWnd(GlobalTexturePage,GlobalTextTP, ulClutID); + else if(bUsingMovie) currTex=LoadTextureMovie(); + else currTex=SelectSubTextureS(GlobalTextTP,ulClutID); + + if(gTexName!=currTex) + {gTexName=currTex;glBindTexture(GL_TEXTURE_2D,currTex);} + + if(!bTexEnabled) // -> turn texturing on + {bTexEnabled=TRUE;glEnable(GL_TEXTURE_2D);} + } + else // no texture ? + if(bTexEnabled) + {bTexEnabled=FALSE;glDisable(GL_TEXTURE_2D);} // -> turn texturing off + + if(bSCol) // also set color ? + { + if((dwActFixes&4) && ((DrawAttributes&0x00ffffff)==0)) + DrawAttributes|=0x007f7f7f; + + if(bDrawNonShaded) // -> non shaded? + { +/* if(bGLBlend) vertex[0].c.lcol=0x7f7f7f; // --> solid color... + else */vertex[0].c.lcol=0xffffff; + } + else // -> shaded? + { +// if(!bUseMultiPass && !bGLBlend) // --> given color... + vertex[0].c.lcol=DoubleBGR2RGB(DrawAttributes); +// else vertex[0].c.lcol=DrawAttributes; + } + vertex[0].c.col[3]=ubGloAlpha; // -> set color with + SETCOL(vertex[0]); // texture alpha + } + + if(bDrawSmoothShaded!=bOldSmoothShaded) // shading changed? + { + if(bDrawSmoothShaded) glShadeModel(GL_SMOOTH); // -> set actual shading + else glShadeModel(GL_FLAT); + bOldSmoothShaded=bDrawSmoothShaded; + } +} + +//////////////////////////////////////////////////////////////////////// +// Set Opaque multipass color +//////////////////////////////////////////////////////////////////////// + +void SetOpaqueColor(unsigned long DrawAttributes) +{ + if(bDrawNonShaded) return; // no shading? bye + + DrawAttributes=DoubleBGR2RGB(DrawAttributes); // multipass is just half color, so double it on opaque pass + vertex[0].c.lcol=DrawAttributes|0xff000000; + SETCOL(vertex[0]); // set color +} + +//////////////////////////////////////////////////////////////////////// +// Fucking stupid screen coord checking +//////////////////////////////////////////////////////////////////////// + +BOOL ClipVertexListScreen(void) +{ + if (lx0 >= PSXDisplay.DisplayEnd.x) goto NEXTSCRTEST; + if (ly0 >= PSXDisplay.DisplayEnd.y) goto NEXTSCRTEST; + if (lx2 < PSXDisplay.DisplayPosition.x) goto NEXTSCRTEST; + if (ly2 < PSXDisplay.DisplayPosition.y) goto NEXTSCRTEST; + + return TRUE; + +NEXTSCRTEST: + if(PSXDisplay.InterlacedTest) return FALSE; + + if (lx0 >= PreviousPSXDisplay.DisplayEnd.x) return FALSE; + if (ly0 >= PreviousPSXDisplay.DisplayEnd.y) return FALSE; + if (lx2 < PreviousPSXDisplay.DisplayPosition.x) return FALSE; + if (ly2 < PreviousPSXDisplay.DisplayPosition.y) return FALSE; + + return TRUE; +} + +//////////////////////////////////////////////////////////////////////// + +BOOL bDrawOffscreenFront(void) +{ + if(sxmin < PSXDisplay.DisplayPosition.x) return FALSE; // must be complete in front + if(symin < PSXDisplay.DisplayPosition.y) return FALSE; + if(sxmax > PSXDisplay.DisplayEnd.x) return FALSE; + if(symax > PSXDisplay.DisplayEnd.y) return FALSE; + return TRUE; +} + +BOOL bOnePointInFront(void) +{ + if(sxmax< PSXDisplay.DisplayPosition.x) + return FALSE; + + if(symax< PSXDisplay.DisplayPosition.y) + return FALSE; + + if(sxmin>=PSXDisplay.DisplayEnd.x) + return FALSE; + + if(symin>=PSXDisplay.DisplayEnd.y) + return FALSE; + + return TRUE; +} + + +BOOL bOnePointInBack(void) +{ + if(sxmax< PreviousPSXDisplay.DisplayPosition.x) + return FALSE; + + if(symax< PreviousPSXDisplay.DisplayPosition.y) + return FALSE; + + if(sxmin>=PreviousPSXDisplay.DisplayEnd.x) + return FALSE; + + if(symin>=PreviousPSXDisplay.DisplayEnd.y) + return FALSE; + + return TRUE; +} + +BOOL bDrawOffscreen4(void) +{ + BOOL bFront;short sW,sH; + + sxmax=max(lx0,max(lx1,max(lx2,lx3))); + if(sxmaxdrawW) return FALSE; + symax=max(ly0,max(ly1,max(ly2,ly3))); + if(symaxdrawH) return FALSE; + + if(PSXDisplay.Disabled) return TRUE; // disabled? ever + + if(iOffscreenDrawing==1) return bFullVRam; + + if(dwActFixes&1 && iOffscreenDrawing==4) + { + if(PreviousPSXDisplay.DisplayPosition.x==PSXDisplay.DisplayPosition.x && + PreviousPSXDisplay.DisplayPosition.y==PSXDisplay.DisplayPosition.y && + PreviousPSXDisplay.DisplayEnd.x==PSXDisplay.DisplayEnd.x && + PreviousPSXDisplay.DisplayEnd.y==PSXDisplay.DisplayEnd.y) + { + bRenderFrontBuffer=TRUE; + return FALSE; + } + } + + sW=drawW-1;sH=drawH-1; + + sxmin=min(sW,max(sxmin,drawX)); + sxmax=max(drawX,min(sxmax,sW)); + symin=min(sH,max(symin,drawY)); + symax=max(drawY,min(symax,sH)); + + if(bOnePointInBack()) return bFullVRam; + + if(iOffscreenDrawing==2) + bFront=bDrawOffscreenFront(); + else bFront=bOnePointInFront(); + + if(bFront) + { + if(PSXDisplay.InterlacedTest) return bFullVRam; // -> ok, no need for adjust + + vertex[0].x=lx0 - PSXDisplay.DisplayPosition.x+PreviousPSXDisplay.Range.x0; + vertex[1].x=lx1 - PSXDisplay.DisplayPosition.x+PreviousPSXDisplay.Range.x0; + vertex[2].x=lx2 - PSXDisplay.DisplayPosition.x+PreviousPSXDisplay.Range.x0; + vertex[3].x=lx3 - PSXDisplay.DisplayPosition.x+PreviousPSXDisplay.Range.x0; + vertex[0].y=ly0 - PSXDisplay.DisplayPosition.y+PreviousPSXDisplay.Range.y0; + vertex[1].y=ly1 - PSXDisplay.DisplayPosition.y+PreviousPSXDisplay.Range.y0; + vertex[2].y=ly2 - PSXDisplay.DisplayPosition.y+PreviousPSXDisplay.Range.y0; + vertex[3].y=ly3 - PSXDisplay.DisplayPosition.y+PreviousPSXDisplay.Range.y0; + + if(iOffscreenDrawing==4 && !(dwActFixes&1)) // -> frontbuffer wanted + { + bRenderFrontBuffer=TRUE; + //return TRUE; + } + return bFullVRam; // -> but no od + } + + return TRUE; +} + +//////////////////////////////////////////////////////////////////////// + +BOOL bDrawOffscreen3(void) +{ + BOOL bFront;short sW,sH; + + sxmax=max(lx0,max(lx1,lx2)); + if(sxmaxdrawW) return FALSE; + symax=max(ly0,max(ly1,ly2)); + if(symaxdrawH) return FALSE; + + if(PSXDisplay.Disabled) return TRUE; // disabled? ever + + if(iOffscreenDrawing==1) return bFullVRam; + + sW=drawW-1;sH=drawH-1; + sxmin=min(sW,max(sxmin,drawX)); + sxmax=max(drawX,min(sxmax,sW)); + symin=min(sH,max(symin,drawY)); + symax=max(drawY,min(symax,sH)); + + if(bOnePointInBack()) return bFullVRam; + + if(iOffscreenDrawing==2) + bFront=bDrawOffscreenFront(); + else bFront=bOnePointInFront(); + + if(bFront) + { + if(PSXDisplay.InterlacedTest) return bFullVRam; // -> ok, no need for adjust + + vertex[0].x=lx0 - PSXDisplay.DisplayPosition.x+PreviousPSXDisplay.Range.x0; + vertex[1].x=lx1 - PSXDisplay.DisplayPosition.x+PreviousPSXDisplay.Range.x0; + vertex[2].x=lx2 - PSXDisplay.DisplayPosition.x+PreviousPSXDisplay.Range.x0; + vertex[0].y=ly0 - PSXDisplay.DisplayPosition.y+PreviousPSXDisplay.Range.y0; + vertex[1].y=ly1 - PSXDisplay.DisplayPosition.y+PreviousPSXDisplay.Range.y0; + vertex[2].y=ly2 - PSXDisplay.DisplayPosition.y+PreviousPSXDisplay.Range.y0; + + if(iOffscreenDrawing==4) // -> frontbuffer wanted + { + bRenderFrontBuffer=TRUE; + // return TRUE; + } + + return bFullVRam; // -> but no od + } + + return TRUE; +} + +//////////////////////////////////////////////////////////////////////// + +BOOL FastCheckAgainstScreen(short imageX0,short imageY0,short imageX1,short imageY1) +{ + PSXRect_t xUploadArea; + + imageX1 += imageX0; + imageY1 += imageY0; + + if (imageX0 < PreviousPSXDisplay.DisplayPosition.x) + xUploadArea.x0 = PreviousPSXDisplay.DisplayPosition.x; + else + if (imageX0 > PreviousPSXDisplay.DisplayEnd.x) + xUploadArea.x0 = PreviousPSXDisplay.DisplayEnd.x; + else + xUploadArea.x0 = imageX0; + + if(imageX1 < PreviousPSXDisplay.DisplayPosition.x) + xUploadArea.x1 = PreviousPSXDisplay.DisplayPosition.x; + else + if (imageX1 > PreviousPSXDisplay.DisplayEnd.x) + xUploadArea.x1 = PreviousPSXDisplay.DisplayEnd.x; + else + xUploadArea.x1 = imageX1; + + if (imageY0 < PreviousPSXDisplay.DisplayPosition.y) + xUploadArea.y0 = PreviousPSXDisplay.DisplayPosition.y; + else + if (imageY0 > PreviousPSXDisplay.DisplayEnd.y) + xUploadArea.y0 = PreviousPSXDisplay.DisplayEnd.y; + else + xUploadArea.y0 = imageY0; + + if (imageY1 < PreviousPSXDisplay.DisplayPosition.y) + xUploadArea.y1 = PreviousPSXDisplay.DisplayPosition.y; + else + if (imageY1 > PreviousPSXDisplay.DisplayEnd.y) + xUploadArea.y1 = PreviousPSXDisplay.DisplayEnd.y; + else + xUploadArea.y1 = imageY1; + + if ((xUploadArea.x0 != xUploadArea.x1) && (xUploadArea.y0 != xUploadArea.y1)) + return TRUE; + else return FALSE; +} + +BOOL CheckAgainstScreen(short imageX0,short imageY0,short imageX1,short imageY1) +{ + imageX1 += imageX0; + imageY1 += imageY0; + + if (imageX0 < PreviousPSXDisplay.DisplayPosition.x) + xrUploadArea.x0 = PreviousPSXDisplay.DisplayPosition.x; + else + if (imageX0 > PreviousPSXDisplay.DisplayEnd.x) + xrUploadArea.x0 = PreviousPSXDisplay.DisplayEnd.x; + else + xrUploadArea.x0 = imageX0; + + if(imageX1 < PreviousPSXDisplay.DisplayPosition.x) + xrUploadArea.x1 = PreviousPSXDisplay.DisplayPosition.x; + else + if (imageX1 > PreviousPSXDisplay.DisplayEnd.x) + xrUploadArea.x1 = PreviousPSXDisplay.DisplayEnd.x; + else + xrUploadArea.x1 = imageX1; + + if (imageY0 < PreviousPSXDisplay.DisplayPosition.y) + xrUploadArea.y0 = PreviousPSXDisplay.DisplayPosition.y; + else + if (imageY0 > PreviousPSXDisplay.DisplayEnd.y) + xrUploadArea.y0 = PreviousPSXDisplay.DisplayEnd.y; + else + xrUploadArea.y0 = imageY0; + + if (imageY1 < PreviousPSXDisplay.DisplayPosition.y) + xrUploadArea.y1 = PreviousPSXDisplay.DisplayPosition.y; + else + if (imageY1 > PreviousPSXDisplay.DisplayEnd.y) + xrUploadArea.y1 = PreviousPSXDisplay.DisplayEnd.y; + else + xrUploadArea.y1 = imageY1; + + if ((xrUploadArea.x0 != xrUploadArea.x1) && (xrUploadArea.y0 != xrUploadArea.y1)) + return TRUE; + else return FALSE; +} + +BOOL FastCheckAgainstFrontScreen(short imageX0,short imageY0,short imageX1,short imageY1) +{ + PSXRect_t xUploadArea; + + imageX1 += imageX0; + imageY1 += imageY0; + + if (imageX0 < PSXDisplay.DisplayPosition.x) + xUploadArea.x0 = PSXDisplay.DisplayPosition.x; + else + if (imageX0 > PSXDisplay.DisplayEnd.x) + xUploadArea.x0 = PSXDisplay.DisplayEnd.x; + else + xUploadArea.x0 = imageX0; + + if(imageX1 < PSXDisplay.DisplayPosition.x) + xUploadArea.x1 = PSXDisplay.DisplayPosition.x; + else + if (imageX1 > PSXDisplay.DisplayEnd.x) + xUploadArea.x1 = PSXDisplay.DisplayEnd.x; + else + xUploadArea.x1 = imageX1; + + if (imageY0 < PSXDisplay.DisplayPosition.y) + xUploadArea.y0 = PSXDisplay.DisplayPosition.y; + else + if (imageY0 > PSXDisplay.DisplayEnd.y) + xUploadArea.y0 = PSXDisplay.DisplayEnd.y; + else + xUploadArea.y0 = imageY0; + + if (imageY1 < PSXDisplay.DisplayPosition.y) + xUploadArea.y1 = PSXDisplay.DisplayPosition.y; + else + if (imageY1 > PSXDisplay.DisplayEnd.y) + xUploadArea.y1 = PSXDisplay.DisplayEnd.y; + else + xUploadArea.y1 = imageY1; + + if ((xUploadArea.x0 != xUploadArea.x1) && (xUploadArea.y0 != xUploadArea.y1)) + return TRUE; + else return FALSE; +} + +BOOL CheckAgainstFrontScreen(short imageX0,short imageY0,short imageX1,short imageY1) +{ + imageX1 += imageX0; + imageY1 += imageY0; + + if (imageX0 < PSXDisplay.DisplayPosition.x) + xrUploadArea.x0 = PSXDisplay.DisplayPosition.x; + else + if (imageX0 > PSXDisplay.DisplayEnd.x) + xrUploadArea.x0 = PSXDisplay.DisplayEnd.x; + else + xrUploadArea.x0 = imageX0; + + if(imageX1 < PSXDisplay.DisplayPosition.x) + xrUploadArea.x1 = PSXDisplay.DisplayPosition.x; + else + if (imageX1 > PSXDisplay.DisplayEnd.x) + xrUploadArea.x1 = PSXDisplay.DisplayEnd.x; + else + xrUploadArea.x1 = imageX1; + + if (imageY0 < PSXDisplay.DisplayPosition.y) + xrUploadArea.y0 = PSXDisplay.DisplayPosition.y; + else + if (imageY0 > PSXDisplay.DisplayEnd.y) + xrUploadArea.y0 = PSXDisplay.DisplayEnd.y; + else + xrUploadArea.y0 = imageY0; + + if (imageY1 < PSXDisplay.DisplayPosition.y) + xrUploadArea.y1 = PSXDisplay.DisplayPosition.y; + else + if (imageY1 > PSXDisplay.DisplayEnd.y) + xrUploadArea.y1 = PSXDisplay.DisplayEnd.y; + else + xrUploadArea.y1 = imageY1; + + if ((xrUploadArea.x0 != xrUploadArea.x1) && (xrUploadArea.y0 != xrUploadArea.y1)) + return TRUE; + else return FALSE; +} + +//////////////////////////////////////////////////////////////////////// + +void PrepareFullScreenUpload (long Position) +{ + if (Position==-1) // rgb24 + { + if(PSXDisplay.Interlaced) + { + xrUploadArea.x0 = PSXDisplay.DisplayPosition.x; + xrUploadArea.x1 = PSXDisplay.DisplayEnd.x; + xrUploadArea.y0 = PSXDisplay.DisplayPosition.y; + xrUploadArea.y1 = PSXDisplay.DisplayEnd.y; + } + else + { + xrUploadArea.x0 = PreviousPSXDisplay.DisplayPosition.x; + xrUploadArea.x1 = PreviousPSXDisplay.DisplayEnd.x; + xrUploadArea.y0 = PreviousPSXDisplay.DisplayPosition.y; + xrUploadArea.y1 = PreviousPSXDisplay.DisplayEnd.y; + } + + if(bNeedRGB24Update) + { + if(lClearOnSwap) + { +// lClearOnSwap=0; + } + else + if(PSXDisplay.Interlaced && PreviousPSXDisplay.RGB24<2) // in interlaced mode we upload at least two full frames (GT1 menu) + { + PreviousPSXDisplay.RGB24++; + } + else + { + xrUploadArea.y1 = min(xrUploadArea.y0+xrUploadAreaRGB24.y1,xrUploadArea.y1); + xrUploadArea.y0+=xrUploadAreaRGB24.y0; + } + } + } + else + if (Position) + { + xrUploadArea.x0 = PSXDisplay.DisplayPosition.x; + xrUploadArea.x1 = PSXDisplay.DisplayEnd.x; + xrUploadArea.y0 = PSXDisplay.DisplayPosition.y; + xrUploadArea.y1 = PSXDisplay.DisplayEnd.y; + } + else + { + xrUploadArea.x0 = PreviousPSXDisplay.DisplayPosition.x; + xrUploadArea.x1 = PreviousPSXDisplay.DisplayEnd.x; + xrUploadArea.y0 = PreviousPSXDisplay.DisplayPosition.y; + xrUploadArea.y1 = PreviousPSXDisplay.DisplayEnd.y; + } + + if (xrUploadArea.x0 < 0) xrUploadArea.x0 = 0; + else + if (xrUploadArea.x0 > 1023) xrUploadArea.x0 = 1023; + + if (xrUploadArea.x1 < 0) xrUploadArea.x1 = 0; + else + if (xrUploadArea.x1 > 1024) xrUploadArea.x1 = 1024; + + if (xrUploadArea.y0 < 0) xrUploadArea.y0 = 0; + else + if (xrUploadArea.y0 > iGPUHeightMask) xrUploadArea.y0 = iGPUHeightMask; + + if (xrUploadArea.y1 < 0) xrUploadArea.y1 = 0; + else + if (xrUploadArea.y1 > iGPUHeight) xrUploadArea.y1 = iGPUHeight; + + if (PSXDisplay.RGB24) + { + InvalidateTextureArea(xrUploadArea.x0,xrUploadArea.y0,xrUploadArea.x1-xrUploadArea.x0,xrUploadArea.y1-xrUploadArea.y0); + } +} + +//////////////////////////////////////////////////////////////////////// +// Upload screen (MDEC and such) +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// + +u8 * LoadDirectMovieFast(void); + +void UploadScreenEx(long Position) +{ + short ya,yb,xa,xb,x, y, YStep, XStep, U, UStep,ux[4],vy[4]; + + if(!PSXDisplay.DisplayMode.x) return; + if(!PSXDisplay.DisplayMode.y) return; + + glDisable(GL_SCISSOR_TEST); + glShadeModel(GL_FLAT); + bOldSmoothShaded=FALSE; + glDisable(GL_BLEND); + bBlendEnable=FALSE; + glDisable(GL_TEXTURE_2D); + bTexEnabled=FALSE; + glDisable(GL_ALPHA_TEST); + + //glPixelZoom(((float)rRatioRect.right)/((float)PSXDisplay.DisplayMode.x), + // -1.0f*(((float)rRatioRect.bottom)/((float)PSXDisplay.DisplayMode.y))); + + //----------------------------------------------------// + + YStep = 256; // max texture size + XStep = 256; + UStep = (PSXDisplay.RGB24 ? 128 : 0); + ya = xrUploadArea.y0; + yb = xrUploadArea.y1; + xa = xrUploadArea.x0; + xb = xrUploadArea.x1; + + for(y=ya;y<=yb;y+=YStep) // loop y + { + U = 0; + for(x=xa;x<=xb;x+=XStep) // loop x + { + ly0 = ly1 = y; // -> get y coords + ly2 = y + YStep; + if (ly2 > yb) ly2 = yb; + ly3 = ly2; + + lx0 = lx3 = x; // -> get x coords + lx1 = x + XStep; + if (lx1 > xb) lx1 = xb; + + lx2 = lx1; + + ux[0]=ux[3]=(xa - x); // -> set tex x coords + if (ux[0] < 0) ux[0]=ux[3]=0; + ux[2]=ux[1]=(xb - x); + if (ux[2] > 256) ux[2]=ux[1]=256; + + vy[0]=vy[1]=(ya - y); // -> set tex y coords + if (vy[0] < 0) vy[0]=vy[1]=0; + vy[2]=vy[3]=(yb - y); + if (vy[2] > 256) vy[2]=vy[3]=256; + + if ((ux[0] >= ux[2]) || // -> cheaters never win... + (vy[0] >= vy[2])) continue; // (but winners always cheat...) + + xrMovieArea.x0=lx0+U; xrMovieArea.y0=ly0; + xrMovieArea.x1=lx2+U; xrMovieArea.y1=ly2; + + offsetScreenUpload(Position); + + //glRasterPos2f(vertex[0].x,vertex[0].y); + + //glDrawPixels(xrMovieArea.x1-xrMovieArea.x0, + // xrMovieArea.y1-xrMovieArea.y0, + // GL_RGBA,GL_UNSIGNED_BYTE, + LoadDirectMovieFast();//); + + U+=UStep; + } + } + + //----------------------------------------------------// + +// glPixelZoom(1.0F,1.0F); + + glEnable(GL_ALPHA_TEST); + glEnable(GL_SCISSOR_TEST); +} + +//////////////////////////////////////////////////////////////////////// + +void UploadScreen(long Position) +{ + short x, y, YStep, XStep, U, s, UStep,ux[4],vy[4]; + short xa,xb,ya,yb; + + if(xrUploadArea.x0>1023) xrUploadArea.x0=1023; + if(xrUploadArea.x1>1024) xrUploadArea.x1=1024; + if(xrUploadArea.y0>iGPUHeightMask) xrUploadArea.y0=iGPUHeightMask; + if(xrUploadArea.y1>iGPUHeight) xrUploadArea.y1=iGPUHeight; + + if(xrUploadArea.x0==xrUploadArea.x1) return; + if(xrUploadArea.y0==xrUploadArea.y1) return; + + if(PSXDisplay.Disabled && iOffscreenDrawing<4) return; + + iDrawnSomething = 2; + iLastRGB24=PSXDisplay.RGB24+1; + + if(bSkipNextFrame) return; + + if(dwActFixes & 2) {UploadScreenEx(Position);return;} + + bUsingMovie = TRUE; + bDrawTextured = TRUE; // just doing textures + bDrawSmoothShaded = FALSE; + +/* if(bGLBlend) vertex[0].c.lcol=0xff7f7f7f; // set solid col + else */vertex[0].c.lcol=0xffffffff; + SETCOL(vertex[0]); + + SetOGLDisplaySettings(0); + + YStep = 256; // max texture size + XStep = 256; + + UStep = (PSXDisplay.RGB24 ? 128 : 0); + + ya=xrUploadArea.y0; + yb=xrUploadArea.y1; + xa=xrUploadArea.x0; + xb=xrUploadArea.x1; + + for(y=ya;y<=yb;y+=YStep) // loop y + { + U = 0; + for(x=xa;x<=xb;x+=XStep) // loop x + { + ly0 = ly1 = y; // -> get y coords + ly2 = y + YStep; + if (ly2 > yb) ly2 = yb; + ly3 = ly2; + + lx0 = lx3 = x; // -> get x coords + lx1 = x + XStep; + if (lx1 > xb) lx1 = xb; + + lx2 = lx1; + + ux[0]=ux[3]=(xa - x); // -> set tex x coords + if (ux[0] < 0) ux[0]=ux[3]=0; + ux[2]=ux[1]=(xb - x); + if (ux[2] > 256) ux[2]=ux[1]=256; + + vy[0]=vy[1]=(ya - y); // -> set tex y coords + if (vy[0] < 0) vy[0]=vy[1]=0; + vy[2]=vy[3]=(yb - y); + if (vy[2] > 256) vy[2]=vy[3]=256; + + if ((ux[0] >= ux[2]) || // -> cheaters never win... + (vy[0] >= vy[2])) continue; // (but winners always cheat...) + + xrMovieArea.x0=lx0+U; xrMovieArea.y0=ly0; + xrMovieArea.x1=lx2+U; xrMovieArea.y1=ly2; + + s=ux[2] - ux[0]; if(s>255) s=255; + + gl_ux[2] = gl_ux[1] = s; + s=vy[2] - vy[0]; if(s>255) s=255; + gl_vy[2] = gl_vy[3] = s; + gl_ux[0] = gl_ux[3] = gl_vy[0] = gl_vy[1] = 0; + + SetRenderState((unsigned long)0x01000000); + SetRenderMode((unsigned long)0x01000000, FALSE); // upload texture data + offsetScreenUpload(Position); + assignTextureVRAMWrite(); + + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); + + U+=UStep; + } + } + + bUsingMovie=FALSE; // done... + bDisplayNotSet = TRUE; +} + +//////////////////////////////////////////////////////////////////////// +// Detect next screen +//////////////////////////////////////////////////////////////////////// + +BOOL IsCompleteInsideNextScreen(short x, short y, short xoff, short yoff) +{ + if (x > PSXDisplay.DisplayPosition.x+1) return FALSE; + if ((x + xoff) < PSXDisplay.DisplayEnd.x-1) return FALSE; + yoff+=y; + if (y >= PSXDisplay.DisplayPosition.y && + y <= PSXDisplay.DisplayEnd.y ) + { + if ((yoff) >= PSXDisplay.DisplayPosition.y && + (yoff) <= PSXDisplay.DisplayEnd.y ) return TRUE; + } + if (y > PSXDisplay.DisplayPosition.y+1) return FALSE; + if (yoff < PSXDisplay.DisplayEnd.y-1) return FALSE; + return TRUE; +} + +BOOL IsPrimCompleteInsideNextScreen(short x, short y, short xoff, short yoff) +{ + x+=PSXDisplay.DrawOffset.x; + if (x > PSXDisplay.DisplayPosition.x+1) return FALSE; + y+=PSXDisplay.DrawOffset.y; + if (y > PSXDisplay.DisplayPosition.y+1) return FALSE; + xoff+=PSXDisplay.DrawOffset.x; + if (xoff < PSXDisplay.DisplayEnd.x-1) return FALSE; + yoff+=PSXDisplay.DrawOffset.y; + if (yoff < PSXDisplay.DisplayEnd.y-1) return FALSE; + return TRUE; +} + +BOOL IsInsideNextScreen(short x, short y, short xoff, short yoff) +{ + if (x > PSXDisplay.DisplayEnd.x) return FALSE; + if (y > PSXDisplay.DisplayEnd.y) return FALSE; + if ((x + xoff) < PSXDisplay.DisplayPosition.x) return FALSE; + if ((y + yoff) < PSXDisplay.DisplayPosition.y) return FALSE; + return TRUE; +} + +//////////////////////////////////////////////////////////////////////// +// mask stuff... +//////////////////////////////////////////////////////////////////////// + +//Mask1 Set mask bit while drawing. 1 = on +//Mask2 Do not draw to mask areas. 1= on + +void cmdSTP(u8 * baseAddr) +{ + unsigned long gdata = ((unsigned long*)baseAddr)[0]; + + STATUSREG&=~0x1800; // clear the necessary bits + STATUSREG|=((gdata & 0x03) << 11); // set the current bits + + if(!iUseMask) return; + + if(gdata&1) {sSetMask=0x8000;lSetMask=0x80008000;iSetMask=1;} + else {sSetMask=0; lSetMask=0; iSetMask=0;} + + if(gdata&2) + { + if(!(gdata&1)) iSetMask=2; + bCheckMask=TRUE; + if(iDepthFunc==0) return; + iDepthFunc=0; + glDepthFunc(GL_LESS); + } + else + { + bCheckMask=FALSE; + if(iDepthFunc==1) return; + glDepthFunc(GL_ALWAYS); + iDepthFunc=1; + } +} + +//////////////////////////////////////////////////////////////////////// +// cmd: Set texture page infos +//////////////////////////////////////////////////////////////////////// + +void cmdTexturePage(u8 * baseAddr) +{ + unsigned long gdata = ((unsigned long*)baseAddr)[0]; + UpdateGlobalTP((unsigned short)gdata); + GlobalTextREST = (gdata&0x00ffffff)>>9; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: turn on/off texture window +//////////////////////////////////////////////////////////////////////// + +void cmdTextureWindow(u8 *baseAddr) +{ + unsigned long gdata = ((unsigned long*)baseAddr)[0]; + + unsigned long YAlign,XAlign; + + ulGPUInfoVals[INFO_TW]=gdata&0xFFFFF; + + if(gdata & 0x020) + TWin.Position.y1 = 8; // xxxx1 + else if (gdata & 0x040) + TWin.Position.y1 = 16; // xxx10 + else if (gdata & 0x080) + TWin.Position.y1 = 32; // xx100 + else if (gdata & 0x100) + TWin.Position.y1 = 64; // x1000 + else if (gdata & 0x200) + TWin.Position.y1 = 128; // 10000 + else + TWin.Position.y1 = 256; // 00000 + + // Texture window size is determined by the least bit set of the relevant 5 bits + + if (gdata & 0x001) + TWin.Position.x1 = 8; // xxxx1 + else if (gdata & 0x002) + TWin.Position.x1 = 16; // xxx10 + else if (gdata & 0x004) + TWin.Position.x1 = 32; // xx100 + else if (gdata & 0x008) + TWin.Position.x1 = 64; // x1000 + else if (gdata & 0x010) + TWin.Position.x1 = 128; // 10000 + else + TWin.Position.x1 = 256; // 00000 + + // Re-calculate the bit field, because we can't trust what is passed in the data + + YAlign = (unsigned long)(32 - (TWin.Position.y1 >> 3)); + XAlign = (unsigned long)(32 - (TWin.Position.x1 >> 3)); + + // Absolute position of the start of the texture window + + TWin.Position.y0 = (short)(((gdata >> 15) & YAlign) << 3); + TWin.Position.x0 = (short)(((gdata >> 10) & XAlign) << 3); + + if((TWin.Position.x0 == 0 && // tw turned off + TWin.Position.y0 == 0 && + TWin.Position.x1 == 0 && + TWin.Position.y1 == 0) || + (TWin.Position.x1 == 256 && + TWin.Position.y1 == 256)) + { + bUsingTWin = FALSE; // -> just do it + +#ifdef OWNSCALE + TWin.UScaleFactor = 1.0f; + TWin.VScaleFactor = 1.0f; +#else + TWin.UScaleFactor = + TWin.VScaleFactor = 1.0f/256.0f; +#endif + } + else // tw turned on + { + bUsingTWin = TRUE; + + TWin.OPosition.y1 = TWin.Position.y1; // -> get psx sizes + TWin.OPosition.x1 = TWin.Position.x1; + + if(TWin.Position.x1<=2) TWin.Position.x1=2; // -> set OGL sizes + else + if(TWin.Position.x1<=4) TWin.Position.x1=4; + else + if(TWin.Position.x1<=8) TWin.Position.x1=8; + else + if(TWin.Position.x1<=16) TWin.Position.x1=16; + else + if(TWin.Position.x1<=32) TWin.Position.x1=32; + else + if(TWin.Position.x1<=64) TWin.Position.x1=64; + else + if(TWin.Position.x1<=128) TWin.Position.x1=128; + else + if(TWin.Position.x1<=256) TWin.Position.x1=256; + + if(TWin.Position.y1<=2) TWin.Position.y1=2; + else + if(TWin.Position.y1<=4) TWin.Position.y1=4; + else + if(TWin.Position.y1<=8) TWin.Position.y1=8; + else + if(TWin.Position.y1<=16) TWin.Position.y1=16; + else + if(TWin.Position.y1<=32) TWin.Position.y1=32; + else + if(TWin.Position.y1<=64) TWin.Position.y1=64; + else + if(TWin.Position.y1<=128) TWin.Position.y1=128; + else + if(TWin.Position.y1<=256) TWin.Position.y1=256; + +#ifdef OWNSCALE + TWin.UScaleFactor = (float)TWin.Position.x1; + TWin.VScaleFactor = (float)TWin.Position.y1; +#else + TWin.UScaleFactor = ((float)TWin.Position.x1)/256.0f; // -> set scale factor + TWin.VScaleFactor = ((float)TWin.Position.y1)/256.0f; +#endif + } +} + +//////////////////////////////////////////////////////////////////////// +// mmm, Lewpy uses that in TileS ... I don't ;) +//////////////////////////////////////////////////////////////////////// + +/* +void ClampToPSXDrawAreaOffset(short *x0, short *y0, short *x1, short *y1) +{ + if (*x0 < PSXDisplay.DrawArea.x0) + { + *x1 -= (PSXDisplay.DrawArea.x0 - *x0); + *x0 = PSXDisplay.DrawArea.x0; + } + else + if (*x0 > PSXDisplay.DrawArea.x1) + { + *x0 = PSXDisplay.DrawArea.x1; + *x1 = 0; + } + + if (*y0 < PSXDisplay.DrawArea.y0) + { + *y1 -= (PSXDisplay.DrawArea.y0 - *y0); + *y0 = PSXDisplay.DrawArea.y0; + } + else + if (*y0 > PSXDisplay.DrawArea.y1) + { + *y0 = PSXDisplay.DrawArea.y1; + *y1 = 0; + } + + if (*x1 < 0) *x1 = 0; + + if ((*x1 + *x0) > PSXDisplay.DrawArea.x1) + *x1 = (PSXDisplay.DrawArea.x1 - *x0 + 1); + + if (*y1 < 0) *y1 = 0; + + if ((*y1 + *y0) > PSXDisplay.DrawArea.y1) + *y1 = (PSXDisplay.DrawArea.y1 - *y0 + 1); +} +*/ + +//////////////////////////////////////////////////////////////////////// +// Check draw area dimensions +//////////////////////////////////////////////////////////////////////// + +void ClampToPSXScreen(short *x0, short *y0, short *x1, short *y1) +{ + if (*x0 < 0) *x0 = 0; + else + if (*x0 > 1023) *x0 = 1023; + + if (*x1 < 0) *x1 = 0; + else + if (*x1 > 1023) *x1 = 1023; + + if (*y0 < 0) *y0 = 0; + else + if (*y0 > iGPUHeightMask) *y0 = iGPUHeightMask; + + if (*y1 < 0) *y1 = 0; + else + if (*y1 > iGPUHeightMask) *y1 = iGPUHeightMask; +} + +//////////////////////////////////////////////////////////////////////// +// Used in Load Image and Blk Fill +//////////////////////////////////////////////////////////////////////// + +void ClampToPSXScreenOffset(short *x0, short *y0, short *x1, short *y1) +{ + if (*x0 < 0) + { *x1 += *x0; *x0 = 0; } + else + if (*x0 > 1023) + { *x0 = 1023; *x1 = 0; } + + if (*y0 < 0) + { *y1 += *y0; *y0 = 0; } + else + if (*y0 > iGPUHeightMask) + { *y0 = iGPUHeightMask; *y1 = 0; } + + if (*x1 < 0) *x1 = 0; + + if ((*x1 + *x0) > 1024) *x1 = (1024 - *x0); + + if (*y1 < 0) *y1 = 0; + + if ((*y1 + *y0) > iGPUHeight) *y1 = (iGPUHeight - *y0); +} + +//////////////////////////////////////////////////////////////////////// +// cmd: start of drawing area... primitives will be clipped inside +//////////////////////////////////////////////////////////////////////// + +void cmdDrawAreaStart(u8 * baseAddr) +{ + unsigned long gdata = ((unsigned long*)baseAddr)[0]; + + drawX = gdata & 0x3ff; // for soft drawing + if(drawX>=1024) drawX=1023; + + if(dwGPUVersion==2) + { + ulGPUInfoVals[INFO_DRAWSTART]=gdata&0x3FFFFF; + drawY = (gdata>>12)&0x3ff; + } + else + { + ulGPUInfoVals[INFO_DRAWSTART]=gdata&0xFFFFF; + drawY = (gdata>>10)&0x3ff; + } + + if(drawY>=iGPUHeight) drawY=iGPUHeightMask; + + PreviousPSXDisplay.DrawArea.y0=PSXDisplay.DrawArea.y0; + PreviousPSXDisplay.DrawArea.x0=PSXDisplay.DrawArea.x0; + + PSXDisplay.DrawArea.y0 = (short)drawY; // for OGL drawing + PSXDisplay.DrawArea.x0 = (short)drawX; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: end of drawing area... primitives will be clipped inside +//////////////////////////////////////////////////////////////////////// + +void cmdDrawAreaEnd(u8 * baseAddr) +{ + unsigned long gdata = ((unsigned long*)baseAddr)[0]; + + drawW = gdata & 0x3ff; // for soft drawing + if(drawW>=1024) drawW=1023; + + if(dwGPUVersion==2) + { + ulGPUInfoVals[INFO_DRAWEND]=gdata&0x3FFFFF; + drawH = (gdata>>12)&0x3ff; + } + else + { + ulGPUInfoVals[INFO_DRAWEND]=gdata&0xFFFFF; + drawH = (gdata>>10)&0x3ff; + } + + if(drawH>=iGPUHeight) drawH=iGPUHeightMask; + + PSXDisplay.DrawArea.y1 = (short)drawH; // for OGL drawing + PSXDisplay.DrawArea.x1 = (short)drawW; + + ClampToPSXScreen(&PSXDisplay.DrawArea.x0, // clamp + &PSXDisplay.DrawArea.y0, + &PSXDisplay.DrawArea.x1, + &PSXDisplay.DrawArea.y1); + + bDisplayNotSet = TRUE; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: draw offset... will be added to prim coords +//////////////////////////////////////////////////////////////////////// + +void cmdDrawOffset(u8 * baseAddr) +{ + unsigned long gdata = ((unsigned long*)baseAddr)[0]; + + PreviousPSXDisplay.DrawOffset.x = + PSXDisplay.DrawOffset.x = (short)(gdata & 0x7ff); + + if(dwGPUVersion==2) + { + ulGPUInfoVals[INFO_DRAWOFF]=gdata&0x7FFFFF; + PSXDisplay.DrawOffset.y = (short)((gdata>>12) & 0x7ff); + } + else + { + ulGPUInfoVals[INFO_DRAWOFF]=gdata&0x3FFFFF; + PSXDisplay.DrawOffset.y = (short)((gdata>>11) & 0x7ff); + } + + PSXDisplay.DrawOffset.x=(short)(((int)PSXDisplay.DrawOffset.x<<21)>>21); + PSXDisplay.DrawOffset.y=(short)(((int)PSXDisplay.DrawOffset.y<<21)>>21); + + PSXDisplay.CumulOffset.x = // new OGL prim offsets + PSXDisplay.DrawOffset.x - PSXDisplay.GDrawOffset.x + PreviousPSXDisplay.Range.x0; + PSXDisplay.CumulOffset.y = + PSXDisplay.DrawOffset.y - PSXDisplay.GDrawOffset.y + PreviousPSXDisplay.Range.y0; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: load image to vram +//////////////////////////////////////////////////////////////////////// + +void primLoadImage(u8 * baseAddr) +{ + unsigned short *sgpuData = ((unsigned short *) baseAddr); + + VRAMWrite.x = sgpuData[2]&0x03ff; + VRAMWrite.y = sgpuData[3]&iGPUHeightMask; + VRAMWrite.Width = sgpuData[4]; + VRAMWrite.Height = sgpuData[5]; + + iDataWriteMode = DR_VRAMTRANSFER; + VRAMWrite.ImagePtr = psxVuw + (VRAMWrite.y<<10) + VRAMWrite.x; + VRAMWrite.RowsRemaining = VRAMWrite.Width; + VRAMWrite.ColsRemaining = VRAMWrite.Height; + + bNeedWriteUpload=TRUE; +} + +//////////////////////////////////////////////////////////////////////// + +void PrepareRGB24Upload(void) +{ + VRAMWrite.x=(VRAMWrite.x*2)/3; + VRAMWrite.Width=(VRAMWrite.Width*2)/3; + + if(!PSXDisplay.InterlacedTest && // NEW + CheckAgainstScreen(VRAMWrite.x, VRAMWrite.y, VRAMWrite.Width, VRAMWrite.Height)) + { + xrUploadArea.x0-=PreviousPSXDisplay.DisplayPosition.x; + xrUploadArea.x1-=PreviousPSXDisplay.DisplayPosition.x; + xrUploadArea.y0-=PreviousPSXDisplay.DisplayPosition.y; + xrUploadArea.y1-=PreviousPSXDisplay.DisplayPosition.y; + } + else + if(CheckAgainstFrontScreen(VRAMWrite.x, VRAMWrite.y, VRAMWrite.Width, VRAMWrite.Height)) + { + xrUploadArea.x0-=PSXDisplay.DisplayPosition.x; + xrUploadArea.x1-=PSXDisplay.DisplayPosition.x; + xrUploadArea.y0-=PSXDisplay.DisplayPosition.y; + xrUploadArea.y1-=PSXDisplay.DisplayPosition.y; + } + else return; + + if(bRenderFrontBuffer) + { + updateFrontDisplay(); + } + + if(bNeedRGB24Update==FALSE) + { + xrUploadAreaRGB24=xrUploadArea; + bNeedRGB24Update=TRUE; + } + else + { + xrUploadAreaRGB24.x0=min(xrUploadAreaRGB24.x0,xrUploadArea.x0); + xrUploadAreaRGB24.x1=max(xrUploadAreaRGB24.x1,xrUploadArea.x1); + xrUploadAreaRGB24.y0=min(xrUploadAreaRGB24.y0,xrUploadArea.y0); + xrUploadAreaRGB24.y1=max(xrUploadAreaRGB24.y1,xrUploadArea.y1); + } +} + +//////////////////////////////////////////////////////////////////////// + +void CheckWriteUpdate() +{ + int iX=0,iY=0; + + if(VRAMWrite.Width) iX=1; + if(VRAMWrite.Height) iY=1; + + InvalidateTextureArea(VRAMWrite.x, VRAMWrite.y, VRAMWrite.Width-iX, VRAMWrite.Height-iY); + + if(PSXDisplay.Interlaced && !iOffscreenDrawing) return; + + if(PSXDisplay.RGB24) {PrepareRGB24Upload();return;} + + if(!PSXDisplay.InterlacedTest && + CheckAgainstScreen(VRAMWrite.x, VRAMWrite.y, VRAMWrite.Width, VRAMWrite.Height)) + { + if(dwActFixes&0x800) return; + + if(bRenderFrontBuffer) + { + updateFrontDisplay(); + } + + UploadScreen(FALSE); + + bNeedUploadTest=TRUE; + } + else + if(iOffscreenDrawing) + { + if (CheckAgainstFrontScreen(VRAMWrite.x, VRAMWrite.y, VRAMWrite.Width, VRAMWrite.Height)) + { + if(PSXDisplay.InterlacedTest) + { + if(PreviousPSXDisplay.InterlacedNew) + { + PreviousPSXDisplay.InterlacedNew=FALSE; + bNeedInterlaceUpdate=TRUE; + xrUploadAreaIL.x0=PSXDisplay.DisplayPosition.x; + xrUploadAreaIL.y0=PSXDisplay.DisplayPosition.y; + xrUploadAreaIL.x1=PSXDisplay.DisplayPosition.x+PSXDisplay.DisplayModeNew.x; + xrUploadAreaIL.y1=PSXDisplay.DisplayPosition.y+PSXDisplay.DisplayModeNew.y; + if(xrUploadAreaIL.x1>1023) xrUploadAreaIL.x1=1023; + if(xrUploadAreaIL.y1>511) xrUploadAreaIL.y1=511; + } + + if(bNeedInterlaceUpdate==FALSE) + { + xrUploadAreaIL=xrUploadArea; + bNeedInterlaceUpdate=TRUE; + } + else + { + xrUploadAreaIL.x0=min(xrUploadAreaIL.x0,xrUploadArea.x0); + xrUploadAreaIL.x1=max(xrUploadAreaIL.x1,xrUploadArea.x1); + xrUploadAreaIL.y0=min(xrUploadAreaIL.y0,xrUploadArea.y0); + xrUploadAreaIL.y1=max(xrUploadAreaIL.y1,xrUploadArea.y1); + } + return; + } + + if(!bNeedUploadAfter) + { + bNeedUploadAfter = TRUE; + xrUploadArea.x0=VRAMWrite.x; + xrUploadArea.x1=VRAMWrite.x+VRAMWrite.Width; + xrUploadArea.y0=VRAMWrite.y; + xrUploadArea.y1=VRAMWrite.y+VRAMWrite.Height; + } + else + { + xrUploadArea.x0=min(xrUploadArea.x0,VRAMWrite.x); + xrUploadArea.x1=max(xrUploadArea.x1,VRAMWrite.x+VRAMWrite.Width); + xrUploadArea.y0=min(xrUploadArea.y0,VRAMWrite.y); + xrUploadArea.y1=max(xrUploadArea.y1,VRAMWrite.y+VRAMWrite.Height); + } + + if(dwActFixes&0x8000) + { + if((xrUploadArea.x1-xrUploadArea.x0)>=(PSXDisplay.DisplayMode.x-32) && + (xrUploadArea.y1-xrUploadArea.y0)>=(PSXDisplay.DisplayMode.y-32)) + { + UploadScreen(-1); + updateFrontDisplay(); + } + } + } + } +} + +//////////////////////////////////////////////////////////////////////// +// cmd: vram -> psx mem +//////////////////////////////////////////////////////////////////////// + +void primStoreImage(u8 * baseAddr) +{ + unsigned short *sgpuData = ((unsigned short *) baseAddr); + + VRAMRead.x = sgpuData[2]&0x03ff; + VRAMRead.y = sgpuData[3]&iGPUHeightMask; + VRAMRead.Width = sgpuData[4]; + VRAMRead.Height = sgpuData[5]; + + VRAMRead.ImagePtr = psxVuw + (VRAMRead.y<<10) + VRAMRead.x; + VRAMRead.RowsRemaining = VRAMRead.Width; + VRAMRead.ColsRemaining = VRAMRead.Height; + + iDataReadMode = DR_VRAMTRANSFER; + + STATUSREG |= GPUSTATUS_READYFORVRAM; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: blkfill - NO primitive! Doesn't care about draw areas... +//////////////////////////////////////////////////////////////////////// + +void primBlkFill(u8 * baseAddr) +{ + unsigned long *gpuData = ((unsigned long *) baseAddr); + short *sgpuData = ((short *) baseAddr); + + iDrawnSomething=1; + + sprtX = sgpuData[2]; + sprtY = sgpuData[3]; + sprtW = sgpuData[4] & 0x3ff; + sprtH = sgpuData[5] & iGPUHeightMask; + + sprtW = (sprtW+15) & ~15; + + // Increase H & W if they are one short of full values, because they never can be full values + if (sprtH == iGPUHeightMask) sprtH=iGPUHeight; + if (sprtW == 1023) sprtW=1024; + + // x and y of start + ly0 = ly1 = sprtY; + ly2 = ly3 = (sprtY+sprtH); + lx0 = lx3 = sprtX; + lx1 = lx2 = (sprtX+sprtW); + + offsetBlk(); + + if(ClipVertexListScreen()) + { + PSXDisplay_t * pd; + if(PSXDisplay.InterlacedTest) pd=&PSXDisplay; + else pd=&PreviousPSXDisplay; + + if ((lx0 <= pd->DisplayPosition.x+16) && + (ly0 <= pd->DisplayPosition.y+16) && + (lx2 >= pd->DisplayEnd.x-16) && + (ly2 >= pd->DisplayEnd.y-16)) + { + GLclampf g,b,r; + g=((GLclampf)GREEN(gpuData[0]))/255.0f; + b=((GLclampf)BLUE(gpuData[0]))/255.0f; + r=((GLclampf)RED(gpuData[0]))/255.0f; + + glDisable(GL_SCISSOR_TEST); + glClearColor(r,g,b,1.0f); + glClear(uiBufferBits); + gl_z=0.0f; + + if(gpuData[0]!=0x02000000 && + (ly0>pd->DisplayPosition.y || + ly2DisplayEnd.y)) + { + bDrawTextured = FALSE; + bDrawSmoothShaded = FALSE; + SetRenderState((unsigned long)0x01000000); + SetRenderMode((unsigned long)0x01000000, FALSE); + vertex[0].c.lcol=0xff000000; + SETCOL(vertex[0]); + if(ly0>pd->DisplayPosition.y) + { + vertex[0].x=0;vertex[0].y=0; + vertex[1].x=pd->DisplayEnd.x-pd->DisplayPosition.x;vertex[1].y=0; + vertex[2].x=vertex[1].x;vertex[2].y=ly0-pd->DisplayPosition.y; + vertex[3].x=0;vertex[3].y=vertex[2].y; + PRIMdrawQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); + } + if(ly2DisplayEnd.y) + { + vertex[0].x=0;vertex[0].y=(pd->DisplayEnd.y-pd->DisplayPosition.y)-(pd->DisplayEnd.y-ly2); + vertex[1].x=pd->DisplayEnd.x-pd->DisplayPosition.x;vertex[1].y=vertex[0].y; + vertex[2].x=vertex[1].x;vertex[2].y=pd->DisplayEnd.y; + vertex[3].x=0;vertex[3].y=vertex[2].y; + PRIMdrawQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); + } + } + + glEnable(GL_SCISSOR_TEST); + } + else + { + bDrawTextured = FALSE; + bDrawSmoothShaded = FALSE; + SetRenderState((unsigned long)0x01000000); + SetRenderMode((unsigned long)0x01000000, FALSE); + vertex[0].c.lcol=gpuData[0]|0xff000000; + SETCOL(vertex[0]); + glDisable(GL_SCISSOR_TEST); + PRIMdrawQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); + glEnable(GL_SCISSOR_TEST); + } + } + + //mmm... will clean all stuff, also if not all _should_ be cleaned... + //if (IsInsideNextScreen(sprtX, sprtY, sprtW, sprtH)) + // try this: + if (IsCompleteInsideNextScreen(sprtX, sprtY, sprtW, sprtH)) + { + lClearOnSwapColor = COLOR(gpuData[0]); + lClearOnSwap = 1; + } + +/* if(iOffscreenDrawing) + { + ClampToPSXScreenOffset( &sprtX, &sprtY, &sprtW, &sprtH); + if ((sprtW == 0) || (sprtH == 0)) return; + InvalidateTextureArea(sprtX, sprtY, sprtW-1, sprtH-1); + + sprtW+=sprtX; + sprtH+=sprtY; + + FillSoftwareArea(sprtX, sprtY, sprtW, sprtH, BGR24to16(gpuData[0])); + }*/ +} + +//////////////////////////////////////////////////////////////////////// +// cmd: move image vram -> vram +//////////////////////////////////////////////////////////////////////// + +void MoveImageWrapped(short imageX0,short imageY0, + short imageX1,short imageY1, + short imageSX,short imageSY) +{ + int i,j,imageXE,imageYE; + + if(iFrameReadType&2) + { + imageXE=imageX0+imageSX; + imageYE=imageY0+imageSY; + + if(imageYE>iGPUHeight && imageXE>1024) + { + CheckVRamRead(0,0, + (imageXE&0x3ff), + (imageY0&iGPUHeightMask), + FALSE); + } + + if(imageXE>1024) + { + CheckVRamRead(0,imageY0, + (imageXE&0x3ff), + (imageYE>iGPUHeight)?iGPUHeight:imageYE, + FALSE); + } + + if(imageYE>iGPUHeight) + { + CheckVRamRead(imageX0,0, + (imageXE>1024)?1024:imageXE, + imageYE&iGPUHeightMask, + FALSE); + } + + CheckVRamRead(imageX0,imageY0, + (imageXE>1024)?1024:imageXE, + (imageYE>iGPUHeight)?iGPUHeight:imageYE, + FALSE); + } + + for(j=0;jiGPUHeight && imageXE>1024) + { + InvalidateTextureArea(0,0, + (imageXE&0x3ff)-1, + (imageYE&iGPUHeightMask)-1); + } + + if(imageXE>1024) + { + InvalidateTextureArea(0,imageY1, + (imageXE&0x3ff)-1, + ((imageYE>iGPUHeight)?iGPUHeight:imageYE)-imageY1-1); + } + + if(imageYE>iGPUHeight) + { + InvalidateTextureArea(imageX1,0, + ((imageXE>1024)?1024:imageXE)-imageX1-1, + (imageYE&iGPUHeightMask)-1); + } + + InvalidateTextureArea(imageX1,imageY1, + ((imageXE>1024)?1024:imageXE)-imageX1-1, + ((imageYE>iGPUHeight)?iGPUHeight:imageYE)-imageY1-1); + } +} + +//////////////////////////////////////////////////////////////////////// + +void primMoveImage(u8 * baseAddr) +{ + short *sgpuData = ((short *) baseAddr); + short imageY0,imageX0,imageY1,imageX1,imageSX,imageSY,i,j; + + imageX0 = sgpuData[2]&0x03ff; + imageY0 = sgpuData[3]&iGPUHeightMask; + imageX1 = sgpuData[4]&0x03ff; + imageY1 = sgpuData[5]&iGPUHeightMask; + imageSX = sgpuData[6]; + imageSY = sgpuData[7]; + + if((imageX0 == imageX1) && (imageY0 == imageY1)) return; + if(imageSX<=0) return; + if(imageSY<=0) return; + + if(iGPUHeight==1024 && sgpuData[7]>1024) return; + + if((imageY0+imageSY)>iGPUHeight || + (imageX0+imageSX)>1024 || + (imageY1+imageSY)>iGPUHeight || + (imageX1+imageSX)>1024) + { + MoveImageWrapped(imageX0,imageY0,imageX1,imageY1,imageSX,imageSY); + if((imageY0+imageSY)>iGPUHeight) imageSY=iGPUHeight-imageY0; + if((imageX0+imageSX)>1024) imageSX=1024-imageX0; + if((imageY1+imageSY)>iGPUHeight) imageSY=iGPUHeight-imageY1; + if((imageX1+imageSX)>1024) imageSX=1024-imageX1; + } + + if(iFrameReadType&2) + CheckVRamRead(imageX0,imageY0, + imageX0+imageSX, + imageY0+imageSY, + FALSE); + + if(imageSX&1) + { + unsigned short *SRCPtr, *DSTPtr; + unsigned short LineOffset; + + SRCPtr = psxVuw + (1024*imageY0) + imageX0; + DSTPtr = psxVuw + (1024*imageY1) + imageX1; + + LineOffset = 1024 - imageSX; + + for(j=0;j>1; + + SRCPtr = (unsigned long *)(psxVuw + (1024*imageY0) + imageX0); + DSTPtr = (unsigned long *)(psxVuw + (1024*imageY1) + imageX1); + + LineOffset = 512 - dx; + + for(j=0;j=PreviousPSXDisplay.DisplayPosition.x && + imageX1=PreviousPSXDisplay.DisplayPosition.y && + imageY1=PreviousPSXDisplay.DisplayPosition.x && + imageX1<=PreviousPSXDisplay.DisplayEnd.x && + imageY1>=PreviousPSXDisplay.DisplayPosition.y && + imageY1<=PreviousPSXDisplay.DisplayEnd.y) + { + if(!( + imageX0>=PSXDisplay.DisplayPosition.x && + imageX0=PSXDisplay.DisplayPosition.y && + imageY0=PreviousPSXDisplay.DisplayPosition.x && + imageX0=PreviousPSXDisplay.DisplayPosition.y && + imageY0=PSXDisplay.DisplayPosition.x && + imageX0=PSXDisplay.DisplayPosition.y && + imageY0 set color with + SETCOL(vertex[0]); // texture alpha + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); + vertex[0].x+=POFF;vertex[1].x+=POFF; + vertex[2].x+=POFF;vertex[3].x+=POFF; + vertex[0].y+=POFF;vertex[1].y+=POFF; + vertex[2].y+=POFF;vertex[3].y+=POFF; + GlobalTextABR=0; + DrawSemiTrans=1; + SetSemiTrans(); + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); + GlobalTextABR=lABR; + DrawSemiTrans=lDST; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: small sprite (textured rect) +//////////////////////////////////////////////////////////////////////// + +void primSprt8(u8 * baseAddr) +{ + unsigned long *gpuData = ((unsigned long *) baseAddr); + short *sgpuData = ((short *) baseAddr); + short s; + + iSpriteTex=1; + + sprtX = sgpuData[2]; + sprtY = sgpuData[3]; + sprtW = 8; + sprtH = 8; + + lx0 = sprtX; + ly0 = sprtY; + + offsetST(); + + // do texture stuff + gl_ux[0]=gl_ux[3]=baseAddr[8];//gpuData[2]&0xff; + + if(usMirror & 0x1000) + { + s=gl_ux[0]; + s-=sprtW-1; + if(s<0) {s=0;} + gl_ux[0]=gl_ux[3]=s; + } + + sSprite_ux2=s=gl_ux[0]+sprtW; + if(s) s--; + if(s>255) s=255; + gl_ux[1]=gl_ux[2]=s; + // Y coords + gl_vy[0]=gl_vy[1]=baseAddr[9];//(gpuData[2]>>8)&0xff; + + if(usMirror & 0x2000) + { + s=gl_vy[0]; + s-=sprtH-1; + if(s<0) {s=0;} + gl_vy[0]=gl_vy[1]=s; + } + + sSprite_vy2=s=gl_vy[0]+sprtH; + if(s) s--; + if(s>255) s=255; + gl_vy[2]=gl_vy[3]=s; + + ulClutID=(gpuData[2]>>16); + + bDrawTextured = TRUE; + bDrawSmoothShaded = FALSE; + SetRenderState(gpuData[0]); + +/* if(iOffscreenDrawing) + { + offsetPSX4(); + + if(bDrawOffscreen4()) + { + InvalidateTextureAreaEx(); + SetRenderColor(gpuData[0]); + lx0-=PSXDisplay.DrawOffset.x; + ly0-=PSXDisplay.DrawOffset.y; + + if(bUsingTWin) DrawSoftwareSpriteTWin(baseAddr,8,8); + else + if(usMirror) DrawSoftwareSpriteMirror(baseAddr,8,8); + else + DrawSoftwareSprite(baseAddr,8,8,baseAddr[8],baseAddr[9]); + } + } +*/ + SetRenderMode(gpuData[0], TRUE); + SetZMask4SP(); + + sSprite_ux2=gl_ux[0]+sprtW; + sSprite_vy2=gl_vy[0]+sprtH; + + assignTextureSprite(); + + if(iFilterType>4) + DrawMultiFilterSprite(); + else + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); + + if(bDrawMultiPass) + { + SetSemiTransMulti(1); + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); + } + + if(ubOpaqueDraw) + { + SetZMask4O(); + if(bUseMultiPass) SetOpaqueColor(gpuData[0]); + DEFOPAQUEON + +/* if(bSmallAlpha && iFilterType<=2) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + SetZMask4O(); + } +*/ + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); + DEFOPAQUEOFF + } + + iSpriteTex=0; + iDrawnSomething=1; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: medium sprite (textured rect) +//////////////////////////////////////////////////////////////////////// + +void primSprt16(u8 * baseAddr) +{ + unsigned long *gpuData = ((unsigned long *) baseAddr); + short *sgpuData = ((short *) baseAddr); + short s; + + iSpriteTex=1; + + sprtX = sgpuData[2]; + sprtY = sgpuData[3]; + sprtW = 16; + sprtH = 16; + + lx0 = sprtX; + ly0 = sprtY; + + offsetST(); + + // do texture stuff + gl_ux[0]=gl_ux[3]=baseAddr[8];//gpuData[2]&0xff; + + if(usMirror & 0x1000) + { + s=gl_ux[0]; + s-=sprtW-1; + if(s<0) {s=0;} + gl_ux[0]=gl_ux[3]=s; + } + + sSprite_ux2=s=gl_ux[0]+sprtW; + if(s) s--; + if(s>255) s=255; + gl_ux[1]=gl_ux[2]=s; + // Y coords + gl_vy[0]=gl_vy[1]=baseAddr[9];//(gpuData[2]>>8)&0xff; + + if(usMirror & 0x2000) + { + s=gl_vy[0]; + s-=sprtH-1; + if(s<0) {s=0;} + gl_vy[0]=gl_vy[1]=s; + } + + sSprite_vy2=s=gl_vy[0]+sprtH; + if(s) s--; + if(s>255) s=255; + gl_vy[2]=gl_vy[3]=s; + + ulClutID=(gpuData[2]>>16); + + bDrawTextured = TRUE; + bDrawSmoothShaded = FALSE; + SetRenderState(gpuData[0]); + +/* if(iOffscreenDrawing) + { + offsetPSX4(); + + if(bDrawOffscreen4()) + { + InvalidateTextureAreaEx(); + SetRenderColor(gpuData[0]); + lx0-=PSXDisplay.DrawOffset.x; + ly0-=PSXDisplay.DrawOffset.y; + if(bUsingTWin) DrawSoftwareSpriteTWin(baseAddr,16,16); + else + if(usMirror) DrawSoftwareSpriteMirror(baseAddr,16,16); + else + DrawSoftwareSprite(baseAddr,16,16,baseAddr[8],baseAddr[9]); + } + } +*/ + SetRenderMode(gpuData[0], TRUE); + SetZMask4SP(); + + sSprite_ux2=gl_ux[0]+sprtW; + sSprite_vy2=gl_vy[0]+sprtH; + + assignTextureSprite(); + + if(iFilterType>4) + DrawMultiFilterSprite(); + else + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); + + if(bDrawMultiPass) + { + SetSemiTransMulti(1); + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); + } + + if(ubOpaqueDraw) + { + SetZMask4O(); + if(bUseMultiPass) SetOpaqueColor(gpuData[0]); + DEFOPAQUEON + +/* if(bSmallAlpha && iFilterType<=2) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + SetZMask4O(); + } +*/ + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); + DEFOPAQUEOFF + } + + iSpriteTex=0; + iDrawnSomething=1; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: free-size sprite (textured rect) +//////////////////////////////////////////////////////////////////////// + +void primSprtSRest(u8 * baseAddr,unsigned short type) +{ + unsigned long *gpuData = ((unsigned long *) baseAddr); + short *sgpuData = ((short *) baseAddr); + short s;unsigned short sTypeRest=0; + + sprtX = sgpuData[2]; + sprtY = sgpuData[3]; + sprtW = sgpuData[6] & 0x3ff; + sprtH = sgpuData[7] & 0x1ff; + + + // do texture stuff + switch(type) + { + case 1: + gl_vy[0]=gl_vy[1]=baseAddr[9]; + s=256-baseAddr[8]; + sprtW-=s; + sprtX+=s; + gl_ux[0]=gl_ux[3]=0; + break; + case 2: + gl_ux[0]=gl_ux[3]=baseAddr[8]; + s=256-baseAddr[9]; + sprtH-=s; + sprtY+=s; + gl_vy[0]=gl_vy[1]=0; + break; + case 3: + s=256-baseAddr[8]; + sprtW-=s; + sprtX+=s; + gl_ux[0]=gl_ux[3]=0; + s=256-baseAddr[9]; + sprtH-=s; + sprtY+=s; + gl_vy[0]=gl_vy[1]=0; + break; + + case 4: + gl_vy[0]=gl_vy[1]=baseAddr[9]; + s=512-baseAddr[8]; + sprtW-=s; + sprtX+=s; + gl_ux[0]=gl_ux[3]=0; + break; + case 5: + gl_ux[0]=gl_ux[3]=baseAddr[8]; + s=512-baseAddr[9]; + sprtH-=s; + sprtY+=s; + gl_vy[0]=gl_vy[1]=0; + break; + case 6: + s=512-baseAddr[8]; + sprtW-=s; + sprtX+=s; + gl_ux[0]=gl_ux[3]=0; + s=512-baseAddr[9]; + sprtH-=s; + sprtY+=s; + gl_vy[0]=gl_vy[1]=0; + break; + + } + + if(usMirror & 0x1000) + { + s=gl_ux[0]; + s-=sprtW-1;if(s<0) s=0; + gl_ux[0]=gl_ux[3]=s; + } + if(usMirror & 0x2000) + { + s=gl_vy[0]; + s-=sprtH-1;if(s<0) {s=0;} + gl_vy[0]=gl_vy[1]=s; + } + + sSprite_ux2=s=gl_ux[0]+sprtW; + if(s>255) s=255; + gl_ux[1]=gl_ux[2]=s; + sSprite_vy2=s=gl_vy[0]+sprtH; + if(s>255) s=255; + gl_vy[2]=gl_vy[3]=s; + + if(!bUsingTWin) + { + if(sSprite_ux2>256) + {sprtW=256-gl_ux[0];sSprite_ux2=256;sTypeRest+=1;} + if(sSprite_vy2>256) + {sprtH=256-gl_vy[0];sSprite_vy2=256;sTypeRest+=2;} + } + + lx0 = sprtX; + ly0 = sprtY; + + offsetST(); + + ulClutID=(gpuData[2]>>16); + + bDrawTextured = TRUE; + bDrawSmoothShaded = FALSE; + SetRenderState(gpuData[0]); + +/* if(iOffscreenDrawing) + { + offsetPSX4(); + + if(bDrawOffscreen4()) + { + InvalidateTextureAreaEx(); + SetRenderColor(gpuData[0]); + lx0-=PSXDisplay.DrawOffset.x; + ly0-=PSXDisplay.DrawOffset.y; + if(bUsingTWin) DrawSoftwareSpriteTWin(baseAddr,sprtW,sprtH); + else + if(usMirror) DrawSoftwareSpriteMirror(baseAddr,sprtW,sprtH); + else + DrawSoftwareSprite(baseAddr,sprtW,sprtH,baseAddr[8],baseAddr[9]); + } + } +*/ + SetRenderMode(gpuData[0], TRUE); + SetZMask4SP(); + + sSprite_ux2=gl_ux[0]+sprtW; + sSprite_vy2=gl_vy[0]+sprtH; + + assignTextureSprite(); + + if(iFilterType>4) + DrawMultiFilterSprite(); + else + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); + + if(bDrawMultiPass) + { + SetSemiTransMulti(1); + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); + } + + if(ubOpaqueDraw) + { + SetZMask4O(); + if(bUseMultiPass) SetOpaqueColor(gpuData[0]); + DEFOPAQUEON + +/* if(bSmallAlpha && iFilterType<=2) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + SetZMask4O(); + } +*/ + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); + DEFOPAQUEOFF + } + + if(sTypeRest && type<4) + { + if(sTypeRest&1 && type==1) primSprtSRest(baseAddr,4); + if(sTypeRest&2 && type==2) primSprtSRest(baseAddr,5); + if(sTypeRest==3 && type==3) primSprtSRest(baseAddr,6); + } +} + +void primSprtS(u8 * baseAddr) +{ + unsigned long *gpuData = ((unsigned long *) baseAddr); + short *sgpuData = ((short *) baseAddr); + + short s;unsigned short sTypeRest=0; + + sprtX = sgpuData[2]; + sprtY = sgpuData[3]; + sprtW = sgpuData[6] & 0x3ff; + sprtH = sgpuData[7] & 0x1ff; + + if(!sprtH) return; + if(!sprtW) return; + + iSpriteTex=1; + + // do texture stuff + gl_ux[0]=gl_ux[3]=baseAddr[8];//gpuData[2]&0xff; + gl_vy[0]=gl_vy[1]=baseAddr[9];//(gpuData[2]>>8)&0xff; + + if(usMirror & 0x1000) + { + s=gl_ux[0]; + s-=sprtW-1; + if(s<0) {s=0;} + gl_ux[0]=gl_ux[3]=s; + } + if(usMirror & 0x2000) + { + s=gl_vy[0]; + s-=sprtH-1; + if(s<0) {s=0;} + gl_vy[0]=gl_vy[1]=s; + } + + sSprite_ux2=s=gl_ux[0]+sprtW; + if(s) s--; + if(s>255) s=255; + gl_ux[1]=gl_ux[2]=s; + sSprite_vy2=s=gl_vy[0]+sprtH; + if(s) s--; + if(s>255) s=255; + gl_vy[2]=gl_vy[3]=s; + + if(!bUsingTWin) + { + if(sSprite_ux2>256) + {sprtW=256-gl_ux[0];sSprite_ux2=256;sTypeRest+=1;} + if(sSprite_vy2>256) + {sprtH=256-gl_vy[0];sSprite_vy2=256;sTypeRest+=2;} + } + + lx0 = sprtX; + ly0 = sprtY; + + offsetST(); + + ulClutID=(gpuData[2]>>16); + + bDrawTextured = TRUE; + bDrawSmoothShaded = FALSE; + SetRenderState(gpuData[0]); + +/* if(iOffscreenDrawing) + { + offsetPSX4(); + + if(bDrawOffscreen4()) + { + InvalidateTextureAreaEx(); + SetRenderColor(gpuData[0]); + lx0-=PSXDisplay.DrawOffset.x; + ly0-=PSXDisplay.DrawOffset.y; + if(bUsingTWin) DrawSoftwareSpriteTWin(baseAddr,sprtW,sprtH); + else + if(usMirror) DrawSoftwareSpriteMirror(baseAddr,sprtW,sprtH); + else + DrawSoftwareSprite(baseAddr,sprtW,sprtH,baseAddr[8],baseAddr[9]); + } + } +*/ + SetRenderMode(gpuData[0], TRUE); + SetZMask4SP(); + + if((dwActFixes&1) && gTexFrameName && gTexName==gTexFrameName) + {iSpriteTex=0;return;} + + sSprite_ux2=gl_ux[0]+sprtW; + sSprite_vy2=gl_vy[0]+sprtH; + + assignTextureSprite(); + + if(iFilterType>4) + DrawMultiFilterSprite(); + else + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); + + if(bDrawMultiPass) + { + SetSemiTransMulti(1); + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); + } + + if(ubOpaqueDraw) + { + SetZMask4O(); + if(bUseMultiPass) SetOpaqueColor(gpuData[0]); + DEFOPAQUEON + +/* if(bSmallAlpha && iFilterType<=2) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + SetZMask4O(); + } +*/ + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); + DEFOPAQUEOFF + } + + if(sTypeRest) + { + if(sTypeRest&1) primSprtSRest(baseAddr,1); + if(sTypeRest&2) primSprtSRest(baseAddr,2); + if(sTypeRest==3) primSprtSRest(baseAddr,3); + } + + iSpriteTex=0; + iDrawnSomething=1; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: flat shaded Poly4 +//////////////////////////////////////////////////////////////////////// + +void primPolyF4(u8 *baseAddr) +{ + unsigned long *gpuData = ((unsigned long *) baseAddr); + short *sgpuData = ((short *) baseAddr); + + lx0 = sgpuData[2]; + ly0 = sgpuData[3]; + lx1 = sgpuData[4]; + ly1 = sgpuData[5]; + lx2 = sgpuData[6]; + ly2 = sgpuData[7]; + lx3 = sgpuData[8]; + ly3 = sgpuData[9]; + + if(offset4()) return; + + bDrawTextured = FALSE; + bDrawSmoothShaded = FALSE; + SetRenderState(gpuData[0]); + +/* if(iOffscreenDrawing) + { + offsetPSX4(); + if(bDrawOffscreen4()) + { + InvalidateTextureAreaEx(); + drawPoly4F(gpuData[0]); + } + } +*/ + SetRenderMode(gpuData[0], FALSE); + SetZMask4NT(); + + vertex[0].c.lcol=gpuData[0];vertex[0].c.col[3]=ubGloColAlpha; + SETCOL(vertex[0]); + + PRIMdrawTri2(&vertex[0], &vertex[1], &vertex[2],&vertex[3]); + + iDrawnSomething=1; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: smooth shaded Poly4 +//////////////////////////////////////////////////////////////////////// + +void primPolyG4(u8 * baseAddr); + +BOOL bDrawOffscreenFrontFF9G4(void) +{ + if(lx0< PSXDisplay.DisplayPosition.x) return FALSE; // must be complete in front + if(lx0> PSXDisplay.DisplayEnd.x) return FALSE; + if(ly0< PSXDisplay.DisplayPosition.y) return FALSE; + if(ly0> PSXDisplay.DisplayEnd.y) return FALSE; + if(lx1< PSXDisplay.DisplayPosition.x) return FALSE; + if(lx1> PSXDisplay.DisplayEnd.x) return FALSE; + if(ly1< PSXDisplay.DisplayPosition.y) return FALSE; + if(ly1> PSXDisplay.DisplayEnd.y) return FALSE; + if(lx2< PSXDisplay.DisplayPosition.x) return FALSE; + if(lx2> PSXDisplay.DisplayEnd.x) return FALSE; + if(ly2< PSXDisplay.DisplayPosition.y) return FALSE; + if(ly2> PSXDisplay.DisplayEnd.y) return FALSE; + if(lx3< PSXDisplay.DisplayPosition.x) return FALSE; + if(lx3> PSXDisplay.DisplayEnd.x) return FALSE; + if(ly3< PSXDisplay.DisplayPosition.y) return FALSE; + if(ly3> PSXDisplay.DisplayEnd.y) return FALSE; + return TRUE; +} + +BOOL bCheckFF9G4(u8 * baseAddr) +{ + static u8 pFF9G4Cache[32]; + static int iFF9Fix=0; + + if(baseAddr) + { + if(iFF9Fix==0) + { + if(bDrawOffscreenFrontFF9G4()) + { + short *sgpuData = ((short *) pFF9G4Cache); + iFF9Fix=2; + memcpy(pFF9G4Cache,baseAddr,32); + + if(sgpuData[2]==142) + { + sgpuData[2] +=65; + sgpuData[10]+=65; + } + return TRUE; + } + else iFF9Fix=1; + } + return FALSE; + } + + if(iFF9Fix==2) + { + long labr=GlobalTextABR; + GlobalTextABR=1; + primPolyG4(pFF9G4Cache); + GlobalTextABR=labr; + } + iFF9Fix=0; + + return FALSE; +} + +//////////////////////////////////////////////////////////////////////// + +void primPolyG4(u8 * baseAddr) +{ + unsigned long *gpuData = (unsigned long *)baseAddr; + short *sgpuData = ((short *) baseAddr); + + lx0 = sgpuData[2]; + ly0 = sgpuData[3]; + lx1 = sgpuData[6]; + ly1 = sgpuData[7]; + lx2 = sgpuData[10]; + ly2 = sgpuData[11]; + lx3 = sgpuData[14]; + ly3 = sgpuData[15]; + + if(offset4()) return; + + bDrawTextured = FALSE; + bDrawSmoothShaded = TRUE; + SetRenderState(gpuData[0]); + +/* if(iOffscreenDrawing) + { + offsetPSX4(); + + if((dwActFixes&512) && bCheckFF9G4(baseAddr)) return; + + if(bDrawOffscreen4()) + { + InvalidateTextureAreaEx(); + drawPoly4G(gpuData[0], gpuData[2], gpuData[4], gpuData[6]); + } + } +*/ + SetRenderMode(gpuData[0], FALSE); + SetZMask4NT(); + + vertex[0].c.lcol=gpuData[0]; + vertex[1].c.lcol=gpuData[2]; + vertex[2].c.lcol=gpuData[4]; + vertex[3].c.lcol=gpuData[6]; + + vertex[0].c.col[3]=vertex[1].c.col[3]=vertex[2].c.col[3]=vertex[3].c.col[3]=ubGloAlpha; + + + PRIMdrawGouraudTri2Color(&vertex[0],&vertex[1], &vertex[2], &vertex[3]); + + iDrawnSomething=1; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: flat shaded Texture3 +//////////////////////////////////////////////////////////////////////// + +BOOL DoLineCheck(unsigned long * gpuData) +{ + BOOL bQuad=FALSE;short dx,dy; + + if(lx0==lx1) + { + dx=lx0-lx2;if(dx<0) dx=-dx; + + if(ly1==ly2) + { + dy=ly1-ly0;if(dy<0) dy=-dy; + if(dx<=1) + { + vertex[3]=vertex[2]; + vertex[2]=vertex[0]; + vertex[2].x=vertex[3].x; + } + else + if(dy<=1) + { + vertex[3]=vertex[2]; + vertex[2].y=vertex[0].y; + } + else return FALSE; + + bQuad=TRUE; + } + else + if(ly0==ly2) + { + dy=ly0-ly1;if(dy<0) dy=-dy; + if(dx<=1) + { + vertex[3]=vertex[1]; + vertex[3].x=vertex[2].x; + } + else + if(dy<=1) + { + vertex[3]=vertex[2]; + vertex[3].y=vertex[1].y; + } + else return FALSE; + + bQuad=TRUE; + } + } + + if(lx0==lx2) + { + dx=lx0-lx1;if(dx<0) dx=-dx; + + if(ly2==ly1) + { + dy=ly2-ly0;if(dy<0) dy=-dy; + if(dx<=1) + { + vertex[3]=vertex[1]; + vertex[1]=vertex[0]; + vertex[1].x=vertex[3].x; + } + else + if(dy<=1) + { + vertex[3]=vertex[1]; + vertex[1].y=vertex[0].y; + } + else return FALSE; + + bQuad=TRUE; + } + else + if(ly0==ly1) + { + dy=ly2-ly0;if(dy<0) dy=-dy; + if(dx<=1) + { + vertex[3]=vertex[2]; + vertex[3].x=vertex[1].x; + } + else + if(dy<=1) + { + vertex[3]=vertex[1]; + vertex[3].y=vertex[2].y; + } + else return FALSE; + + bQuad=TRUE; + } + } + + if(lx1==lx2) + { + dx=lx1-lx0;if(dx<0) dx=-dx; + + if(ly1==ly0) + { + dy=ly1-ly2;if(dy<0) dy=-dy; + + if(dx<=1) + { + vertex[3]=vertex[2]; + vertex[2].x=vertex[0].x; + } + else + if(dy<=1) + { + vertex[3]=vertex[2]; + vertex[2]=vertex[0]; + vertex[2].y=vertex[3].y; + } + else return FALSE; + + bQuad=TRUE; + } + else + if(ly2==ly0) + { + dy=ly2-ly1;if(dy<0) dy=-dy; + + if(dx<=1) + { + vertex[3]=vertex[1]; + vertex[1].x=vertex[0].x; + } + else + if(dy<=1) + { + vertex[3]=vertex[1]; + vertex[1]=vertex[0]; + vertex[1].y=vertex[3].y; + } + else return FALSE; + + bQuad=TRUE; + } + } + + if(!bQuad) return FALSE; + + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[3], &vertex[2]); + + if(bDrawMultiPass) + { + SetSemiTransMulti(1); + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[3], &vertex[2]); + } + + if(ubOpaqueDraw) + { + SetZMask4O(); + if(bUseMultiPass) SetOpaqueColor(gpuData[0]); + DEFOPAQUEON + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[3], &vertex[2]); + DEFOPAQUEOFF + } + + iDrawnSomething=1; + + return TRUE; +} + +//////////////////////////////////////////////////////////////////////// + +void primPolyFT3(u8 * baseAddr) +{ + unsigned long *gpuData = ((unsigned long *) baseAddr); + short *sgpuData = ((short *) baseAddr); + + lx0 = sgpuData[2]; + ly0 = sgpuData[3]; + lx1 = sgpuData[6]; + ly1 = sgpuData[7]; + lx2 = sgpuData[10]; + ly2 = sgpuData[11]; + + if(offset3()) return; + + // do texture UV coordinates stuff + gl_ux[0]=gl_ux[3]=baseAddr[8];//gpuData[2]&0xff; + gl_vy[0]=gl_vy[3]=baseAddr[9];//(gpuData[2]>>8)&0xff; + gl_ux[1]=baseAddr[16];//gpuData[4]&0xff; + gl_vy[1]=baseAddr[17];//(gpuData[4]>>8)&0xff; + gl_ux[2]=baseAddr[24];//gpuData[6]&0xff; + gl_vy[2]=baseAddr[25];//(gpuData[6]>>8)&0xff; + + UpdateGlobalTP((unsigned short)(gpuData[4]>>16)); + ulClutID=gpuData[2]>>16; + + bDrawTextured = TRUE; + bDrawSmoothShaded = FALSE; + SetRenderState(gpuData[0]); + +/* if(iOffscreenDrawing) + { + offsetPSX3(); + if(bDrawOffscreen3()) + { + InvalidateTextureAreaEx(); + SetRenderColor(gpuData[0]); + drawPoly3FT(baseAddr); + } + } +*/ + SetRenderMode(gpuData[0], TRUE); + SetZMask3(); + + assignTexture3(); + + if(!(dwActFixes&0x10)) + { + if(DoLineCheck(gpuData)) return; + } + + PRIMdrawTexturedTri(&vertex[0], &vertex[1], &vertex[2]); + + if(bDrawMultiPass) + { + SetSemiTransMulti(1); + PRIMdrawTexturedTri(&vertex[0], &vertex[1], &vertex[2]); + } + + if(ubOpaqueDraw) + { + SetZMask3O(); + if(bUseMultiPass) SetOpaqueColor(gpuData[0]); + DEFOPAQUEON + PRIMdrawTexturedTri(&vertex[0], &vertex[1], &vertex[2]); + DEFOPAQUEOFF + } + + iDrawnSomething=1; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: flat shaded Texture4 +//////////////////////////////////////////////////////////////////////// + +#define ST_FAC 255.99f + +void RectTexAlign(void) +{ + int UFlipped = FALSE; + int VFlipped = FALSE; + + if(gTexName==gTexFrameName) return; + + if(ly0==ly1) + { + if(!((lx1==lx3 && ly3==ly2 && lx2==lx0) || + (lx1==lx2 && ly2==ly3 && lx3==lx0))) + return; + + if(ly0 vertex[2].tow) + VFlipped = 1; + } + else + { + if (vertex[0].tow < vertex[2].tow) + VFlipped = 2; + } + } + else + if(ly0==ly2) + { + if(!((lx2==lx3 && ly3==ly1 && lx1==lx0) || + (lx2==lx1 && ly1==ly3 && lx3==lx0))) + return; + + if(ly0 vertex[1].tow) + VFlipped = 3; + } + else + { + if (vertex[0].tow < vertex[1].tow) + VFlipped = 4; + } + } + else + if(ly0==ly3) + { + if(!((lx3==lx2 && ly2==ly1 && lx1==lx0) || + (lx3==lx1 && ly1==ly2 && lx2==lx0))) + return; + + if(ly0 vertex[1].tow) + VFlipped = 5; + } + else + { + if (vertex[0].tow < vertex[1].tow) + VFlipped = 6; + } + } + else return; + + if(lx0==lx1) + { + if(lx0 vertex[2].sow) + UFlipped = 1; + } + else + { + if (vertex[0].sow < vertex[2].sow) + UFlipped = 2; + } + } + else + if(lx0==lx2) + { + if(lx0 vertex[1].sow) + UFlipped = 3; + } + else + { + if (vertex[0].sow < vertex[1].sow) + UFlipped = 4; + } + } + else + if(lx0==lx3) + { + if(lx0 vertex[1].sow) + UFlipped = 5; + } + else + { + if (vertex[0].sow < vertex[1].sow) + UFlipped = 6; + } + } + + if (UFlipped) + { +#ifdef OWNSCALE + if(bUsingTWin) + { + switch(UFlipped) + { + case 1: + vertex[2].sow+=0.95f/TWin.UScaleFactor; + vertex[3].sow+=0.95f/TWin.UScaleFactor; + break; + case 2: + vertex[0].sow+=0.95f/TWin.UScaleFactor; + vertex[1].sow+=0.95f/TWin.UScaleFactor; + break; + case 3: + vertex[1].sow+=0.95f/TWin.UScaleFactor; + vertex[3].sow+=0.95f/TWin.UScaleFactor; + break; + case 4: + vertex[0].sow+=0.95f/TWin.UScaleFactor; + vertex[2].sow+=0.95f/TWin.UScaleFactor; + break; + case 5: + vertex[1].sow+=0.95f/TWin.UScaleFactor; + vertex[2].sow+=0.95f/TWin.UScaleFactor; + break; + case 6: + vertex[0].sow+=0.95f/TWin.UScaleFactor; + vertex[3].sow+=0.95f/TWin.UScaleFactor; + break; + } + } + else + { + switch(UFlipped) + { + case 1: + vertex[2].sow+=1.0f/ST_FAC; + vertex[3].sow+=1.0f/ST_FAC; + break; + case 2: + vertex[0].sow+=1.0f/ST_FAC; + vertex[1].sow+=1.0f/ST_FAC; + break; + case 3: + vertex[1].sow+=1.0f/ST_FAC; + vertex[3].sow+=1.0f/ST_FAC; + break; + case 4: + vertex[0].sow+=1.0f/ST_FAC; + vertex[2].sow+=1.0f/ST_FAC; + break; + case 5: + vertex[1].sow+=1.0f/ST_FAC; + vertex[2].sow+=1.0f/ST_FAC; + break; + case 6: + vertex[0].sow+=1.0f/ST_FAC; + vertex[3].sow+=1.0f/ST_FAC; + break; + } + } +#else + if(bUsingTWin) + { + switch(UFlipped) + { + case 1: + vertex[2].sow+=1.0f/TWin.UScaleFactor; + vertex[3].sow+=1.0f/TWin.UScaleFactor; + break; + case 2: + vertex[0].sow+=1.0f/TWin.UScaleFactor; + vertex[1].sow+=1.0f/TWin.UScaleFactor; + break; + case 3: + vertex[1].sow+=1.0f/TWin.UScaleFactor; + vertex[3].sow+=1.0f/TWin.UScaleFactor; + break; + case 4: + vertex[0].sow+=1.0f/TWin.UScaleFactor; + vertex[2].sow+=1.0f/TWin.UScaleFactor; + break; + case 5: + vertex[1].sow+=1.0f/TWin.UScaleFactor; + vertex[2].sow+=1.0f/TWin.UScaleFactor; + break; + case 6: + vertex[0].sow+=1.0f/TWin.UScaleFactor; + vertex[3].sow+=1.0f/TWin.UScaleFactor; + break; + } + } + else + { + switch(UFlipped) + { + case 1: + vertex[2].sow+=1.0f; + vertex[3].sow+=1.0f; + break; + case 2: + vertex[0].sow+=1.0f; + vertex[1].sow+=1.0f; + break; + case 3: + vertex[1].sow+=1.0f; + vertex[3].sow+=1.0f; + break; + case 4: + vertex[0].sow+=1.0f; + vertex[2].sow+=1.0f; + break; + case 5: + vertex[1].sow+=1.0f; + vertex[2].sow+=1.0f; + break; + case 6: + vertex[0].sow+=1.0f; + vertex[3].sow+=1.0f; + break; + } + } +#endif + } + + if (VFlipped) + { +#ifdef OWNSCALE + if(bUsingTWin) + { + switch(VFlipped) + { + case 1: + vertex[2].tow+=0.95f/TWin.VScaleFactor; + vertex[3].tow+=0.95f/TWin.VScaleFactor; + break; + case 2: + vertex[0].tow+=0.95f/TWin.VScaleFactor; + vertex[1].tow+=0.95f/TWin.VScaleFactor; + break; + case 3: + vertex[1].tow+=0.95f/TWin.VScaleFactor; + vertex[3].tow+=0.95f/TWin.VScaleFactor; + break; + case 4: + vertex[0].tow+=0.95f/TWin.VScaleFactor; + vertex[2].tow+=0.95f/TWin.VScaleFactor; + break; + case 5: + vertex[1].tow+=0.95f/TWin.VScaleFactor; + vertex[2].tow+=0.95f/TWin.VScaleFactor; + break; + case 6: + vertex[0].tow+=0.95f/TWin.VScaleFactor; + vertex[3].tow+=0.95f/TWin.VScaleFactor; + break; + } + } + else + { + switch(VFlipped) + { + case 1: + vertex[2].tow+=1.0f/ST_FAC; + vertex[3].tow+=1.0f/ST_FAC; + break; + case 2: + vertex[0].tow+=1.0f/ST_FAC; + vertex[1].tow+=1.0f/ST_FAC; + break; + case 3: + vertex[1].tow+=1.0f/ST_FAC; + vertex[3].tow+=1.0f/ST_FAC; + break; + case 4: + vertex[0].tow+=1.0f/ST_FAC; + vertex[2].tow+=1.0f/ST_FAC; + break; + case 5: + vertex[1].tow+=1.0f/ST_FAC; + vertex[2].tow+=1.0f/ST_FAC; + break; + case 6: + vertex[0].tow+=1.0f/ST_FAC; + vertex[3].tow+=1.0f/ST_FAC; + break; + } + } +#else + if(bUsingTWin) + { + switch(VFlipped) + { + case 1: + vertex[2].tow+=1.0f/TWin.VScaleFactor; + vertex[3].tow+=1.0f/TWin.VScaleFactor; + break; + case 2: + vertex[0].tow+=1.0f/TWin.VScaleFactor; + vertex[1].tow+=1.0f/TWin.VScaleFactor; + break; + case 3: + vertex[1].tow+=1.0f/TWin.VScaleFactor; + vertex[3].tow+=1.0f/TWin.VScaleFactor; + break; + case 4: + vertex[0].tow+=1.0f/TWin.VScaleFactor; + vertex[2].tow+=1.0f/TWin.VScaleFactor; + break; + case 5: + vertex[1].tow+=1.0f/TWin.VScaleFactor; + vertex[2].tow+=1.0f/TWin.VScaleFactor; + break; + case 6: + vertex[0].tow+=1.0f/TWin.VScaleFactor; + vertex[3].tow+=1.0f/TWin.VScaleFactor; + break; + } + } + else + { + switch(VFlipped) + { + case 1: + vertex[2].tow+=1.0f; + vertex[3].tow+=1.0f; + break; + case 2: + vertex[0].tow+=1.0f; + vertex[1].tow+=1.0f; + break; + case 3: + vertex[1].tow+=1.0f; + vertex[3].tow+=1.0f; + break; + case 4: + vertex[0].tow+=1.0f; + vertex[2].tow+=1.0f; + break; + case 5: + vertex[1].tow+=1.0f; + vertex[2].tow+=1.0f; + break; + case 6: + vertex[0].tow+=1.0f; + vertex[3].tow+=1.0f; + break; + } + } +#endif + } + +} + +void primPolyFT4(u8 * baseAddr) +{ + unsigned long *gpuData = ((unsigned long *) baseAddr); + short *sgpuData = ((short *) baseAddr); + + lx0 = sgpuData[2]; + ly0 = sgpuData[3]; + lx1 = sgpuData[6]; + ly1 = sgpuData[7]; + lx2 = sgpuData[10]; + ly2 = sgpuData[11]; + lx3 = sgpuData[14]; + ly3 = sgpuData[15]; + + if(offset4()) return; + + gl_vy[0]=baseAddr[9];//((gpuData[2]>>8)&0xff); + gl_vy[1]=baseAddr[17];//((gpuData[4]>>8)&0xff); + gl_vy[2]=baseAddr[25];//((gpuData[6]>>8)&0xff); + gl_vy[3]=baseAddr[33];//((gpuData[8]>>8)&0xff); + + gl_ux[0]=baseAddr[8];//(gpuData[2]&0xff); + gl_ux[1]=baseAddr[16];//(gpuData[4]&0xff); + gl_ux[2]=baseAddr[24];//(gpuData[6]&0xff); + gl_ux[3]=baseAddr[32];//(gpuData[8]&0xff); + + UpdateGlobalTP((unsigned short)(gpuData[4]>>16)); + ulClutID=(gpuData[2]>>16); + + bDrawTextured = TRUE; + bDrawSmoothShaded = FALSE; + SetRenderState(gpuData[0]); + +/* if(iOffscreenDrawing) + { + offsetPSX4(); + if(bDrawOffscreen4()) + { + InvalidateTextureAreaEx(); + SetRenderColor(gpuData[0]); + drawPoly4FT(baseAddr); + } + } +*/ + SetRenderMode(gpuData[0], TRUE); + + SetZMask4(); + + assignTexture4(); + + RectTexAlign(); + + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[3], &vertex[2]); + + if(bDrawMultiPass) + { + SetSemiTransMulti(1); + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[3], &vertex[2]); + } + + if(ubOpaqueDraw) + { + SetZMask4O(); + if(bUseMultiPass) SetOpaqueColor(gpuData[0]); + DEFOPAQUEON + +/* if(bSmallAlpha && iFilterType<=2) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[3], &vertex[2]); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + SetZMask4O(); + } +*/ + + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[3], &vertex[2]); + DEFOPAQUEOFF + } + + iDrawnSomething=1; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: smooth shaded Texture3 +//////////////////////////////////////////////////////////////////////// + +void primPolyGT3(u8 *baseAddr) +{ + unsigned long *gpuData = ((unsigned long *) baseAddr); + short *sgpuData = ((short *) baseAddr); + + lx0 = sgpuData[2]; + ly0 = sgpuData[3]; + lx1 = sgpuData[8]; + ly1 = sgpuData[9]; + lx2 = sgpuData[14]; + ly2 = sgpuData[15]; + + if(offset3()) return; + + // do texture stuff + gl_ux[0]=gl_ux[3]=baseAddr[8];//gpuData[2]&0xff; + gl_vy[0]=gl_vy[3]=baseAddr[9];//(gpuData[2]>>8)&0xff; + gl_ux[1]=baseAddr[20];//gpuData[5]&0xff; + gl_vy[1]=baseAddr[21];//(gpuData[5]>>8)&0xff; + gl_ux[2]=baseAddr[32];//gpuData[8]&0xff; + gl_vy[2]=baseAddr[33];//(gpuData[8]>>8)&0xff; + + UpdateGlobalTP((unsigned short)(gpuData[5]>>16)); + ulClutID=(gpuData[2]>>16); + + bDrawTextured = TRUE; + bDrawSmoothShaded = TRUE; + SetRenderState(gpuData[0]); + +/* if(iOffscreenDrawing) + { + offsetPSX3(); + if(bDrawOffscreen3()) + { + InvalidateTextureAreaEx(); + drawPoly3GT(baseAddr); + } + } +*/ + SetRenderMode(gpuData[0], FALSE); + SetZMask3(); + + assignTexture3(); + + if(bDrawNonShaded) + { + //if(!bUseMultiPass) vertex[0].lcol=DoubleBGR2RGB(gpuData[0]); else vertex[0].lcol=gpuData[0]; + // eat this... +/* if(bGLBlend) vertex[0].c.lcol=0x7f7f7f; + else */vertex[0].c.lcol=0xffffff; + vertex[0].c.col[3]=ubGloAlpha; + SETCOL(vertex[0]); + + PRIMdrawTexturedTri(&vertex[0], &vertex[1], &vertex[2]); + + if(ubOpaqueDraw) + { + SetZMask3O(); + DEFOPAQUEON + PRIMdrawTexturedTri(&vertex[0], &vertex[1], &vertex[2]); + DEFOPAQUEOFF + } + return; + } + +/* if(!bUseMultiPass && !bGLBlend) + { + */ vertex[0].c.lcol=DoubleBGR2RGB(gpuData[0]); + vertex[1].c.lcol=DoubleBGR2RGB(gpuData[3]); + vertex[2].c.lcol=DoubleBGR2RGB(gpuData[6]); + /*} + else + { + vertex[0].c.lcol=gpuData[0]; + vertex[1].c.lcol=gpuData[3]; + vertex[2].c.lcol=gpuData[6]; + }*/ + vertex[0].c.col[3]=vertex[1].c.col[3]=vertex[2].c.col[3]=ubGloAlpha; + + PRIMdrawTexGouraudTriColor(&vertex[0], &vertex[1], &vertex[2]); + + if(bDrawMultiPass) + { + SetSemiTransMulti(1); + PRIMdrawTexGouraudTriColor(&vertex[0], &vertex[1], &vertex[2]); + } + + if(ubOpaqueDraw) + { + SetZMask3O(); + if(bUseMultiPass) + { + vertex[0].c.lcol=DoubleBGR2RGB(gpuData[0]); + vertex[1].c.lcol=DoubleBGR2RGB(gpuData[3]); + vertex[2].c.lcol=DoubleBGR2RGB(gpuData[6]); + vertex[0].c.col[3]=vertex[1].c.col[3]=vertex[2].c.col[3]=ubGloAlpha; + } + DEFOPAQUEON + PRIMdrawTexGouraudTriColor(&vertex[0], &vertex[1], &vertex[2]); + DEFOPAQUEOFF + } + + iDrawnSomething=1; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: smooth shaded Poly3 +//////////////////////////////////////////////////////////////////////// + +void primPolyG3(u8 *baseAddr) +{ + unsigned long *gpuData = ((unsigned long *) baseAddr); + short *sgpuData = ((short *) baseAddr); + + lx0 = sgpuData[2]; + ly0 = sgpuData[3]; + lx1 = sgpuData[6]; + ly1 = sgpuData[7]; + lx2 = sgpuData[10]; + ly2 = sgpuData[11]; + + if(offset3()) return; + + bDrawTextured = FALSE; + bDrawSmoothShaded = TRUE; + SetRenderState(gpuData[0]); + +/* if(iOffscreenDrawing) + { + offsetPSX3(); + if(bDrawOffscreen3()) + { + InvalidateTextureAreaEx(); + drawPoly3G(gpuData[0], gpuData[2], gpuData[4]); + } + } +*/ + SetRenderMode(gpuData[0], FALSE); + SetZMask3NT(); + + vertex[0].c.lcol=gpuData[0]; + vertex[1].c.lcol=gpuData[2]; + vertex[2].c.lcol=gpuData[4]; + vertex[0].c.col[3]=vertex[1].c.col[3]=vertex[2].c.col[3]=ubGloColAlpha; + + PRIMdrawGouraudTriColor(&vertex[0], &vertex[1], &vertex[2]); + + iDrawnSomething=1; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: smooth shaded Texture4 +//////////////////////////////////////////////////////////////////////// + +void primPolyGT4(u8 *baseAddr) +{ + unsigned long *gpuData = ((unsigned long *) baseAddr); + short *sgpuData = ((short *) baseAddr); + + lx0 = sgpuData[2]; + ly0 = sgpuData[3]; + lx1 = sgpuData[8]; + ly1 = sgpuData[9]; + lx2 = sgpuData[14]; + ly2 = sgpuData[15]; + lx3 = sgpuData[20]; + ly3 = sgpuData[21]; + + if(offset4()) return; + + // do texture stuff + gl_ux[0]=baseAddr[8];//gpuData[2]&0xff; + gl_vy[0]=baseAddr[9];//(gpuData[2]>>8)&0xff; + gl_ux[1]=baseAddr[20];//gpuData[5]&0xff; + gl_vy[1]=baseAddr[21];//(gpuData[5]>>8)&0xff; + gl_ux[2]=baseAddr[32];//gpuData[8]&0xff; + gl_vy[2]=baseAddr[33];//(gpuData[8]>>8)&0xff; + gl_ux[3]=baseAddr[44];//gpuData[11]&0xff; + gl_vy[3]=baseAddr[45];//(gpuData[11]>>8)&0xff; + + UpdateGlobalTP((unsigned short)(gpuData[5]>>16)); + ulClutID=(gpuData[2]>>16); + + bDrawTextured = TRUE; + bDrawSmoothShaded = TRUE; + SetRenderState(gpuData[0]); + +/* if(iOffscreenDrawing) + { + offsetPSX4(); + if(bDrawOffscreen4()) + { + InvalidateTextureAreaEx(); + drawPoly4GT(baseAddr); + } + } +*/ + SetRenderMode(gpuData[0], FALSE); + SetZMask4(); + + assignTexture4(); + + RectTexAlign(); + + if(bDrawNonShaded) + { + //if(!bUseMultiPass) vertex[0].lcol=DoubleBGR2RGB(gpuData[0]); else vertex[0].lcol=gpuData[0]; +/* if(bGLBlend) vertex[0].c.lcol=0x7f7f7f; + else */vertex[0].c.lcol=0xffffff; + vertex[0].c.col[3]=ubGloAlpha; + SETCOL(vertex[0]); + + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[3], &vertex[2]); + + if(ubOpaqueDraw) + { + SetZMask4O(); + ubGloAlpha=ubGloColAlpha=0xff; + DEFOPAQUEON + PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[3], &vertex[2]); + DEFOPAQUEOFF + } + return; + } + +// if(!bUseMultiPass && !bGLBlend) + { + vertex[0].c.lcol=DoubleBGR2RGB(gpuData[0]); + vertex[1].c.lcol=DoubleBGR2RGB(gpuData[3]); + vertex[2].c.lcol=DoubleBGR2RGB(gpuData[6]); + vertex[3].c.lcol=DoubleBGR2RGB(gpuData[9]); + } + /*else + { + vertex[0].c.lcol=gpuData[0]; + vertex[1].c.lcol=gpuData[3]; + vertex[2].c.lcol=gpuData[6]; + vertex[3].c.lcol=gpuData[9]; + }*/ + + vertex[0].c.col[3]=vertex[1].c.col[3]=vertex[2].c.col[3]=vertex[3].c.col[3]=ubGloAlpha; + + PRIMdrawTexGouraudTriColorQuad(&vertex[0], &vertex[1], &vertex[3],&vertex[2]); + + if(bDrawMultiPass) + { + SetSemiTransMulti(1); + PRIMdrawTexGouraudTriColorQuad(&vertex[0], &vertex[1], &vertex[3],&vertex[2]); + } + + if(ubOpaqueDraw) + { + SetZMask4O(); + if(bUseMultiPass) + { + vertex[0].c.lcol=DoubleBGR2RGB(gpuData[0]); + vertex[1].c.lcol=DoubleBGR2RGB(gpuData[3]); + vertex[2].c.lcol=DoubleBGR2RGB(gpuData[6]); + vertex[3].c.lcol=DoubleBGR2RGB(gpuData[9]); + vertex[0].c.col[3]=vertex[1].c.col[3]=vertex[2].c.col[3]=vertex[3].c.col[3]=ubGloAlpha; + } + ubGloAlpha=ubGloColAlpha=0xff; + DEFOPAQUEON + PRIMdrawTexGouraudTriColorQuad(&vertex[0], &vertex[1], &vertex[3],&vertex[2]); + DEFOPAQUEOFF + } + + iDrawnSomething=1; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: smooth shaded Poly3 +//////////////////////////////////////////////////////////////////////// + +void primPolyF3(u8 *baseAddr) +{ + unsigned long *gpuData = ((unsigned long *) baseAddr); + short *sgpuData = ((short *) baseAddr); + + lx0 = sgpuData[2]; + ly0 = sgpuData[3]; + lx1 = sgpuData[4]; + ly1 = sgpuData[5]; + lx2 = sgpuData[6]; + ly2 = sgpuData[7]; + + if(offset3()) return; + + bDrawTextured = FALSE; + bDrawSmoothShaded = FALSE; + SetRenderState(gpuData[0]); + +/* if(iOffscreenDrawing) + { + offsetPSX3(); + if(bDrawOffscreen3()) + { + InvalidateTextureAreaEx(); + drawPoly3F(gpuData[0]); + } + } +*/ + SetRenderMode(gpuData[0], FALSE); + SetZMask3NT(); + + vertex[0].c.lcol=gpuData[0]; + vertex[0].c.col[3]=ubGloColAlpha; + SETCOL(vertex[0]); + + PRIMdrawTri(&vertex[0], &vertex[1], &vertex[2]); + + iDrawnSomething=1; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: skipping shaded polylines +//////////////////////////////////////////////////////////////////////// + +void primLineGSkip(u8 *baseAddr) +{ + unsigned long *gpuData = ((unsigned long *) baseAddr); + short *sgpuData = ((short *) baseAddr); + int iMax=255; + int i=2; + + lx1 = sgpuData[2]; + ly1 = sgpuData[3]; + + while(!(((gpuData[i] & 0xF000F000) == 0x50005000) && i>=4)) + { + i++; + + ly1 = (short)((gpuData[i]>>16) & 0xffff); + lx1 = (short)(gpuData[i] & 0xffff); + + i++;if(i>iMax) break; + } +} + +//////////////////////////////////////////////////////////////////////// +// cmd: shaded polylines +//////////////////////////////////////////////////////////////////////// + +void primLineGEx(u8 *baseAddr) +{ + unsigned long *gpuData = ((unsigned long *) baseAddr); + int iMax=255; + short cx0,cx1,cy0,cy1;int i;BOOL bDraw=TRUE; + + bDrawTextured = FALSE; + bDrawSmoothShaded = TRUE; + SetRenderState(gpuData[0]); + SetRenderMode(gpuData[0], FALSE); + SetZMask4NT(); + + vertex[0].c.lcol=vertex[3].c.lcol=gpuData[0]; + vertex[0].c.col[3]=vertex[3].c.col[3]=ubGloColAlpha; + ly1 = (short)((gpuData[1]>>16) & 0xffff); + lx1 = (short)(gpuData[1] & 0xffff); + + i=2; + + //while((gpuData[i]>>24)!=0x55) + //while((gpuData[i]&0x50000000)!=0x50000000) + // currently best way to check for poly line end: + while(!(((gpuData[i] & 0xF000F000) == 0x50005000) && i>=4)) + { + ly0 = ly1;lx0=lx1; + vertex[1].c.lcol=vertex[2].c.lcol=vertex[0].c.lcol; + vertex[0].c.lcol=vertex[3].c.lcol=gpuData[i]; + vertex[0].c.col[3]=vertex[3].c.col[3]=ubGloColAlpha; + + i++; + + ly1 = (short)((gpuData[i]>>16) & 0xffff); + lx1 = (short)(gpuData[i] & 0xffff); + + if(offsetline()) bDraw=FALSE; else bDraw=TRUE; + + if (bDraw && ((lx0 != lx1) || (ly0 != ly1))) + { +/* if(iOffscreenDrawing) + { + cx0=lx0;cx1=lx1;cy0=ly0;cy1=ly1; + offsetPSXLine(); + if(bDrawOffscreen4()) + { + InvalidateTextureAreaEx(); + drawPoly4G(gpuData[i-3],gpuData[i-1],gpuData[i-3],gpuData[i-1]); + } + lx0=cx0;lx1=cx1;ly0=cy0;ly1=cy1; + }*/ + + PRIMdrawGouraudLine(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); + } + i++; + + if(i>iMax) break; + } + + iDrawnSomething=1; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: shaded polyline2 +//////////////////////////////////////////////////////////////////////// + +void primLineG2(u8 *baseAddr) +{ + unsigned long *gpuData = ((unsigned long *) baseAddr); + short *sgpuData = ((short *) baseAddr); + + lx0 = sgpuData[2]; + ly0 = sgpuData[3]; + lx1 = sgpuData[6]; + ly1 = sgpuData[7]; + + vertex[0].c.lcol=vertex[3].c.lcol=gpuData[0]; + vertex[1].c.lcol=vertex[2].c.lcol=gpuData[2]; + vertex[0].c.col[3]=vertex[1].c.col[3]=vertex[2].c.col[3]=vertex[3].c.col[3]=ubGloColAlpha; + + bDrawTextured = FALSE; + bDrawSmoothShaded = TRUE; + + if((lx0 == lx1) && (ly0 == ly1)) return; + + if(offsetline()) return; + + SetRenderState(gpuData[0]); + SetRenderMode(gpuData[0], FALSE); + SetZMask4NT(); + +/* if(iOffscreenDrawing) + { + offsetPSXLine(); + if(bDrawOffscreen4()) + { + InvalidateTextureAreaEx(); + drawPoly4G(gpuData[0],gpuData[2],gpuData[0],gpuData[2]); + } + } +*/ + //if(ClipVertexList4()) + PRIMdrawGouraudLine(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); + + iDrawnSomething=1; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: skipping flat polylines +//////////////////////////////////////////////////////////////////////// + +void primLineFSkip(u8 *baseAddr) +{ + unsigned long *gpuData = ((unsigned long *) baseAddr); + int i=2,iMax=255; + + ly1 = (short)((gpuData[1]>>16) & 0xffff); + lx1 = (short)(gpuData[1] & 0xffff); + + while(!(((gpuData[i] & 0xF000F000) == 0x50005000) && i>=3)) + { + ly1 = (short)((gpuData[i]>>16) & 0xffff); + lx1 = (short)(gpuData[i] & 0xffff); + i++;if(i>iMax) break; + } +} + +//////////////////////////////////////////////////////////////////////// +// cmd: drawing flat polylines +//////////////////////////////////////////////////////////////////////// + +void primLineFEx(u8 *baseAddr) +{ + unsigned long *gpuData = ((unsigned long *) baseAddr); + int iMax; + short cx0,cx1,cy0,cy1;int i; + + iMax=255; + + bDrawTextured = FALSE; + bDrawSmoothShaded = FALSE; + SetRenderState(gpuData[0]); + SetRenderMode(gpuData[0], FALSE); + SetZMask4NT(); + + vertex[0].c.lcol=gpuData[0]; + vertex[0].c.col[3]=ubGloColAlpha; + + ly1 = (short)((gpuData[1]>>16) & 0xffff); + lx1 = (short)(gpuData[1] & 0xffff); + + i=2; + +// while(!(gpuData[i]&0x40000000)) +// while((gpuData[i]>>24)!=0x55) +// while((gpuData[i]&0x50000000)!=0x50000000) +// currently best way to check for poly line end: + while(!(((gpuData[i] & 0xF000F000) == 0x50005000) && i>=3)) + { + ly0 = ly1;lx0=lx1; + ly1 = (short)((gpuData[i]>>16) & 0xffff); + lx1 = (short)(gpuData[i] & 0xffff); + + if(!offsetline()) + { +/* if(iOffscreenDrawing) + { + cx0=lx0;cx1=lx1;cy0=ly0;cy1=ly1; + offsetPSXLine(); + if(bDrawOffscreen4()) + { + InvalidateTextureAreaEx(); + drawPoly4F(gpuData[0]); + } + lx0=cx0;lx1=cx1;ly0=cy0;ly1=cy1; + }*/ + PRIMdrawFlatLine(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); + } + + i++;if(i>iMax) break; + } + + iDrawnSomething=1; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: drawing flat polyline2 +//////////////////////////////////////////////////////////////////////// + +void primLineF2(u8 *baseAddr) +{ + unsigned long *gpuData = ((unsigned long *) baseAddr); + short *sgpuData = ((short *) baseAddr); + + lx0 = sgpuData[2]; + ly0 = sgpuData[3]; + lx1 = sgpuData[4]; + ly1 = sgpuData[5]; + + if(offsetline()) return; + + bDrawTextured = FALSE; + bDrawSmoothShaded = FALSE; + SetRenderState(gpuData[0]); + SetRenderMode(gpuData[0], FALSE); + SetZMask4NT(); + + vertex[0].c.lcol=gpuData[0]; + vertex[0].c.col[3]=ubGloColAlpha; + +/* if(iOffscreenDrawing) + { + offsetPSXLine(); + if(bDrawOffscreen4()) + { + InvalidateTextureAreaEx(); + drawPoly4F(gpuData[0]); + } + } +*/ + //if(ClipVertexList4()) + PRIMdrawFlatLine(&vertex[0], &vertex[1], &vertex[2], &vertex[3]); + + iDrawnSomething=1; +} + +//////////////////////////////////////////////////////////////////////// +// cmd: well, easiest command... not implemented +//////////////////////////////////////////////////////////////////////// + +void primNI(u8 *bA) +{ +} + +//////////////////////////////////////////////////////////////////////// +// cmd func ptr table +//////////////////////////////////////////////////////////////////////// + +void (*primTableJ[256])(u8 *) = +{ + // 00 + primNI,primNI,primBlkFill,primNI,primNI,primNI,primNI,primNI, + // 08 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 10 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 18 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 20 + primPolyF3,primPolyF3,primPolyF3,primPolyF3,primPolyFT3,primPolyFT3,primPolyFT3,primPolyFT3, + // 28 + primPolyF4,primPolyF4,primPolyF4,primPolyF4,primPolyFT4,primPolyFT4,primPolyFT4,primPolyFT4, + // 30 + primPolyG3,primPolyG3,primPolyG3,primPolyG3,primPolyGT3,primPolyGT3,primPolyGT3,primPolyGT3, + // 38 + primPolyG4,primPolyG4,primPolyG4,primPolyG4,primPolyGT4,primPolyGT4,primPolyGT4,primPolyGT4, + // 40 + primLineF2,primLineF2,primLineF2,primLineF2,primNI,primNI,primNI,primNI, + // 48 + primLineFEx,primLineFEx,primLineFEx,primLineFEx,primLineFEx,primLineFEx,primLineFEx,primLineFEx, + // 50 + primLineG2,primLineG2,primLineG2,primLineG2,primNI,primNI,primNI,primNI, + // 58 + primLineGEx,primLineGEx,primLineGEx,primLineGEx,primLineGEx,primLineGEx,primLineGEx,primLineGEx, + // 60 + primTileS,primTileS,primTileS,primTileS,primSprtS,primSprtS,primSprtS,primSprtS, + // 68 + primTile1,primTile1,primTile1,primTile1,primNI,primNI,primNI,primNI, + // 70 + primTile8,primTile8,primTile8,primTile8,primSprt8,primSprt8,primSprt8,primSprt8, + // 78 + primTile16,primTile16,primTile16,primTile16,primSprt16,primSprt16,primSprt16,primSprt16, + // 80 + primMoveImage,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 88 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 90 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 98 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // a0 + primLoadImage,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // a8 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // b0 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // b8 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // c0 + primStoreImage,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // c8 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // d0 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // d8 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // e0 + primNI,cmdTexturePage,cmdTextureWindow,cmdDrawAreaStart,cmdDrawAreaEnd,cmdDrawOffset,cmdSTP,primNI, + // e8 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // f0 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // f8 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI +}; + +//////////////////////////////////////////////////////////////////////// +// cmd func ptr table for skipping +//////////////////////////////////////////////////////////////////////// + +void (*primTableSkip[256])(u8 *) = +{ + // 00 + primNI,primNI,primBlkFill,primNI,primNI,primNI,primNI,primNI, + // 08 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 10 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 18 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 20 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 28 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 30 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 38 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 40 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 48 + primLineFSkip,primLineFSkip,primLineFSkip,primLineFSkip,primLineFSkip,primLineFSkip,primLineFSkip,primLineFSkip, + // 50 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 58 + primLineGSkip,primLineGSkip,primLineGSkip,primLineGSkip,primLineGSkip,primLineGSkip,primLineGSkip,primLineGSkip, + // 60 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 68 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 70 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 78 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 80 + primMoveImage,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 88 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 90 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // 98 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // a0 + primLoadImage,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // a8 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // b0 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // b8 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // c0 + primStoreImage,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // c8 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // d0 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // d8 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // e0 + primNI,cmdTexturePage,cmdTextureWindow,cmdDrawAreaStart,cmdDrawAreaEnd,cmdDrawOffset,cmdSTP,primNI, + // e8 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // f0 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, + // f8 + primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI +}; diff --git a/plugins/gpu-gles/gpuPrim.h b/plugins/gpu-gles/gpuPrim.h new file mode 100644 index 00000000..58d33118 --- /dev/null +++ b/plugins/gpu-gles/gpuPrim.h @@ -0,0 +1,58 @@ +/*************************************************************************** + prim.h - description + ------------------- + begin : Sun Mar 08 2009 + copyright : (C) 1999-2009 by Pete Bernert + web : www.pbernert.com + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2009/03/08 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +#ifndef _PRIMDRAW_H_ +#define _PRIMDRAW_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "gpuExternals.h" +#include "gpuStdafx.h" + +#ifndef _WINDOWS +extern EGLSurface surface; +extern EGLDisplay display; +#endif + +void UploadScreen (long Position); +void PrepareFullScreenUpload (long Position); +BOOL CheckAgainstScreen(short imageX0,short imageY0,short imageX1,short imageY1); +BOOL CheckAgainstFrontScreen(short imageX0,short imageY0,short imageX1,short imageY1); +BOOL FastCheckAgainstScreen(short imageX0,short imageY0,short imageX1,short imageY1); +BOOL FastCheckAgainstFrontScreen(short imageX0,short imageY0,short imageX1,short imageY1); +BOOL bCheckFF9G4(u8 * baseAddr); +void SetScanTrans(void); +void SetScanTexTrans(void); +void DrawMultiBlur(void); +void CheckWriteUpdate(); + +#ifdef __cplusplus +} +#endif + +#endif // _PRIMDRAW_H_ diff --git a/plugins/gpu-gles/gpuStdafx.h b/plugins/gpu-gles/gpuStdafx.h new file mode 100644 index 00000000..fc7ee3d5 --- /dev/null +++ b/plugins/gpu-gles/gpuStdafx.h @@ -0,0 +1,99 @@ +/*************************************************************************** + stdafx.h - description + ------------------- + begin : Sun Mar 08 2009 + copyright : (C) 1999-2009 by Pete Bernert + web : www.pbernert.com + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2009/03/08 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + +#ifndef __GPU_STDAFX__ +#define __GPU_STDAFX__ + +#ifdef __cplusplus +extern "C" { +#endif + + + + + + // maybe we should remove this? +#ifdef _WINDOWS + +#define _CRT_SECURE_NO_WARNINGS + +#include +#include +#include +#include "resource.h" + +#pragma warning (disable:4244) + +#include + +#else +/* +#define __X11_C_ +*/ + +#include +#include +#include +#include +#ifdef __NANOGL__ +#include +#else +#ifdef SOFT_LINKAGE +#pragma softfp_linkage +#endif +#ifdef MAEMO_CHANGES + #include + #include + #include + #include +#else + #include // for opengl es types + #include +#endif +#ifdef SOFT_LINKAGE +#pragma no_softfp_linkage +#endif +#endif +#include + +#define __inline inline + +#endif + +#define SHADETEXBIT(x) ((x>>24) & 0x1) +#define SEMITRANSBIT(x) ((x>>25) & 0x1) + +#ifndef _WINDOWS +#ifndef GL_BGRA_EXT +#define GL_BGRA_EXT GL_RGBA +#endif +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/plugins/gpu-gles/gpuTexture.c b/plugins/gpu-gles/gpuTexture.c new file mode 100644 index 00000000..d047a62f --- /dev/null +++ b/plugins/gpu-gles/gpuTexture.c @@ -0,0 +1,4226 @@ +/*************************************************************************** + texture.c - description + ------------------- + begin : Sun Mar 08 2009 + copyright : (C) 1999-2009 by Pete Bernert + web : www.pbernert.com + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. See also the license.txt file for * + * additional informations. * + * * + ***************************************************************************/ + +//*************************************************************************// +// History of changes: +// +// 2009/03/08 - Pete +// - generic cleanup for the Peops release +// +//*************************************************************************// + + +//////////////////////////////////////////////////////////////////////////////////// +// Texture related functions are here ! +// +// The texture handling is heart and soul of this gpu. The plugin was developed +// 1999, by this time no shaders were available. Since the psx gpu is making +// heavy use of CLUT (="color lookup tables", aka palettized textures), it was +// an interesting task to get those emulated at good speed on NV TNT cards +// (which was my major goal when I created the first "gpuPeteTNT"). Later cards +// (Geforce256) supported texture palettes by an OGL extension, but at some point +// this support was dropped again by gfx card vendors. +// Well, at least there is a certain advatage, if no texture palettes extension can +// be used: it is possible to modify the textures in any way, allowing "hi-res" +// textures and other tweaks. +// +// My main texture caching is kinda complex: the plugin is allocating "n" 256x256 textures, +// and it places small psx texture parts inside them. The plugin keeps track what +// part (with what palette) it had placed in which texture, so it can re-use this +// part again. The more ogl textures it can use, the better (of course the managing/ +// searching will be slower, but everything is faster than uploading textures again +// and again to a gfx card). My first card (TNT1) had 16 MB Vram, and it worked +// well with many games, but I recommend nowadays 64 MB Vram to get a good speed. +// +// Sadly, there is also a second kind of texture cache needed, for "psx texture windows". +// Those are "repeated" textures, so a psx "texture window" needs to be put in +// a whole texture to use the GL_TEXTURE_WRAP_ features. This cache can get full very +// fast in games which are having an heavy "texture window" usage, like RRT4. As an +// alternative, this plugin can use the OGL "palette" extension on texture windows, +// if available. Nowadays also a fragment shader can easily be used to emulate +// texture wrapping in a texture atlas, so the main cache could hold the texture +// windows as well (that's what I am doing in the OGL2 plugin). But currently the +// OGL1 plugin is a "shader-free" zone, so heavy "texture window" games will cause +// much texture uploads. +// +// Some final advice: take care if you change things in here. I've removed my ASM +// handlers (they didn't cause much speed gain anyway) for readability/portability, +// but still the functions/data structures used here are easy to mess up. I guess it +// can be a pain in the ass to port the plugin to another byte order :) +// +//////////////////////////////////////////////////////////////////////////////////// + +#define _IN_TEXTURE + +#ifdef _WINDOWS +#include "stdafx.h" + +#include "externals.h" +#include "texture.h" +#include "gpu.h" +#include "prim.h" +#else +#include "gpuStdafx.h" +#ifdef __NANOGL__ +#include +#include +#else +#ifdef SOFT_LINKAGE +#pragma softfp_linkage +#endif +#ifdef MAEMO_CHANGES + #include + #include + #include + #include +#else + #include // for opengl es types + #include +#endif +#ifdef SOFT_LINKAGE +#pragma no_softfp_linkage +#endif +#endif +#include "gpuDraw.h" +//#include "plugins.h" +#include "gpuExternals.h" +#include "gpuTexture.h" +#include "gpuPlugin.h" +#include "gpuPrim.h" +#endif +#define CLUTCHK 0x00060000 +#define CLUTSHIFT 17 + +//////////////////////////////////////////////////////////////////////// +// texture conversion buffer .. +//////////////////////////////////////////////////////////////////////// + +GLubyte ubPaletteBuffer[256][4]; +GLuint gTexMovieName=0; +GLuint gTexBlurName=0; +GLuint gTexFrameName=0; +int iTexGarbageCollection=1; +unsigned long dwTexPageComp=0; +int iVRamSize=0; +#ifdef _WINDOWS +int iClampType=GL_CLAMP; +#else +int iClampType=GL_CLAMP_TO_EDGE; +#endif +int iFilter = GL_LINEAR; +void (*LoadSubTexFn) (int,int,short,short); +unsigned long (*PalTexturedColourFn) (unsigned long); + +//////////////////////////////////////////////////////////////////////// +// defines +//////////////////////////////////////////////////////////////////////// + +#define PALCOL(x) PalTexturedColourFn (x) + +#define CSUBSIZE 2048 +#define CSUBSIZEA 8192 +#define CSUBSIZES 4096 + +#define OFFA 0 +#define OFFB 2048 +#define OFFC 4096 +#define OFFD 6144 + +#define XOFFA 0 +#define XOFFB 512 +#define XOFFC 1024 +#define XOFFD 1536 + +#define SOFFA 0 +#define SOFFB 1024 +#define SOFFC 2048 +#define SOFFD 3072 + +#define MAXWNDTEXCACHE 128 + +#define XCHECK(pos1,pos2) ((pos1.c[0]>=pos2.c[1])&&(pos1.c[1]<=pos2.c[0])&&(pos1.c[2]>=pos2.c[3])&&(pos1.c[3]<=pos2.c[2])) +#define INCHECK(pos2,pos1) ((pos1.c[0]<=pos2.c[0]) && (pos1.c[1]>=pos2.c[1]) && (pos1.c[2]<=pos2.c[2]) && (pos1.c[3]>=pos2.c[3])) + +//////////////////////////////////////////////////////////////////////// + +u8 * CheckTextureInSubSCache(long TextureMode,unsigned long GivenClutId,unsigned short * pCache); +void LoadSubTexturePageSort(int pageid, int mode, short cx, short cy); +void LoadPackedSubTexturePageSort(int pageid, int mode, short cx, short cy); +void DefineSubTextureSort(void); + +//////////////////////////////////////////////////////////////////////// +// some globals +//////////////////////////////////////////////////////////////////////// + +long GlobalTexturePage; +GLint XTexS; +GLint YTexS; +GLint DXTexS; +GLint DYTexS; +int iSortTexCnt=32; +BOOL bUseFastMdec=FALSE; +BOOL bUse15bitMdec=FALSE; +int iFrameTexType=0; +int iFrameReadType=0; + +unsigned long (*TCF[2]) (unsigned long); +unsigned short (*PTCF[2]) (unsigned short); + +//////////////////////////////////////////////////////////////////////// +// texture cache implementation +//////////////////////////////////////////////////////////////////////// + +#ifdef _WINDOWS +#pragma pack(1) +#endif + +// "texture window" cache entry + +typedef struct textureWndCacheEntryTag +{ + unsigned long ClutID; + short pageid; + short textureMode; + short Opaque; + short used; + EXLong pos; + GLuint texname; +} textureWndCacheEntry; + +// "standard texture" cache entry (12 byte per entry, as small as possible... we need lots of them) + +typedef struct textureSubCacheEntryTagS +{ + unsigned long ClutID; + EXLong pos; + u8 posTX; + u8 posTY; + u8 cTexID; + u8 Opaque; +} textureSubCacheEntryS; + +#ifdef _WINDOWS +#pragma pack() +#endif + +//--------------------------------------------- + +#define MAXTPAGES_MAX 64 +#define MAXSORTTEX_MAX 196 + +//--------------------------------------------- + +textureWndCacheEntry wcWndtexStore[MAXWNDTEXCACHE]; +textureSubCacheEntryS * pscSubtexStore[3][MAXTPAGES_MAX]; +EXLong * pxSsubtexLeft [MAXSORTTEX_MAX]; +GLuint uiStexturePage[MAXSORTTEX_MAX]; + +unsigned short usLRUTexPage=0; + +int iMaxTexWnds=0; +int iTexWndTurn=0; +int iTexWndLimit=MAXWNDTEXCACHE/2; + +GLubyte * texturepart=NULL; +GLubyte * texturebuffer=NULL; +unsigned long g_x1,g_y1,g_x2,g_y2; +u8 ubOpaqueDraw=0; + +unsigned short MAXTPAGES = 32; +unsigned short CLUTMASK = 0x7fff; +unsigned short CLUTYMASK = 0x1ff; +unsigned short MAXSORTTEX = 196; + +//////////////////////////////////////////////////////////////////////// +// Texture color conversions... all my ASM funcs are removed for easier +// porting... and honestly: nowadays the speed gain would be pointless +//////////////////////////////////////////////////////////////////////// + +unsigned long XP8RGBA(unsigned long BGR) +{ + if(!(BGR&0xffff)) return 0x50000000; + if(DrawSemiTrans && !(BGR&0x8000)) + {ubOpaqueDraw=1;return ((((BGR<<3)&0xf8)|((BGR<<6)&0xf800)|((BGR<<9)&0xf80000))&0xffffff);} + return ((((BGR<<3)&0xf8)|((BGR<<6)&0xf800)|((BGR<<9)&0xf80000))&0xffffff)|0xff000000; +} + +unsigned long XP8RGBAEx(unsigned long BGR) +{ + if(!(BGR&0xffff)) return 0x03000000; + if(DrawSemiTrans && !(BGR&0x8000)) + {ubOpaqueDraw=1;return ((((BGR<<3)&0xf8)|((BGR<<6)&0xf800)|((BGR<<9)&0xf80000))&0xffffff);} + return ((((BGR<<3)&0xf8)|((BGR<<6)&0xf800)|((BGR<<9)&0xf80000))&0xffffff)|0xff000000; +} + +unsigned long CP8RGBA(unsigned long BGR) +{ + unsigned long l; + if(!(BGR&0xffff)) return 0x50000000; + if(DrawSemiTrans && !(BGR&0x8000)) + {ubOpaqueDraw=1;return ((((BGR<<3)&0xf8)|((BGR<<6)&0xf800)|((BGR<<9)&0xf80000))&0xffffff);} + l=((((BGR<<3)&0xf8)|((BGR<<6)&0xf800)|((BGR<<9)&0xf80000))&0xffffff)|0xff000000; + if(l==0xffffff00) l=0xff000000; + return l; +} + +unsigned long CP8RGBAEx(unsigned long BGR) +{ + unsigned long l; + if(!(BGR&0xffff)) return 0x03000000; + if(DrawSemiTrans && !(BGR&0x8000)) + {ubOpaqueDraw=1;return ((((BGR<<3)&0xf8)|((BGR<<6)&0xf800)|((BGR<<9)&0xf80000))&0xffffff);} + l=((((BGR<<3)&0xf8)|((BGR<<6)&0xf800)|((BGR<<9)&0xf80000))&0xffffff)|0xff000000; + if(l==0xffffff00) l=0xff000000; + return l; +} + +unsigned long XP8RGBA_0(unsigned long BGR) +{ + if(!(BGR&0xffff)) return 0x50000000; + return ((((BGR<<3)&0xf8)|((BGR<<6)&0xf800)|((BGR<<9)&0xf80000))&0xffffff)|0xff000000; +} + +unsigned long XP8RGBAEx_0(unsigned long BGR) +{ + if(!(BGR&0xffff)) return 0x03000000; + return ((((BGR<<3)&0xf8)|((BGR<<6)&0xf800)|((BGR<<9)&0xf80000))&0xffffff)|0xff000000; +} + +unsigned long XP8BGRA_0(unsigned long BGR) +{ + if(!(BGR&0xffff)) return 0x50000000; + return ((((BGR>>7)&0xf8)|((BGR<<6)&0xf800)|((BGR<<19)&0xf80000))&0xffffff)|0xff000000; +} + +unsigned long XP8BGRAEx_0(unsigned long BGR) +{ + if(!(BGR&0xffff)) return 0x03000000; + return ((((BGR>>7)&0xf8)|((BGR<<6)&0xf800)|((BGR<<19)&0xf80000))&0xffffff)|0xff000000; +} + +unsigned long CP8RGBA_0(unsigned long BGR) +{ + unsigned long l; + + if(!(BGR&0xffff)) return 0x50000000; + l=((((BGR<<3)&0xf8)|((BGR<<6)&0xf800)|((BGR<<9)&0xf80000))&0xffffff)|0xff000000; + if(l==0xfff8f800) l=0xff000000; + return l; +} + +unsigned long CP8RGBAEx_0(unsigned long BGR) +{ + unsigned long l; + + if(!(BGR&0xffff)) return 0x03000000; + l=((((BGR<<3)&0xf8)|((BGR<<6)&0xf800)|((BGR<<9)&0xf80000))&0xffffff)|0xff000000; + if(l==0xfff8f800) l=0xff000000; + return l; +} + +unsigned long CP8BGRA_0(unsigned long BGR) +{ + unsigned long l; + + if(!(BGR&0xffff)) return 0x50000000; + l=((((BGR>>7)&0xf8)|((BGR<<6)&0xf800)|((BGR<<19)&0xf80000))&0xffffff)|0xff000000; + if(l==0xff00f8f8) l=0xff000000; + return l; +} + +unsigned long CP8BGRAEx_0(unsigned long BGR) +{ + unsigned long l; + + if(!(BGR&0xffff)) return 0x03000000; + l=((((BGR>>7)&0xf8)|((BGR<<6)&0xf800)|((BGR<<19)&0xf80000))&0xffffff)|0xff000000; + if(l==0xff00f8f8) l=0xff000000; + return l; +} + +unsigned long XP8RGBA_1(unsigned long BGR) +{ + if(!(BGR&0xffff)) return 0x50000000; + if(!(BGR&0x8000)) {ubOpaqueDraw=1;return ((((BGR<<3)&0xf8)|((BGR<<6)&0xf800)|((BGR<<9)&0xf80000))&0xffffff);} + return ((((BGR<<3)&0xf8)|((BGR<<6)&0xf800)|((BGR<<9)&0xf80000))&0xffffff)|0xff000000; +} + +unsigned long XP8RGBAEx_1(unsigned long BGR) +{ + if(!(BGR&0xffff)) return 0x03000000; + if(!(BGR&0x8000)) {ubOpaqueDraw=1;return ((((BGR<<3)&0xf8)|((BGR<<6)&0xf800)|((BGR<<9)&0xf80000))&0xffffff);} + return ((((BGR<<3)&0xf8)|((BGR<<6)&0xf800)|((BGR<<9)&0xf80000))&0xffffff)|0xff000000; +} + +unsigned long XP8BGRA_1(unsigned long BGR) +{ + if(!(BGR&0xffff)) return 0x50000000; + if(!(BGR&0x8000)) {ubOpaqueDraw=1;return ((((BGR>>7)&0xf8)|((BGR<<6)&0xf800)|((BGR<<19)&0xf80000))&0xffffff);} + return ((((BGR>>7)&0xf8)|((BGR<<6)&0xf800)|((BGR<<19)&0xf80000))&0xffffff)|0xff000000; +} + +unsigned long XP8BGRAEx_1(unsigned long BGR) +{ + if(!(BGR&0xffff)) return 0x03000000; + if(!(BGR&0x8000)) {ubOpaqueDraw=1;return ((((BGR>>7)&0xf8)|((BGR<<6)&0xf800)|((BGR<<19)&0xf80000))&0xffffff);} + return ((((BGR>>7)&0xf8)|((BGR<<6)&0xf800)|((BGR<<19)&0xf80000))&0xffffff)|0xff000000; +} + +unsigned long P8RGBA(unsigned long BGR) +{ + if(!(BGR&0xffff)) return 0; + return ((((BGR<<3)&0xf8)|((BGR<<6)&0xf800)|((BGR<<9)&0xf80000))&0xffffff)|0xff000000; +} + +unsigned long P8BGRA(unsigned long BGR) +{ + if(!(BGR&0xffff)) return 0; + return ((((BGR>>7)&0xf8)|((BGR<<6)&0xf800)|((BGR<<19)&0xf80000))&0xffffff)|0xff000000; +} + +unsigned short XP5RGBA(unsigned short BGR) +{ + if(!BGR) return 0; + if(DrawSemiTrans && !(BGR&0x8000)) + {ubOpaqueDraw=1;return ((((BGR<<11))|((BGR>>9)&0x3e)|((BGR<<1)&0x7c0)));} + return ((((BGR<<11))|((BGR>>9)&0x3e)|((BGR<<1)&0x7c0)))|1; +} + +unsigned short XP5RGBA_0 (unsigned short BGR) +{ + if(!BGR) return 0; + + return ((((BGR<<11))|((BGR>>9)&0x3e)|((BGR<<1)&0x7c0)))|1; +} + +unsigned short CP5RGBA_0 (unsigned short BGR) +{ + unsigned short s; + + if(!BGR) return 0; + + s=((((BGR<<11))|((BGR>>9)&0x3e)|((BGR<<1)&0x7c0)))|1; + if(s==0x07ff) s=1; + return s; +} + +unsigned short XP5RGBA_1(unsigned short BGR) +{ + if(!BGR) return 0; + if(!(BGR&0x8000)) + {ubOpaqueDraw=1;return ((((BGR<<11))|((BGR>>9)&0x3e)|((BGR<<1)&0x7c0)));} + return ((((BGR<<11))|((BGR>>9)&0x3e)|((BGR<<1)&0x7c0)))|1; +} + +unsigned short P5RGBA(unsigned short BGR) +{ + if(!BGR) return 0; + return ((((BGR<<11))|((BGR>>9)&0x3e)|((BGR<<1)&0x7c0)))|1; +} + +unsigned short XP4RGBA(unsigned short BGR) +{ + if(!BGR) return 6; + if(DrawSemiTrans && !(BGR&0x8000)) + {ubOpaqueDraw=1;return ((((BGR<<11))|((BGR>>9)&0x3e)|((BGR<<1)&0x7c0)));} + return (((((BGR&0x1e)<<11))|((BGR&0x7800)>>7)|((BGR&0x3c0)<<2)))|0xf; +} + +unsigned short XP4RGBA_0 (unsigned short BGR) +{ + if(!BGR) return 6; + return (((((BGR&0x1e)<<11))|((BGR&0x7800)>>7)|((BGR&0x3c0)<<2)))|0xf; +} + +unsigned short CP4RGBA_0 (unsigned short BGR) +{ + unsigned short s; + if(!BGR) return 6; + s=(((((BGR&0x1e)<<11))|((BGR&0x7800)>>7)|((BGR&0x3c0)<<2)))|0xf; + if(s==0x0fff) s=0x000f; + return s; +} + +unsigned short XP4RGBA_1(unsigned short BGR) +{ + if(!BGR) return 6; + if(!(BGR&0x8000)) + {ubOpaqueDraw=1;return ((((BGR<<11))|((BGR>>9)&0x3e)|((BGR<<1)&0x7c0)));} + return (((((BGR&0x1e)<<11))|((BGR&0x7800)>>7)|((BGR&0x3c0)<<2)))|0xf; +} + +unsigned short P4RGBA(unsigned short BGR) +{ + if(!BGR) return 0; + return (((((BGR&0x1e)<<11))|((BGR&0x7800)>>7)|((BGR&0x3c0)<<2)))|0xf; +} + +//////////////////////////////////////////////////////////////////////// +// CHECK TEXTURE MEM (on plugin startup) +//////////////////////////////////////////////////////////////////////// + +int iFTexA=512; +int iFTexB=512; + +void CheckTextureMemory(void) +{ + GLboolean b;GLboolean * bDetail; + int i,iCnt,iRam=iVRamSize*1024*1024; + int iTSize;s8 * p; + + + if(iVRamSize) + { + int ts; + + iRam-=(iResX*iResY*8); + iRam-=(iResX*iResY*(iZBufferDepth/8)); + + ts=4; + iSortTexCnt=iRam/(256*256*ts); + + if(iSortTexCnt>MAXSORTTEX) + { + iSortTexCnt=MAXSORTTEX-min(1,0); + } + else + { + iSortTexCnt-=3+min(1,0); + if(iSortTexCnt<8) iSortTexCnt=8; + } + + for(i=0;i info for 32*3 + for(j=0;j info 0..511 + { + pxSsubtexLeft[i]=(EXLong *)malloc(CSUBSIZE*sizeof(EXLong)); + memset(pxSsubtexLeft[i],0,CSUBSIZE*sizeof(EXLong)); + uiStexturePage[i]=0; + } +} + +//////////////////////////////////////////////////////////////////////// +// Clean up on exit +//////////////////////////////////////////////////////////////////////// + +void CleanupTextureStore() +{ + int i,j;textureWndCacheEntry * tsx; + //----------------------------------------------------// + glBindTexture(GL_TEXTURE_2D,0); + //----------------------------------------------------// + free(texturepart); // free tex part + texturepart=0; + if(texturebuffer) + { + free(texturebuffer); + texturebuffer=0; + } + //----------------------------------------------------// + tsx=wcWndtexStore; // loop tex window cache + for(i=0;itexname) // -> some tex? + glDeleteTextures(1,&tsx->texname); // --> delete it + } + iMaxTexWnds=0; // no more tex wnds + //----------------------------------------------------// + if(gTexMovieName!=0) // some movie tex? + glDeleteTextures(1, &gTexMovieName); // -> delete it + gTexMovieName=0; // no more movie tex + //----------------------------------------------------// + if(gTexFrameName!=0) // some 15bit framebuffer tex? + glDeleteTextures(1, &gTexFrameName); // -> delete it + gTexFrameName=0; // no more movie tex + //----------------------------------------------------// + if(gTexBlurName!=0) // some 15bit framebuffer tex? + glDeleteTextures(1, &gTexBlurName); // -> delete it + gTexBlurName=0; // no more movie tex + //----------------------------------------------------// + for(i=0;i<3;i++) // -> loop + for(j=0;j clean mem + } + for(i=0;i tex used ? + { + glDeleteTextures(1,&uiStexturePage[i]); + uiStexturePage[i]=0; // --> delete it + } + free(pxSsubtexLeft[i]); // -> clean mem + } + //----------------------------------------------------// +} + +//////////////////////////////////////////////////////////////////////// +// Reset textures in game... +//////////////////////////////////////////////////////////////////////// + +void ResetTextureArea(BOOL bDelTex) +{ + int i,j;textureSubCacheEntryS * tss;EXLong * lu; + textureWndCacheEntry * tsx; + //----------------------------------------------------// + + dwTexPageComp=0; + + //----------------------------------------------------// + if(bDelTex) {glBindTexture(GL_TEXTURE_2D,0);gTexName=0;} + //----------------------------------------------------// + tsx=wcWndtexStore; + for(i=0;iused=0; + if(bDelTex && tsx->texname) + { + glDeleteTextures(1,&tsx->texname); + tsx->texname=0; + } + } + iMaxTexWnds=0; + //----------------------------------------------------// + + for(i=0;i<3;i++) + for(j=0;jpos.l=0; + (tss+SOFFB)->pos.l=0; + (tss+SOFFC)->pos.l=0; + (tss+SOFFD)->pos.l=0; + } + + for(i=0;il=0; + if(bDelTex && uiStexturePage[i]) + {glDeleteTextures(1,&uiStexturePage[i]);uiStexturePage[i]=0;} + } +} + + +//////////////////////////////////////////////////////////////////////// +// Invalidate tex windows +//////////////////////////////////////////////////////////////////////// + +void InvalidateWndTextureArea(long X,long Y,long W, long H) +{ + int i,px1,px2,py1,py2,iYM=1; + textureWndCacheEntry * tsw=wcWndtexStore; + + W+=X-1; + H+=Y-1; + if(X<0) X=0;if(X>1023) X=1023; + if(W<0) W=0;if(W>1023) W=1023; + if(Y<0) Y=0;if(Y>iGPUHeightMask) Y=iGPUHeightMask; + if(H<0) H=0;if(H>iGPUHeightMask) H=iGPUHeightMask; + W++;H++; + + if(iGPUHeight==1024) iYM=3; + + py1=min(iYM,Y>>8); + py2=min(iYM,H>>8); // y: 0 or 1 + + px1=max(0,(X>>6)); + px2=min(15,(W>>6)); + + if(py1==py2) + { + py1=py1<<4;px1+=py1;px2+=py1; // change to 0-31 + for(i=0;iused) + { + if(tsw->pageid>=px1 && tsw->pageid<=px2) + { + tsw->used=0; + } + } + } + } + else + { + py1=px1+16;py2=px2+16; + for(i=0;iused) + { + if((tsw->pageid>=px1 && tsw->pageid<=px2) || + (tsw->pageid>=py1 && tsw->pageid<=py2)) + { + tsw->used=0; + } + } + } + } + + // adjust tex window count + tsw=wcWndtexStore+iMaxTexWnds-1; + while(iMaxTexWnds && !tsw->used) {iMaxTexWnds--;tsw--;} +} + + + +//////////////////////////////////////////////////////////////////////// +// same for sort textures +//////////////////////////////////////////////////////////////////////// + +void MarkFree(textureSubCacheEntryS * tsx) +{ + EXLong * ul, * uls; + int j,iMax;u8 x1,y1,dx,dy; + + uls=pxSsubtexLeft[tsx->cTexID]; + iMax=uls->l;ul=uls+1; + + if(!iMax) return; + + for(j=0;jl==0xffffffff) break; + + if(jl=uls->l+1; + + x1=tsx->posTX;dx=tsx->pos.c[2]-tsx->pos.c[3]; + if(tsx->posTX) {x1--;dx+=3;} + y1=tsx->posTY;dy=tsx->pos.c[0]-tsx->pos.c[1]; + if(tsx->posTY) {y1--;dy+=3;} + + ul->c[3]=x1; + ul->c[2]=dx; + ul->c[1]=y1; + ul->c[0]=dy; + } +} + +void InvalidateSubSTextureArea(long X,long Y,long W, long H) +{ + int i,j,k,iMax,px,py,px1,px2,py1,py2,iYM=1; + EXLong npos;textureSubCacheEntryS * tsb; + long x1,x2,y1,y2,xa,sw; + + W+=X-1; + H+=Y-1; + if(X<0) X=0;if(X>1023) X=1023; + if(W<0) W=0;if(W>1023) W=1023; + if(Y<0) Y=0;if(Y>iGPUHeightMask) Y=iGPUHeightMask; + if(H<0) H=0;if(H>iGPUHeightMask) H=iGPUHeightMask; + W++;H++; + + if(iGPUHeight==1024) iYM=3; + + py1=min(iYM,Y>>8); + py2=min(iYM,H>>8); // y: 0 or 1 + px1=max(0,(X>>6)-3); + px2=min(15,(W>>6)+3); // x: 0-15 + + for(py=py1;py<=py2;py++) + { + j=(py<<4)+px1; // get page + + y1=py*256;y2=y1+255; + + if(Hy2) continue; + + if(Y>y1) y1=Y; + if(Hx2) continue; + + if(X>x1) x1=X; + if(Wpos.l;tsb++; + for(i=0;iClutID && XCHECK(tsb->pos,npos)) {tsb->ClutID=0;MarkFree(tsb);} + +// if(npos.l & 0x00800000) + { + tsb=pscSubtexStore[k][j]+SOFFB;iMax=tsb->pos.l;tsb++; + for(i=0;iClutID && XCHECK(tsb->pos,npos)) {tsb->ClutID=0;MarkFree(tsb);} + } + +// if(npos.l & 0x00000080) + { + tsb=pscSubtexStore[k][j]+SOFFC;iMax=tsb->pos.l;tsb++; + for(i=0;iClutID && XCHECK(tsb->pos,npos)) {tsb->ClutID=0;MarkFree(tsb);} + } + +// if(npos.l & 0x00800080) + { + tsb=pscSubtexStore[k][j]+SOFFD;iMax=tsb->pos.l;tsb++; + for(i=0;iClutID && XCHECK(tsb->pos,npos)) {tsb->ClutID=0;MarkFree(tsb);} + } + } + } + } + } +} + +//////////////////////////////////////////////////////////////////////// +// Invalidate some parts of cache: main routine +//////////////////////////////////////////////////////////////////////// + +void InvalidateTextureAreaEx(void) +{ + short W=sxmax-sxmin; + short H=symax-symin; + + if(W==0 && H==0) return; + + if(iMaxTexWnds) + InvalidateWndTextureArea(sxmin,symin,W,H); + + InvalidateSubSTextureArea(sxmin,symin,W,H); +} + +//////////////////////////////////////////////////////////////////////// + +void InvalidateTextureArea(long X,long Y,long W, long H) +{ + if(W==0 && H==0) return; + + if(iMaxTexWnds) InvalidateWndTextureArea(X,Y,W,H); + + InvalidateSubSTextureArea(X,Y,W,H); +} + + +//////////////////////////////////////////////////////////////////////// +// tex window: define +//////////////////////////////////////////////////////////////////////// + +void DefineTextureWnd(void) +{ + if(gTexName==0) + glGenTextures(1, &gTexName); + + glBindTexture(GL_TEXTURE_2D, gTexName); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + +{ + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, iFilter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, iFilter); + } + + glTexImage2D(GL_TEXTURE_2D, 0,GL_RGBA, + TWin.Position.x1, + TWin.Position.y1, + 0, GL_RGBA, GL_UNSIGNED_BYTE, texturepart); +} + +//////////////////////////////////////////////////////////////////////// +// tex window: load packed stretch +//////////////////////////////////////////////////////////////////////// + +void LoadStretchPackedWndTexturePage(int pageid, int mode, short cx, short cy) +{ + unsigned long start,row,column,j,sxh,sxm,ldx,ldy,ldxo; + unsigned int palstart; + unsigned short *px,*pa,*ta; + u8 *cSRCPtr,*cOSRCPtr; + unsigned short *wSRCPtr,*wOSRCPtr; + unsigned long LineOffset;unsigned short s; + int pmult=pageid/16; + unsigned short (*LPTCOL)(unsigned short); + + LPTCOL=PTCF[DrawSemiTrans]; + + ldxo=TWin.Position.x1-TWin.OPosition.x1; + ldy =TWin.Position.y1-TWin.OPosition.y1; + + pa=px=(unsigned short *)ubPaletteBuffer; + ta=(unsigned short *)texturepart; + palstart=cx+(cy*1024); + + ubOpaqueDraw=0; + + switch(mode) + { + //--------------------------------------------------// + // 4bit texture load .. + case 0: + if(GlobalTextIL) + { + unsigned int TXV,TXU,n_xi,n_yi; + + wSRCPtr=psxVuw+palstart; + for(row=0;row<16;row++) + *px++=LPTCOL(*wSRCPtr++); + + column=g_y2-ldy; + for(TXV=g_y1;TXV<=column;TXV++) + { + ldx=ldxo; + for(TXU=g_x1;TXU<=g_x2-ldxo;TXU++) + { + n_xi = ( ( TXU >> 2 ) & ~0x3c ) + ( ( TXV << 2 ) & 0x3c ); + n_yi = ( TXV & ~0xf ) + ( ( TXU >> 4 ) & 0xf ); + + s=*(pa+((*( psxVuw + ((GlobalTextAddrY + n_yi)*1024) + GlobalTextAddrX + n_xi ) >> ( ( TXU & 0x03 ) << 2 ) ) & 0x0f )); + *ta++=s; + + if(ldx) {*ta++=s;ldx--;} + } + + if(ldy) + {ldy--; + for(TXU=g_x1;TXU<=g_x2;TXU++) + *ta++=*(ta-(g_x2-g_x1)); + } + } + + DefineTextureWnd(); + + break; + } + + + start=((pageid-16*pmult)*128)+256*2048*pmult; + + // convert CLUT to 32bits .. and then use THAT as a lookup table + + wSRCPtr=psxVuw+palstart; + for(row=0;row<16;row++) + *px++=LPTCOL(*wSRCPtr++); + + sxm=g_x1&1;sxh=g_x1>>1; + if(sxm) j=g_x1+1; else j=g_x1; + cSRCPtr = psxVub + start + (2048*g_y1) + sxh; + for(column=g_y1;column<=g_y2;column++) + { + cOSRCPtr=cSRCPtr;ldx=ldxo; + if(sxm) *ta++=*(pa+((*cSRCPtr++ >> 4) & 0xF)); + + for(row=j;row<=g_x2-ldxo;row++) + { + s=*(pa+(*cSRCPtr & 0xF)); + *ta++=s; + if(ldx) {*ta++=s;ldx--;} + row++; + if(row<=g_x2-ldxo) + { + s=*(pa+((*cSRCPtr >> 4) & 0xF)); + *ta++=s; + if(ldx) {*ta++=s;ldx--;} + } + cSRCPtr++; + } + + if(ldy && column&1) + {ldy--;cSRCPtr = cOSRCPtr;} + else cSRCPtr = psxVub + start + (2048*(column+1)) + sxh; + } + + DefineTextureWnd(); + break; + //--------------------------------------------------// + // 8bit texture load .. + case 1: + if(GlobalTextIL) + { + unsigned int TXV,TXU,n_xi,n_yi; + + wSRCPtr=psxVuw+palstart; + for(row=0;row<256;row++) + *px++=LPTCOL(*wSRCPtr++); + + column=g_y2-ldy; + for(TXV=g_y1;TXV<=column;TXV++) + { + ldx=ldxo; + for(TXU=g_x1;TXU<=g_x2-ldxo;TXU++) + { + n_xi = ( ( TXU >> 1 ) & ~0x78 ) + ( ( TXU << 2 ) & 0x40 ) + ( ( TXV << 3 ) & 0x38 ); + n_yi = ( TXV & ~0x7 ) + ( ( TXU >> 5 ) & 0x7 ); + + s=*(pa+((*( psxVuw + ((GlobalTextAddrY + n_yi)*1024) + GlobalTextAddrX + n_xi ) >> ( ( TXU & 0x01 ) << 3 ) ) & 0xff)); + + *ta++=s; + if(ldx) {*ta++=s;ldx--;} + } + + if(ldy) + {ldy--; + for(TXU=g_x1;TXU<=g_x2;TXU++) + *ta++=*(ta-(g_x2-g_x1)); + } + + } + + DefineTextureWnd(); + + break; + } + + start=((pageid-16*pmult)*128)+256*2048*pmult; + + // not using a lookup table here... speeds up smaller texture areas + cSRCPtr = psxVub + start + (2048*g_y1) + g_x1; + LineOffset = 2048 - (g_x2-g_x1+1) +ldxo; + + for(column=g_y1;column<=g_y2;column++) + { + cOSRCPtr=cSRCPtr;ldx=ldxo; + for(row=g_x1;row<=g_x2-ldxo;row++) + { + s=LPTCOL(psxVuw[palstart+ *cSRCPtr++]); + *ta++=s; + if(ldx) {*ta++=s;ldx--;} + } + if(ldy && column&1) {ldy--;cSRCPtr=cOSRCPtr;} + else cSRCPtr+=LineOffset; + } + + DefineTextureWnd(); + break; + //--------------------------------------------------// + // 16bit texture load .. + case 2: + start=((pageid-16*pmult)*64)+256*1024*pmult; + wSRCPtr = psxVuw + start + (1024*g_y1) + g_x1; + LineOffset = 1024 - (g_x2-g_x1+1) +ldxo; + + for(column=g_y1;column<=g_y2;column++) + { + wOSRCPtr=wSRCPtr;ldx=ldxo; + for(row=g_x1;row<=g_x2-ldxo;row++) + { + s=LPTCOL(*wSRCPtr++); + *ta++=s; + if(ldx) {*ta++=s;ldx--;} + } + if(ldy && column&1) {ldy--;wSRCPtr=wOSRCPtr;} + else wSRCPtr+=LineOffset; + } + + DefineTextureWnd(); + break; + //--------------------------------------------------// + // others are not possible ! + } +} + +//////////////////////////////////////////////////////////////////////// +// tex window: load stretched +//////////////////////////////////////////////////////////////////////// + +void LoadStretchWndTexturePage(int pageid, int mode, short cx, short cy) +{ + unsigned long start,row,column,j,sxh,sxm,ldx,ldy,ldxo,s; + unsigned int palstart; + unsigned long *px,*pa,*ta; + u8 *cSRCPtr,*cOSRCPtr; + unsigned short *wSRCPtr,*wOSRCPtr; + unsigned long LineOffset; + int pmult=pageid/16; + unsigned long (*LTCOL)(unsigned long); + + LTCOL=TCF[DrawSemiTrans]; + + ldxo=TWin.Position.x1-TWin.OPosition.x1; + ldy =TWin.Position.y1-TWin.OPosition.y1; + + pa=px=(unsigned long *)ubPaletteBuffer; + ta=(unsigned long *)texturepart; + palstart=cx+(cy*1024); + + ubOpaqueDraw=0; + + switch(mode) + { + //--------------------------------------------------// + // 4bit texture load .. + case 0: + //------------------- ZN STUFF + + if(GlobalTextIL) + { + unsigned int TXV,TXU,n_xi,n_yi; + + wSRCPtr=psxVuw+palstart; + + row=4;do + { + *px =LTCOL(*wSRCPtr); + *(px+1)=LTCOL(*(wSRCPtr+1)); + *(px+2)=LTCOL(*(wSRCPtr+2)); + *(px+3)=LTCOL(*(wSRCPtr+3)); + row--;px+=4;wSRCPtr+=4; + } + while (row); + + column=g_y2-ldy; + for(TXV=g_y1;TXV<=column;TXV++) + { + ldx=ldxo; + for(TXU=g_x1;TXU<=g_x2-ldxo;TXU++) + { + n_xi = ( ( TXU >> 2 ) & ~0x3c ) + ( ( TXV << 2 ) & 0x3c ); + n_yi = ( TXV & ~0xf ) + ( ( TXU >> 4 ) & 0xf ); + + s=*(pa+((*( psxVuw + ((GlobalTextAddrY + n_yi)*1024) + GlobalTextAddrX + n_xi ) >> ( ( TXU & 0x03 ) << 2 ) ) & 0x0f )); + *ta++=s; + + if(ldx) {*ta++=s;ldx--;} + } + + if(ldy) + {ldy--; + for(TXU=g_x1;TXU<=g_x2;TXU++) + *ta++=*(ta-(g_x2-g_x1)); + } + } + + DefineTextureWnd(); + + break; + } + + //------------------- + + start=((pageid-16*pmult)*128)+256*2048*pmult; + // convert CLUT to 32bits .. and then use THAT as a lookup table + + wSRCPtr=psxVuw+palstart; + for(row=0;row<16;row++) + *px++=LTCOL(*wSRCPtr++); + + sxm=g_x1&1;sxh=g_x1>>1; + if(sxm) j=g_x1+1; else j=g_x1; + cSRCPtr = psxVub + start + (2048*g_y1) + sxh; + for(column=g_y1;column<=g_y2;column++) + { + cOSRCPtr=cSRCPtr;ldx=ldxo; + if(sxm) *ta++=*(pa+((*cSRCPtr++ >> 4) & 0xF)); + + for(row=j;row<=g_x2-ldxo;row++) + { + s=*(pa+(*cSRCPtr & 0xF)); + *ta++=s; + if(ldx) {*ta++=s;ldx--;} + row++; + if(row<=g_x2-ldxo) + { + s=*(pa+((*cSRCPtr >> 4) & 0xF)); + *ta++=s; + if(ldx) {*ta++=s;ldx--;} + } + cSRCPtr++; + } + if(ldy && column&1) + {ldy--;cSRCPtr = cOSRCPtr;} + else cSRCPtr = psxVub + start + (2048*(column+1)) + sxh; + } + + DefineTextureWnd(); + break; + //--------------------------------------------------// + // 8bit texture load .. + case 1: + //------------ ZN STUFF + if(GlobalTextIL) + { + unsigned int TXV,TXU,n_xi,n_yi; + + wSRCPtr=psxVuw+palstart; + + row=64;do + { + *px =LTCOL(*wSRCPtr); + *(px+1)=LTCOL(*(wSRCPtr+1)); + *(px+2)=LTCOL(*(wSRCPtr+2)); + *(px+3)=LTCOL(*(wSRCPtr+3)); + row--;px+=4;wSRCPtr+=4; + } + while (row); + + column=g_y2-ldy; + for(TXV=g_y1;TXV<=column;TXV++) + { + ldx=ldxo; + for(TXU=g_x1;TXU<=g_x2-ldxo;TXU++) + { + n_xi = ( ( TXU >> 1 ) & ~0x78 ) + ( ( TXU << 2 ) & 0x40 ) + ( ( TXV << 3 ) & 0x38 ); + n_yi = ( TXV & ~0x7 ) + ( ( TXU >> 5 ) & 0x7 ); + + s=*(pa+((*( psxVuw + ((GlobalTextAddrY + n_yi)*1024) + GlobalTextAddrX + n_xi ) >> ( ( TXU & 0x01 ) << 3 ) ) & 0xff)); + *ta++=s; + if(ldx) {*ta++=s;ldx--;} + } + + if(ldy) + {ldy--; + for(TXU=g_x1;TXU<=g_x2;TXU++) + *ta++=*(ta-(g_x2-g_x1)); + } + + } + + DefineTextureWnd(); + + break; + } + //------------ + + start=((pageid-16*pmult)*128)+256*2048*pmult; + + // not using a lookup table here... speeds up smaller texture areas + cSRCPtr = psxVub + start + (2048*g_y1) + g_x1; + LineOffset = 2048 - (g_x2-g_x1+1) +ldxo; + + for(column=g_y1;column<=g_y2;column++) + { + cOSRCPtr=cSRCPtr;ldx=ldxo; + for(row=g_x1;row<=g_x2-ldxo;row++) + { + s=LTCOL(psxVuw[palstart+ *cSRCPtr++]); + *ta++=s; + if(ldx) {*ta++=s;ldx--;} + } + if(ldy && column&1) {ldy--;cSRCPtr=cOSRCPtr;} + else cSRCPtr+=LineOffset; + } + + DefineTextureWnd(); + break; + //--------------------------------------------------// + // 16bit texture load .. + case 2: + start=((pageid-16*pmult)*64)+256*1024*pmult; + + wSRCPtr = psxVuw + start + (1024*g_y1) + g_x1; + LineOffset = 1024 - (g_x2-g_x1+1) +ldxo; + + for(column=g_y1;column<=g_y2;column++) + { + wOSRCPtr=wSRCPtr;ldx=ldxo; + for(row=g_x1;row<=g_x2-ldxo;row++) + { + s=LTCOL(*wSRCPtr++); + *ta++=s; + if(ldx) {*ta++=s;ldx--;} + } + if(ldy && column&1) {ldy--;wSRCPtr=wOSRCPtr;} + else wSRCPtr+=LineOffset; + } + + DefineTextureWnd(); + break; + //--------------------------------------------------// + // others are not possible ! + } +} + +//////////////////////////////////////////////////////////////////////// +// tex window: load packed simple +//////////////////////////////////////////////////////////////////////// + +void LoadPackedWndTexturePage(int pageid, int mode, short cx, short cy) +{ + unsigned long start,row,column,j,sxh,sxm; + unsigned int palstart; + unsigned short *px,*pa,*ta; + u8 *cSRCPtr; + unsigned short *wSRCPtr; + unsigned long LineOffset; + int pmult=pageid/16; + unsigned short (*LPTCOL)(unsigned short); + + LPTCOL=PTCF[DrawSemiTrans]; + + pa=px=(unsigned short *)ubPaletteBuffer; + ta=(unsigned short *)texturepart; + palstart=cx+(cy*1024); + + ubOpaqueDraw=0; + + switch(mode) + { + //--------------------------------------------------// + // 4bit texture load .. + case 0: + if(GlobalTextIL) + { + unsigned int TXV,TXU,n_xi,n_yi; + + wSRCPtr=psxVuw+palstart; + for(row=0;row<16;row++) + *px++=LPTCOL(*wSRCPtr++); + + for(TXV=g_y1;TXV<=g_y2;TXV++) + { + for(TXU=g_x1;TXU<=g_x2;TXU++) + { + n_xi = ( ( TXU >> 2 ) & ~0x3c ) + ( ( TXV << 2 ) & 0x3c ); + n_yi = ( TXV & ~0xf ) + ( ( TXU >> 4 ) & 0xf ); + + *ta++=*(pa+((*( psxVuw + ((GlobalTextAddrY + n_yi)*1024) + GlobalTextAddrX + n_xi ) >> ( ( TXU & 0x03 ) << 2 ) ) & 0x0f )); + } + } + + DefineTextureWnd(); + + break; + } + + start=((pageid-16*pmult)*128)+256*2048*pmult; + + // convert CLUT to 32bits .. and then use THAT as a lookup table + + wSRCPtr=psxVuw+palstart; + for(row=0;row<16;row++) + *px++=LPTCOL(*wSRCPtr++); + + sxm=g_x1&1;sxh=g_x1>>1; + if(sxm) j=g_x1+1; else j=g_x1; + cSRCPtr = psxVub + start + (2048*g_y1) + sxh; + for(column=g_y1;column<=g_y2;column++) + { + cSRCPtr = psxVub + start + (2048*column) + sxh; + + if(sxm) *ta++=*(pa+((*cSRCPtr++ >> 4) & 0xF)); + + for(row=j;row<=g_x2;row++) + { + *ta++=*(pa+(*cSRCPtr & 0xF)); row++; + if(row<=g_x2) *ta++=*(pa+((*cSRCPtr >> 4) & 0xF)); + cSRCPtr++; + } + } + + DefineTextureWnd(); + break; + //--------------------------------------------------// + // 8bit texture load .. + case 1: + if(GlobalTextIL) + { + unsigned int TXV,TXU,n_xi,n_yi; + + wSRCPtr=psxVuw+palstart; + for(row=0;row<256;row++) + *px++=LPTCOL(*wSRCPtr++); + + for(TXV=g_y1;TXV<=g_y2;TXV++) + { + for(TXU=g_x1;TXU<=g_x2;TXU++) + { + n_xi = ( ( TXU >> 1 ) & ~0x78 ) + ( ( TXU << 2 ) & 0x40 ) + ( ( TXV << 3 ) & 0x38 ); + n_yi = ( TXV & ~0x7 ) + ( ( TXU >> 5 ) & 0x7 ); + + *ta++=*(pa+((*( psxVuw + ((GlobalTextAddrY + n_yi)*1024) + GlobalTextAddrX + n_xi ) >> ( ( TXU & 0x01 ) << 3 ) ) & 0xff)); + } + } + + DefineTextureWnd(); + + break; + } + + start=((pageid-16*pmult)*128)+256*2048*pmult; + + // not using a lookup table here... speeds up smaller texture areas + cSRCPtr = psxVub + start + (2048*g_y1) + g_x1; + LineOffset = 2048 - (g_x2-g_x1+1); + + for(column=g_y1;column<=g_y2;column++) + { + for(row=g_x1;row<=g_x2;row++) + *ta++=LPTCOL(psxVuw[palstart+ *cSRCPtr++]); + cSRCPtr+=LineOffset; + } + + DefineTextureWnd(); + break; + //--------------------------------------------------// + // 16bit texture load .. + case 2: + start=((pageid-16*pmult)*64)+256*1024*pmult; + wSRCPtr = psxVuw + start + (1024*g_y1) + g_x1; + LineOffset = 1024 - (g_x2-g_x1+1); + + for(column=g_y1;column<=g_y2;column++) + { + for(row=g_x1;row<=g_x2;row++) + *ta++=LPTCOL(*wSRCPtr++); + wSRCPtr+=LineOffset; + } + + DefineTextureWnd(); + break; + //--------------------------------------------------// + // others are not possible ! + } +} + +//////////////////////////////////////////////////////////////////////// +// tex window: load simple +//////////////////////////////////////////////////////////////////////// + +void LoadWndTexturePage(int pageid, int mode, short cx, short cy) +{ + unsigned long start,row,column,j,sxh,sxm; + unsigned int palstart; + unsigned long *px,*pa,*ta; + u8 *cSRCPtr; + unsigned short *wSRCPtr; + unsigned long LineOffset; + int pmult=pageid/16; + unsigned long (*LTCOL)(unsigned long); + + LTCOL=TCF[DrawSemiTrans]; + + pa=px=(unsigned long *)ubPaletteBuffer; + ta=(unsigned long *)texturepart; + palstart=cx+(cy*1024); + + ubOpaqueDraw=0; + + switch(mode) + { + //--------------------------------------------------// + // 4bit texture load .. + case 0: + if(GlobalTextIL) + { + unsigned int TXV,TXU,n_xi,n_yi; + + wSRCPtr=psxVuw+palstart; + + row=4;do + { + *px =LTCOL(*wSRCPtr); + *(px+1)=LTCOL(*(wSRCPtr+1)); + *(px+2)=LTCOL(*(wSRCPtr+2)); + *(px+3)=LTCOL(*(wSRCPtr+3)); + row--;px+=4;wSRCPtr+=4; + } + while (row); + + for(TXV=g_y1;TXV<=g_y2;TXV++) + { + for(TXU=g_x1;TXU<=g_x2;TXU++) + { + n_xi = ( ( TXU >> 2 ) & ~0x3c ) + ( ( TXV << 2 ) & 0x3c ); + n_yi = ( TXV & ~0xf ) + ( ( TXU >> 4 ) & 0xf ); + + *ta++=*(pa+((*( psxVuw + ((GlobalTextAddrY + n_yi)*1024) + GlobalTextAddrX + n_xi ) >> ( ( TXU & 0x03 ) << 2 ) ) & 0x0f )); + } + } + + DefineTextureWnd(); + + break; + } + + start=((pageid-16*pmult)*128)+256*2048*pmult; + + // convert CLUT to 32bits .. and then use THAT as a lookup table + + wSRCPtr=psxVuw+palstart; + for(row=0;row<16;row++) + *px++=LTCOL(*wSRCPtr++); + + sxm=g_x1&1;sxh=g_x1>>1; + if(sxm) j=g_x1+1; else j=g_x1; + cSRCPtr = psxVub + start + (2048*g_y1) + sxh; + for(column=g_y1;column<=g_y2;column++) + { + cSRCPtr = psxVub + start + (2048*column) + sxh; + + if(sxm) *ta++=*(pa+((*cSRCPtr++ >> 4) & 0xF)); + + for(row=j;row<=g_x2;row++) + { + *ta++=*(pa+(*cSRCPtr & 0xF)); row++; + if(row<=g_x2) *ta++=*(pa+((*cSRCPtr >> 4) & 0xF)); + cSRCPtr++; + } + } + + DefineTextureWnd(); + break; + //--------------------------------------------------// + // 8bit texture load .. + case 1: + if(GlobalTextIL) + { + unsigned int TXV,TXU,n_xi,n_yi; + + wSRCPtr=psxVuw+palstart; + + row=64;do + { + *px =LTCOL(*wSRCPtr); + *(px+1)=LTCOL(*(wSRCPtr+1)); + *(px+2)=LTCOL(*(wSRCPtr+2)); + *(px+3)=LTCOL(*(wSRCPtr+3)); + row--;px+=4;wSRCPtr+=4; + } + while (row); + + for(TXV=g_y1;TXV<=g_y2;TXV++) + { + for(TXU=g_x1;TXU<=g_x2;TXU++) + { + n_xi = ( ( TXU >> 1 ) & ~0x78 ) + ( ( TXU << 2 ) & 0x40 ) + ( ( TXV << 3 ) & 0x38 ); + n_yi = ( TXV & ~0x7 ) + ( ( TXU >> 5 ) & 0x7 ); + + *ta++=*(pa+((*( psxVuw + ((GlobalTextAddrY + n_yi)*1024) + GlobalTextAddrX + n_xi ) >> ( ( TXU & 0x01 ) << 3 ) ) & 0xff)); + } + } + + DefineTextureWnd(); + + break; + } + + start=((pageid-16*pmult)*128)+256*2048*pmult; + + // not using a lookup table here... speeds up smaller texture areas + cSRCPtr = psxVub + start + (2048*g_y1) + g_x1; + LineOffset = 2048 - (g_x2-g_x1+1); + + for(column=g_y1;column<=g_y2;column++) + { + for(row=g_x1;row<=g_x2;row++) + *ta++=LTCOL(psxVuw[palstart+ *cSRCPtr++]); + cSRCPtr+=LineOffset; + } + + DefineTextureWnd(); + break; + //--------------------------------------------------// + // 16bit texture load .. + case 2: + start=((pageid-16*pmult)*64)+256*1024*pmult; + + wSRCPtr = psxVuw + start + (1024*g_y1) + g_x1; + LineOffset = 1024 - (g_x2-g_x1+1); + + for(column=g_y1;column<=g_y2;column++) + { + for(row=g_x1;row<=g_x2;row++) + *ta++=LTCOL(*wSRCPtr++); + wSRCPtr+=LineOffset; + } + + DefineTextureWnd(); + break; + //--------------------------------------------------// + // others are not possible ! + } +} + +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// + +void UploadTexWndPal(int mode,short cx,short cy) +{ + unsigned int i,iSize; + unsigned short * wSrcPtr; + unsigned long * ta=(unsigned long *)texturepart; + + wSrcPtr=psxVuw+cx+(cy*1024); + if(mode==0) i=4; else i=64; + iSize=i<<2; + ubOpaqueDraw=0; + + do + { + *ta =PALCOL(*wSrcPtr); + *(ta+1)=PALCOL(*(wSrcPtr+1)); + *(ta+2)=PALCOL(*(wSrcPtr+2)); + *(ta+3)=PALCOL(*(wSrcPtr+3)); + ta+=4;wSrcPtr+=4;i--; + } + while(i); + +/* (*glColorTableEXTEx)(GL_TEXTURE_2D,GL_RGBA8,iSize, + GL_RGBA,GL_UNSIGNED_BYTE,texturepart); +*/} + +//////////////////////////////////////////////////////////////////////// + +void DefinePalTextureWnd(void) +{ + if(gTexName==0) + glGenTextures(1, &gTexName); + + glBindTexture(GL_TEXTURE_2D, gTexName); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + +{ + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, iFilter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, iFilter); + } + + glTexImage2D(GL_TEXTURE_2D, 0,GL_RGBA, + TWin.Position.x1, + TWin.Position.y1, + 0, GL_RGBA, GL_UNSIGNED_BYTE,texturepart); +} + +/////////////////////////////////////////////////////// + +void LoadPalWndTexturePage(int pageid, int mode, short cx, short cy) +{ + unsigned long start,row,column,j,sxh,sxm; + u8 *ta; + u8 *cSRCPtr; + unsigned long LineOffset; + int pmult=pageid/16; + + ta=(u8 *)texturepart; + + switch(mode) + { + //--------------------------------------------------// + // 4bit texture load .. + case 0: + start=((pageid-16*pmult)*128)+256*2048*pmult; + + sxm=g_x1&1;sxh=g_x1>>1; + if(sxm) j=g_x1+1; else j=g_x1; + cSRCPtr = psxVub + start + (2048*g_y1) + sxh; + for(column=g_y1;column<=g_y2;column++) + { + cSRCPtr = psxVub + start + (2048*column) + sxh; + + if(sxm) *ta++=((*cSRCPtr++ >> 4) & 0xF); + + for(row=j;row<=g_x2;row++) + { + *ta++=(*cSRCPtr & 0xF); row++; + if(row<=g_x2) *ta++=((*cSRCPtr >> 4) & 0xF); + cSRCPtr++; + } + } + + DefinePalTextureWnd(); + break; + //--------------------------------------------------// + // 8bit texture load .. + case 1: + start=((pageid-16*pmult)*128)+256*2048*pmult; + + // not using a lookup table here... speeds up smaller texture areas + cSRCPtr = psxVub + start + (2048*g_y1) + g_x1; + LineOffset = 2048 - (g_x2-g_x1+1); + + for(column=g_y1;column<=g_y2;column++) + { + for(row=g_x1;row<=g_x2;row++) + *ta++=*cSRCPtr++; + cSRCPtr+=LineOffset; + } + + DefinePalTextureWnd(); + break; + } + UploadTexWndPal(mode,cx,cy); +} + +//////////////////////////////////////////////////////////////////////// + +void LoadStretchPalWndTexturePage(int pageid, int mode, short cx, short cy) +{ + unsigned long start,row,column,j,sxh,sxm,ldx,ldy,ldxo; + u8 *ta,s; + u8 *cSRCPtr,*cOSRCPtr; + unsigned long LineOffset; + int pmult=pageid/16; + + ldxo=TWin.Position.x1-TWin.OPosition.x1; + ldy =TWin.Position.y1-TWin.OPosition.y1; + + ta=(u8 *)texturepart; + + switch(mode) + { + //--------------------------------------------------// + // 4bit texture load .. + case 0: + start=((pageid-16*pmult)*128)+256*2048*pmult; + + sxm=g_x1&1;sxh=g_x1>>1; + if(sxm) j=g_x1+1; else j=g_x1; + cSRCPtr = psxVub + start + (2048*g_y1) + sxh; + for(column=g_y1;column<=g_y2;column++) + { + cOSRCPtr=cSRCPtr;ldx=ldxo; + if(sxm) *ta++=((*cSRCPtr++ >> 4) & 0xF); + + for(row=j;row<=g_x2-ldxo;row++) + { + s=(*cSRCPtr & 0xF); + *ta++=s; + if(ldx) {*ta++=s;ldx--;} + row++; + if(row<=g_x2-ldxo) + { + s=((*cSRCPtr >> 4) & 0xF); + *ta++=s; + if(ldx) {*ta++=s;ldx--;} + } + cSRCPtr++; + } + if(ldy && column&1) + {ldy--;cSRCPtr = cOSRCPtr;} + else cSRCPtr = psxVub + start + (2048*(column+1)) + sxh; + } + + DefinePalTextureWnd(); + break; + //--------------------------------------------------// + // 8bit texture load .. + case 1: + start=((pageid-16*pmult)*128)+256*2048*pmult; + + cSRCPtr = psxVub + start + (2048*g_y1) + g_x1; + LineOffset = 2048 - (g_x2-g_x1+1) +ldxo; + + for(column=g_y1;column<=g_y2;column++) + { + cOSRCPtr=cSRCPtr;ldx=ldxo; + for(row=g_x1;row<=g_x2-ldxo;row++) + { + s=*cSRCPtr++; + *ta++=s; + if(ldx) {*ta++=s;ldx--;} + } + if(ldy && column&1) {ldy--;cSRCPtr=cOSRCPtr;} + else cSRCPtr+=LineOffset; + } + + DefinePalTextureWnd(); + break; + } + UploadTexWndPal(mode,cx,cy); +} + +//////////////////////////////////////////////////////////////////////// +// tex window: main selecting, cache handler included +//////////////////////////////////////////////////////////////////////// + +GLuint LoadTextureWnd(long pageid,long TextureMode,unsigned long GivenClutId) +{ + textureWndCacheEntry * ts, * tsx=NULL; + int i;short cx,cy; + EXLong npos; + + npos.c[3]=TWin.Position.x0; + npos.c[2]=TWin.OPosition.x1; + npos.c[1]=TWin.Position.y0; + npos.c[0]=TWin.OPosition.y1; + + g_x1=TWin.Position.x0;g_x2=g_x1+TWin.Position.x1-1; + g_y1=TWin.Position.y0;g_y2=g_y1+TWin.Position.y1-1; + + if(TextureMode==2) {GivenClutId=0;cx=cy=0;} + else + { + cx=((GivenClutId << 4) & 0x3F0);cy=((GivenClutId >> 6) & CLUTYMASK); + GivenClutId=(GivenClutId&CLUTMASK)|(DrawSemiTrans<<30); + + // palette check sum + { + unsigned long l=0,row; + unsigned long * lSRCPtr=(unsigned long *)(psxVuw+cx+(cy*1024)); + if(TextureMode==1) for(row=1;row<129;row++) l+=((*lSRCPtr++)-1)*row; + else for(row=1;row<9;row++) l+=((*lSRCPtr++)-1)<used) + { + if(ts->pos.l==npos.l && + ts->pageid==pageid && + ts->textureMode==TextureMode) + { + if(ts->ClutID==GivenClutId) + { + ubOpaqueDraw=ts->Opaque; + return ts->texname; + } + } + } + else tsx=ts; + } + + if(!tsx) + { + if(iMaxTexWnds==iTexWndLimit) + { + tsx=wcWndtexStore+iTexWndTurn; + iTexWndTurn++; + if(iTexWndTurn==iTexWndLimit) iTexWndTurn=0; + } + else + { + tsx=wcWndtexStore+iMaxTexWnds; + iMaxTexWnds++; + } + } + + gTexName=tsx->texname; + + if(TWin.OPosition.y1==TWin.Position.y1 && + TWin.OPosition.x1==TWin.Position.x1) + { + LoadWndTexturePage(pageid,TextureMode,cx,cy); + } + else + { + LoadStretchWndTexturePage(pageid,TextureMode,cx,cy); + } + + tsx->Opaque=ubOpaqueDraw; + tsx->pos.l=npos.l; + tsx->ClutID=GivenClutId; + tsx->pageid=pageid; + tsx->textureMode=TextureMode; + tsx->texname=gTexName; + tsx->used=1; + + return gTexName; +} + +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +// movie texture: define +//////////////////////////////////////////////////////////////////////// + +void DefinePackedTextureMovie(void) +{ + if(gTexMovieName==0) + { + glGenTextures(1, &gTexMovieName); + gTexName=gTexMovieName; + glBindTexture(GL_TEXTURE_2D, gTexName); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, iClampType); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, iClampType); + + if(!bUseFastMdec) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + } + else + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, iFilter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, iFilter); + } + + glTexImage2D(GL_TEXTURE_2D, 0, //giWantedRGBA, + GL_RGBA, + 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, texturepart); + } + else + { + gTexName=gTexMovieName;glBindTexture(GL_TEXTURE_2D, gTexName); + } + + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, + (xrMovieArea.x1-xrMovieArea.x0), + (xrMovieArea.y1-xrMovieArea.y0), + GL_RGBA, + GL_UNSIGNED_SHORT, + texturepart); +} + +//////////////////////////////////////////////////////////////////////// + +void DefineTextureMovie(void) +{ + if(gTexMovieName==0) + { + glGenTextures(1, &gTexMovieName); + gTexName=gTexMovieName; + glBindTexture(GL_TEXTURE_2D, gTexName); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, iClampType); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, iClampType); + + if(!bUseFastMdec) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + } + else + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, iFilter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, iFilter); + } + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, texturepart); + } + else + { + gTexName=gTexMovieName;glBindTexture(GL_TEXTURE_2D, gTexName); + } + + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, + (xrMovieArea.x1-xrMovieArea.x0), + (xrMovieArea.y1-xrMovieArea.y0), + GL_RGBA, GL_UNSIGNED_BYTE, texturepart); +} + +//////////////////////////////////////////////////////////////////////// +// movie texture: load +//////////////////////////////////////////////////////////////////////// + +#define MRED(x) ((x>>3) & 0x1f) +#define MGREEN(x) ((x>>6) & 0x3e0) +#define MBLUE(x) ((x>>9) & 0x7c00) + +#define XMGREEN(x) ((x>>5) & 0x07c0) +#define XMRED(x) ((x<<8) & 0xf800) +#define XMBLUE(x) ((x>>18) & 0x003e) + +//////////////////////////////////////////////////////////////////////// +// movie texture: load +//////////////////////////////////////////////////////////////////////// + +u8 * LoadDirectMovieFast(void) +{ + long row,column; + unsigned int startxy; + + unsigned long * ta=(unsigned long *)texturepart; + + if(PSXDisplay.RGB24) + { + u8 * pD; + + startxy=((1024)*xrMovieArea.y0)+xrMovieArea.x0; + + for(column=xrMovieArea.y0;column1280 || iResY>1024) iFTex=2048; + else + if(iResX>640 || iResY>480) iFTex=1024; + else iFTex=512; + + glGenTextures(1, &gTexFrameName); + gTexName=gTexFrameName; + glBindTexture(GL_TEXTURE_2D, gTexName); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, iClampType); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, iClampType); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, iFilter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, iFilter); + + p=(s8 *)malloc(iFTex*iFTex*4); + memset(p,0,iFTex*iFTex*4); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, iFTex, iFTex, 0, GL_RGBA, GL_UNSIGNED_BYTE, p); + free(p); + + glGetError(); + } + else + { + gTexName=gTexFrameName; + glBindTexture(GL_TEXTURE_2D, gTexName); + } + + x1+=PreviousPSXDisplay.Range.x0; + y1+=PreviousPSXDisplay.Range.y0; + + if(PSXDisplay.DisplayMode.x) + ScaleX=(float)rRatioRect.right/(float)PSXDisplay.DisplayMode.x; + else ScaleX=1.0f; + if(PSXDisplay.DisplayMode.y) + ScaleY=(float)rRatioRect.bottom/(float)PSXDisplay.DisplayMode.y; + else ScaleY=1.0f; + + rSrc.left =max(x1*ScaleX,0); + rSrc.right =min((x1+x2)*ScaleX+0.99f,iResX-1); + rSrc.top =max(y1*ScaleY,0); + rSrc.bottom=min((y1+y2)*ScaleY+0.99f,iResY-1); + + iYAdjust=(y1+y2)-PSXDisplay.DisplayMode.y; + if(iYAdjust>0) + iYAdjust=(int)((float)iYAdjust*ScaleY)+1; + else iYAdjust=0; + + gl_vy[0]=255-gl_vy[0]; + gl_vy[1]=255-gl_vy[1]; + gl_vy[2]=255-gl_vy[2]; + gl_vy[3]=255-gl_vy[3]; + + y1=min(gl_vy[0],min(gl_vy[1],min(gl_vy[2],gl_vy[3]))); + + gl_vy[0]-=y1; + gl_vy[1]-=y1; + gl_vy[2]-=y1; + gl_vy[3]-=y1; + gl_ux[0]-=gl_ux[7]; + gl_ux[1]-=gl_ux[7]; + gl_ux[2]-=gl_ux[7]; + gl_ux[3]-=gl_ux[7]; + + ScaleX*=256.0f/((float)(iFTex)); + ScaleY*=256.0f/((float)(iFTex)); + + y1=((float)gl_vy[0]*ScaleY); if(y1>255) y1=255; + gl_vy[0]=y1; + y1=((float)gl_vy[1]*ScaleY); if(y1>255) y1=255; + gl_vy[1]=y1; + y1=((float)gl_vy[2]*ScaleY); if(y1>255) y1=255; + gl_vy[2]=y1; + y1=((float)gl_vy[3]*ScaleY); if(y1>255) y1=255; + gl_vy[3]=y1; + + x1=((float)gl_ux[0]*ScaleX); if(x1>255) x1=255; + gl_ux[0]=x1; + x1=((float)gl_ux[1]*ScaleX); if(x1>255) x1=255; + gl_ux[1]=x1; + x1=((float)gl_ux[2]*ScaleX); if(x1>255) x1=255; + gl_ux[2]=x1; + x1=((float)gl_ux[3]*ScaleX); if(x1>255) x1=255; + gl_ux[3]=x1; + + x1=rSrc.right-rSrc.left; + if(x1<=0) x1=1; + if(x1>iFTex) x1=iFTex; + + y1=rSrc.bottom-rSrc.top; + if(y1<=0) y1=1; + if(y1+iYAdjust>iFTex) y1=iFTex-iYAdjust; + + + glCopyTexSubImage2D( GL_TEXTURE_2D, 0, + 0, + iYAdjust, + rSrc.left+rRatioRect.left, + iResY-rSrc.bottom-rRatioRect.top, + x1,y1); + + if(glGetError()) + { + s8 * p=(s8 *)malloc(iFTex*iFTex*4); + memset(p,0,iFTex*iFTex*4); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, iFTex, iFTex, + GL_RGBA, GL_UNSIGNED_BYTE, p); + free(p); + } + + + ubOpaqueDraw=0; + + if(iSpriteTex) + { + sprtW=gl_ux[1]-gl_ux[0]; + sprtH=-(gl_vy[0]-gl_vy[2]); + } + + return (GLuint)gTexName; +} + +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +// +// load texture part (unpacked) +// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// + +void LoadSubTexturePageSort(int pageid, int mode, short cx, short cy) +{ + unsigned long start,row,column,j,sxh,sxm; + unsigned int palstart; + unsigned long *px,*pa,*ta; + u8 *cSRCPtr; + unsigned short *wSRCPtr; + unsigned long LineOffset; + unsigned long x2a,xalign=0; + unsigned long x1=gl_ux[7]; + unsigned long x2=gl_ux[6]; + unsigned long y1=gl_ux[5]; + unsigned long y2=gl_ux[4]; + unsigned long dx=x2-x1+1; + unsigned long dy=y2-y1+1; + int pmult=pageid/16; + unsigned long (*LTCOL)(unsigned long); + unsigned int a,r,g,b,cnt,h; + unsigned long scol[8]; + + LTCOL=TCF[DrawSemiTrans]; + + pa=px=(unsigned long *)ubPaletteBuffer; + ta=(unsigned long *)texturepart; + palstart=cx+(cy<<10); + + ubOpaqueDraw=0; + + if(YTexS) {ta+=dx;if(XTexS) ta+=2;} + if(XTexS) {ta+=1;xalign=2;} + + switch(mode) + { + //--------------------------------------------------// + // 4bit texture load .. + case 0: + if(GlobalTextIL) + { + unsigned int TXV,TXU,n_xi,n_yi; + + wSRCPtr=psxVuw+palstart; + + row=4;do + { + *px =LTCOL(*wSRCPtr); + *(px+1)=LTCOL(*(wSRCPtr+1)); + *(px+2)=LTCOL(*(wSRCPtr+2)); + *(px+3)=LTCOL(*(wSRCPtr+3)); + row--;px+=4;wSRCPtr+=4; + } + while (row); + + for(TXV=y1;TXV<=y2;TXV++) + { + for(TXU=x1;TXU<=x2;TXU++) + { + n_xi = ( ( TXU >> 2 ) & ~0x3c ) + ( ( TXV << 2 ) & 0x3c ); + n_yi = ( TXV & ~0xf ) + ( ( TXU >> 4 ) & 0xf ); + + *ta++=*(pa+((*( psxVuw + ((GlobalTextAddrY + n_yi)*1024) + GlobalTextAddrX + n_xi ) >> ( ( TXU & 0x03 ) << 2 ) ) & 0x0f )); + } + ta+=xalign; + } + break; + } + + start=((pageid-16*pmult)<<7)+524288*pmult; + // convert CLUT to 32bits .. and then use THAT as a lookup table + + wSRCPtr=psxVuw+palstart; + + row=4;do + { + *px =LTCOL(*wSRCPtr); + *(px+1)=LTCOL(*(wSRCPtr+1)); + *(px+2)=LTCOL(*(wSRCPtr+2)); + *(px+3)=LTCOL(*(wSRCPtr+3)); + row--;px+=4;wSRCPtr+=4; + } + while (row); + + x2a=x2?(x2-1):0;//if(x2) x2a=x2-1; else x2a=0; + sxm=x1&1;sxh=x1>>1; + j=sxm?(x1+1):x1;//if(sxm) j=x1+1; else j=x1; + for(column=y1;column<=y2;column++) + { + cSRCPtr = psxVub + start + (column<<11) + sxh; + + if(sxm) *ta++=*(pa+((*cSRCPtr++ >> 4) & 0xF)); + + for(row=j;row> 4) & 0xF)); + cSRCPtr++;ta+=2; + } + + if(row<=x2) + { + *ta++=*(pa+(*cSRCPtr & 0xF)); row++; + if(row<=x2) *ta++=*(pa+((*cSRCPtr >> 4) & 0xF)); + } + + ta+=xalign; + } + + break; + //--------------------------------------------------// + // 8bit texture load .. + case 1: + if(GlobalTextIL) + { + unsigned int TXV,TXU,n_xi,n_yi; + + wSRCPtr=psxVuw+palstart; + + row=64;do + { + *px =LTCOL(*wSRCPtr); + *(px+1)=LTCOL(*(wSRCPtr+1)); + *(px+2)=LTCOL(*(wSRCPtr+2)); + *(px+3)=LTCOL(*(wSRCPtr+3)); + row--;px+=4;wSRCPtr+=4; + } + while (row); + + for(TXV=y1;TXV<=y2;TXV++) + { + for(TXU=x1;TXU<=x2;TXU++) + { + n_xi = ( ( TXU >> 1 ) & ~0x78 ) + ( ( TXU << 2 ) & 0x40 ) + ( ( TXV << 3 ) & 0x38 ); + n_yi = ( TXV & ~0x7 ) + ( ( TXU >> 5 ) & 0x7 ); + + *ta++=*(pa+((*( psxVuw + ((GlobalTextAddrY + n_yi)*1024) + GlobalTextAddrX + n_xi ) >> ( ( TXU & 0x01 ) << 3 ) ) & 0xff)); + } + ta+=xalign; + } + + break; + } + + start=((pageid-16*pmult)<<7)+524288*pmult; + + cSRCPtr = psxVub + start + (y1<<11) + x1; + LineOffset = 2048 - dx; + + if(dy*dx>384) + { + wSRCPtr=psxVuw+palstart; + + row=64;do + { + *px =LTCOL(*wSRCPtr); + *(px+1)=LTCOL(*(wSRCPtr+1)); + *(px+2)=LTCOL(*(wSRCPtr+2)); + *(px+3)=LTCOL(*(wSRCPtr+3)); + row--;px+=4;wSRCPtr+=4; + } + while (row); + + column=dy;do + { + row=dx; + do {*ta++=*(pa+(*cSRCPtr++));row--;} while(row); + ta+=xalign; + cSRCPtr+=LineOffset;column--; + } + while(column); + } + else + { + wSRCPtr=psxVuw+palstart; + + column=dy;do + { + row=dx; + do {*ta++=LTCOL(*(wSRCPtr+*cSRCPtr++));row--;} while(row); + ta+=xalign; + cSRCPtr+=LineOffset;column--; + } + while(column); + } + + break; + //--------------------------------------------------// + // 16bit texture load .. + case 2: + start=((pageid-16*pmult)<<6)+262144*pmult; + + wSRCPtr = psxVuw + start + (y1<<10) + x1; + LineOffset = 1024 - dx; + + column=dy;do + { + row=dx; + do {*ta++=LTCOL(*wSRCPtr++);row--;} while(row); + ta+=xalign; + wSRCPtr+=LineOffset;column--; + } + while(column); + + break; + //--------------------------------------------------// + // others are not possible ! + } + + x2a=dx+xalign; + + if(YTexS) + { + ta=(unsigned long *)texturepart; + pa=(unsigned long *)texturepart+x2a; + row=x2a;do {*ta++=*pa++;row--;} while(row); + pa=(unsigned long *)texturepart+dy*x2a; + ta=pa+x2a; + row=x2a;do {*ta++=*pa++;row--;} while(row); + YTexS--; + dy+=2; + } + + if(XTexS) + { + ta=(unsigned long *)texturepart; + pa=ta+1; + row=dy;do {*ta=*pa;ta+=x2a;pa+=x2a;row--;} while(row); + pa=(unsigned long *)texturepart+dx; + ta=pa+1; + row=dy;do {*ta=*pa;ta+=x2a;pa+=x2a;row--;} while(row); + XTexS--; + dx+=2; + } + + DXTexS=dx;DYTexS=dy; + + if(!iFilterType) {DefineSubTextureSort();return;} + if(iFilterType!=2 && iFilterType!=4 && iFilterType!=6) {DefineSubTextureSort();return;} + if((iFilterType==4 || iFilterType==6) && ly0==ly1 && ly2==ly3 && lx0==lx3 && lx1==lx2) + {DefineSubTextureSort();return;} + + ta=(unsigned long *)texturepart; + x1=dx-1; + y1=dy-1; + + if(bOpaquePass) + { +{ + for(column=0;column>24!=1) scol[cnt++]=*(ta-dx); + if(row && *(ta-1) !=0x50000000 && *(ta-1)>>24!=1) scol[cnt++]=*(ta-1); + if(row!=x1 && *(ta+1) !=0x50000000 && *(ta+1)>>24!=1) scol[cnt++]=*(ta+1); + if( column!=y1 && *(ta+dx) !=0x50000000 && *(ta+dx)>>24!=1) scol[cnt++]=*(ta+dx); + + if(row && column && *(ta-dx-1)!=0x50000000 && *(ta-dx-1)>>24!=1) scol[cnt++]=*(ta-dx-1); + if(row!=x1 && column && *(ta-dx+1)!=0x50000000 && *(ta-dx+1)>>24!=1) scol[cnt++]=*(ta-dx+1); + if(row && column!=y1 && *(ta+dx-1)!=0x50000000 && *(ta+dx-1)>>24!=1) scol[cnt++]=*(ta+dx-1); + if(row!=x1 && column!=y1 && *(ta+dx+1)!=0x50000000 && *(ta+dx+1)>>24!=1) scol[cnt++]=*(ta+dx+1); + + if(cnt) + { + r=g=b=a=0; + for(h=0;h>24); + r+=(scol[h]>>16)&0xff; + g+=(scol[h]>>8)&0xff; + b+=scol[h]&0xff; + } + r/=cnt;b/=cnt;g/=cnt; + + *ta=(r<<16)|(g<<8)|b; + if(a) *ta|=0x50000000; + else *ta|=0x01000000; + } + } + ta++; + } + } + } + } + else + for(column=0;column>16)&0xff; + g+=(scol[h]>>8)&0xff; + b+=scol[h]&0xff; + } + r/=cnt;b/=cnt;g/=cnt; + *ta=(r<<16)|(g<<8)|b; + } + } + ta++; + } + } + + DefineSubTextureSort(); +} + +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +// +// load texture part (packed) +// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// + +void LoadPackedSubTexturePageSort(int pageid, int mode, short cx, short cy) +{ + unsigned long start,row,column,j,sxh,sxm; + unsigned int palstart; + unsigned short *px,*pa,*ta; + u8 *cSRCPtr; + unsigned short *wSRCPtr; + unsigned long LineOffset; + unsigned long x2a,xalign=0; + unsigned long x1=gl_ux[7]; + unsigned long x2=gl_ux[6]; + unsigned long y1=gl_ux[5]; + unsigned long y2=gl_ux[4]; + unsigned long dx=x2-x1+1; + unsigned long dy=y2-y1+1; + int pmult=pageid/16; + unsigned short (*LPTCOL)(unsigned short); + unsigned int a,r,g,b,cnt,h; + unsigned short scol[8]; + + LPTCOL=PTCF[DrawSemiTrans]; + + pa=px=(unsigned short *)ubPaletteBuffer; + ta=(unsigned short *)texturepart; + palstart=cx+(cy<<10); + + ubOpaqueDraw=0; + + if(YTexS) {ta+=dx;if(XTexS) ta+=2;} + if(XTexS) {ta+=1;xalign=2;} + + switch(mode) + { + //--------------------------------------------------// + // 4bit texture load .. + case 0: + if(GlobalTextIL) + { + unsigned int TXV,TXU,n_xi,n_yi; + + wSRCPtr=psxVuw+palstart; + row=4;do + { + *px =LPTCOL(*wSRCPtr); + *(px+1)=LPTCOL(*(wSRCPtr+1)); + *(px+2)=LPTCOL(*(wSRCPtr+2)); + *(px+3)=LPTCOL(*(wSRCPtr+3)); + row--;px+=4;wSRCPtr+=4; + } + while (row); + + for(TXV=y1;TXV<=y2;TXV++) + { + for(TXU=x1;TXU<=x2;TXU++) + { + n_xi = ( ( TXU >> 2 ) & ~0x3c ) + ( ( TXV << 2 ) & 0x3c ); + n_yi = ( TXV & ~0xf ) + ( ( TXU >> 4 ) & 0xf ); + + *ta++=*(pa+((*( psxVuw + ((GlobalTextAddrY + n_yi)*1024) + GlobalTextAddrX + n_xi ) >> ( ( TXU & 0x03 ) << 2 ) ) & 0x0f )); + } + ta+=xalign; + } + break; + } + + start=((pageid-16*pmult)<<7)+524288*pmult; + + wSRCPtr=psxVuw+palstart; + row=4;do + { + *px =LPTCOL(*wSRCPtr); + *(px+1)=LPTCOL(*(wSRCPtr+1)); + *(px+2)=LPTCOL(*(wSRCPtr+2)); + *(px+3)=LPTCOL(*(wSRCPtr+3)); + row--;px+=4;wSRCPtr+=4; + } + while (row); + + x2a=x2?(x2-1):0;//if(x2) x2a=x2-1; else x2a=0; + sxm=x1&1;sxh=x1>>1; + j=sxm?(x1+1):x1;//if(sxm) j=x1+1; else j=x1; + + for(column=y1;column<=y2;column++) + { + cSRCPtr = psxVub + start + (column<<11) + sxh; + + if(sxm) *ta++=*(pa+((*cSRCPtr++ >> 4) & 0xF)); + + for(row=j;row> 4) & 0xF)); + cSRCPtr++;ta+=2; + } + + if(row<=x2) + { + *ta++=*(pa+(*cSRCPtr & 0xF));row++; + if(row<=x2) *ta++=*(pa+((*cSRCPtr >> 4) & 0xF)); + } + + ta+=xalign; + } + break; + //--------------------------------------------------// + // 8bit texture load .. + case 1: + if(GlobalTextIL) + { + unsigned int TXV,TXU,n_xi,n_yi; + + wSRCPtr=psxVuw+palstart; + + row=64;do + { + *px =LPTCOL(*wSRCPtr); + *(px+1)=LPTCOL(*(wSRCPtr+1)); + *(px+2)=LPTCOL(*(wSRCPtr+2)); + *(px+3)=LPTCOL(*(wSRCPtr+3)); + row--;px+=4;wSRCPtr+=4; + } + while (row); + + for(TXV=y1;TXV<=y2;TXV++) + { + for(TXU=x1;TXU<=x2;TXU++) + { + n_xi = ( ( TXU >> 1 ) & ~0x78 ) + ( ( TXU << 2 ) & 0x40 ) + ( ( TXV << 3 ) & 0x38 ); + n_yi = ( TXV & ~0x7 ) + ( ( TXU >> 5 ) & 0x7 ); + + *ta++=*(pa+((*( psxVuw + ((GlobalTextAddrY + n_yi)*1024) + GlobalTextAddrX + n_xi ) >> ( ( TXU & 0x01 ) << 3 ) ) & 0xff)); + } + ta+=xalign; + } + + break; + } + + start=((pageid-16*pmult)<<7)+524288*pmult; + + cSRCPtr = psxVub + start + (y1<<11) + x1; + LineOffset = 2048 - dx; + + if(dy*dx>384) // more pix? use lut + { + wSRCPtr=psxVuw+palstart; + + row=64;do + { + *px =LPTCOL(*wSRCPtr); + *(px+1)=LPTCOL(*(wSRCPtr+1)); + *(px+2)=LPTCOL(*(wSRCPtr+2)); + *(px+3)=LPTCOL(*(wSRCPtr+3)); + row--;px+=4;wSRCPtr+=4; + } + while (row); + + column=dy;do + { + row=dx; + do {*ta++=*(pa+(*cSRCPtr++));row--;} while(row); + + ta+=xalign; + + cSRCPtr+=LineOffset;column--; + } + while(column); + } + else // small area? no lut + { + wSRCPtr=psxVuw+palstart; + + column=dy;do + { + row=dx; + do {*ta++=LPTCOL(*(wSRCPtr+*cSRCPtr++));row--;} while(row); + + ta+=xalign; + + cSRCPtr+=LineOffset;column--; + } + while(column); + } + break; + //--------------------------------------------------// + // 16bit texture load .. + case 2: + start=((pageid-16*pmult)<<6)+262144*pmult; + + wSRCPtr = psxVuw + start + (y1<<10) + x1; + LineOffset = 1024 - dx; + + column=dy;do + { + row=dx; + do {*ta++=LPTCOL(*wSRCPtr++);row--;} while(row); + + ta+=xalign; + + wSRCPtr+=LineOffset;column--; + } + while(column); + break; + //--------------------------------------------------// + // others are not possible ! + } + + //////////////////////////////////////////////////////// + + x2a=dx+xalign; + + if(YTexS) + { + ta=(unsigned short *)texturepart; + pa=(unsigned short *)texturepart+x2a; + row=x2a;do {*ta++=*pa++;row--;} while(row); + + pa=(unsigned short *)texturepart+dy*x2a; + ta=pa+x2a; + row=x2a;do {*ta++=*pa++;row--;} while(row); + + YTexS--; + dy+=2; + } + + if(XTexS) + { + ta=(unsigned short *)texturepart; + pa=ta+1; + row=dy;do {*ta=*pa;ta+=x2a;pa+=x2a;row--;} while(row); + + pa=(unsigned short *)texturepart+dx; + ta=pa+1; + row=dy;do {*ta=*pa;ta+=x2a;pa+=x2a;row--;} while(row); + + XTexS--; + dx+=2; + } + + DXTexS=dx;DYTexS=dy; + + if(!iFilterType) {DefineSubTextureSort();return;} + if(iFilterType!=2 && iFilterType!=4 && iFilterType!=6) {DefineSubTextureSort();return;} + if((iFilterType==4 || iFilterType==6) && ly0==ly1 && ly2==ly3 && lx0==lx3 && lx1==lx2) + {DefineSubTextureSort();return;} + + ta=(unsigned short *)texturepart; + x1=dx-1; + y1=dy-1; + +{ + for(column=0;column>11; + g+=(scol[h]>>6)&0x1f; + b+=(scol[h]>>1)&0x1f; + } + r/=cnt;b/=cnt;g/=cnt; + *ta=(r<<11)|(g<<6)|(b<<1); + } + } + ta++; + } + } + } + + DefineSubTextureSort(); +} + +///////////////////////////////////////////////////////////////////////////// + +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +// +// hires texture funcs +// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// + + +#define GET_RESULT(A, B, C, D) ((A != C || A != D) - (B != C || B != D)) + +//////////////////////////////////////////////////////////////////////// + +#define colorMask8 0x00FEFEFE +#define lowPixelMask8 0x00010101 +#define qcolorMask8 0x00FCFCFC +#define qlowpixelMask8 0x00030303 + + +#define INTERPOLATE8_02(A, B) (((((A & colorMask8) >> 1) + ((B & colorMask8) >> 1) + (A & B & lowPixelMask8))|((((A&0xFF000000)==0x03000000)?0x03000000:(((B&0xFF000000)==0x03000000)?0x03000000:(((A&0xFF000000)==0x00000000)?0x00000000:(((B&0xFF000000)==0x00000000)?0x00000000:0xFF000000))))))) + +#define Q_INTERPOLATE8_02(A, B, C, D) (((((A & qcolorMask8) >> 2) + ((B & qcolorMask8) >> 2) + ((C & qcolorMask8) >> 2) + ((D & qcolorMask8) >> 2) + ((((A & qlowpixelMask8) + (B & qlowpixelMask8) + (C & qlowpixelMask8) + (D & qlowpixelMask8)) >> 2) & qlowpixelMask8))|((((A&0xFF000000)==0x03000000)?0x03000000:(((B&0xFF000000)==0x03000000)?0x03000000:(((C&0xFF000000)==0x03000000)?0x03000000:(((D&0xFF000000)==0x03000000)?0x03000000:(((A&0xFF000000)==0x00000000)?0x00000000:(((B&0xFF000000)==0x00000000)?0x00000000:(((C&0xFF000000)==0x00000000)?0x00000000:(((D&0xFF000000)==0x00000000)?0x00000000:0xFF000000))))))))))) + +#define INTERPOLATE8(A, B) (((((A & colorMask8) >> 1) + ((B & colorMask8) >> 1) + (A & B & lowPixelMask8))|((((A&0xFF000000)==0x50000000)?0x50000000:(((B&0xFF000000)==0x50000000)?0x50000000:(((A&0xFF000000)==0x00000000)?0x00000000:(((B&0xFF000000)==0x00000000)?0x00000000:0xFF000000))))))) + +#define Q_INTERPOLATE8(A, B, C, D) (((((A & qcolorMask8) >> 2) + ((B & qcolorMask8) >> 2) + ((C & qcolorMask8) >> 2) + ((D & qcolorMask8) >> 2) + ((((A & qlowpixelMask8) + (B & qlowpixelMask8) + (C & qlowpixelMask8) + (D & qlowpixelMask8)) >> 2) & qlowpixelMask8))|((((A&0xFF000000)==0x50000000)?0x50000000:(((B&0xFF000000)==0x50000000)?0x50000000:(((C&0xFF000000)==0x50000000)?0x50000000:(((D&0xFF000000)==0x50000000)?0x50000000:(((A&0xFF000000)==0x00000000)?0x00000000:(((B&0xFF000000)==0x00000000)?0x00000000:(((C&0xFF000000)==0x00000000)?0x00000000:(((D&0xFF000000)==0x00000000)?0x00000000:0xFF000000))))))))))) + +void Super2xSaI_ex8_Ex(u8 *srcPtr, DWORD srcPitch, + u8 *dstBitmap, int width, int height) +{ + DWORD dstPitch = srcPitch * 2; + DWORD line; + DWORD *dP; + DWORD *bP; + int width2 = width*2; + int iXA,iXB,iXC,iYA,iYB,iYC,finish; + DWORD color4, color5, color6; + DWORD color1, color2, color3; + DWORD colorA0, colorA1, colorA2, colorA3, + colorB0, colorB1, colorB2, colorB3, + colorS1, colorS2; + DWORD product1a, product1b, + product2a, product2b; + + line = 0; + + { + for (; height; height-=1) + { + bP = (DWORD *)srcPtr; + dP = (DWORD *)(dstBitmap + line*dstPitch); + for (finish = width; finish; finish -= 1 ) + { +//--------------------------------------- B1 B2 +// 4 5 6 S2 +// 1 2 3 S1 +// A1 A2 + if(finish==width) iXA=0; + else iXA=1; + if(finish>4) {iXB=1;iXC=2;} + else + if(finish>3) {iXB=1;iXC=1;} + else {iXB=0;iXC=0;} + if(line==0) iYA=0; + else iYA=width; + if(height>4) {iYB=width;iYC=width2;} + else + if(height>3) {iYB=width;iYC=width;} + else {iYB=0;iYC=0;} + + + colorB0 = *(bP- iYA - iXA); + colorB1 = *(bP- iYA); + colorB2 = *(bP- iYA + iXB); + colorB3 = *(bP- iYA + iXC); + + color4 = *(bP - iXA); + color5 = *(bP); + color6 = *(bP + iXB); + colorS2 = *(bP + iXC); + + color1 = *(bP + iYB - iXA); + color2 = *(bP + iYB); + color3 = *(bP + iYB + iXB); + colorS1= *(bP + iYB + iXC); + + colorA0 = *(bP + iYC - iXA); + colorA1 = *(bP + iYC); + colorA2 = *(bP + iYC + iXB); + colorA3 = *(bP + iYC + iXC); + +//-------------------------------------- + if (color2 == color6 && color5 != color3) + { + product2b = product1b = color2; + } + else + if (color5 == color3 && color2 != color6) + { + product2b = product1b = color5; + } + else + if (color5 == color3 && color2 == color6) + { + register int r = 0; + + r += GET_RESULT ((color6&0x00ffffff), (color5&0x00ffffff), (color1&0x00ffffff), (colorA1&0x00ffffff)); + r += GET_RESULT ((color6&0x00ffffff), (color5&0x00ffffff), (color4&0x00ffffff), (colorB1&0x00ffffff)); + r += GET_RESULT ((color6&0x00ffffff), (color5&0x00ffffff), (colorA2&0x00ffffff), (colorS1&0x00ffffff)); + r += GET_RESULT ((color6&0x00ffffff), (color5&0x00ffffff), (colorB2&0x00ffffff), (colorS2&0x00ffffff)); + + if (r > 0) + product2b = product1b = color6; + else + if (r < 0) + product2b = product1b = color5; + else + { + product2b = product1b = INTERPOLATE8_02(color5, color6); + } + } + else + { + if (color6 == color3 && color3 == colorA1 && color2 != colorA2 && color3 != colorA0) + product2b = Q_INTERPOLATE8_02 (color3, color3, color3, color2); + else + if (color5 == color2 && color2 == colorA2 && colorA1 != color3 && color2 != colorA3) + product2b = Q_INTERPOLATE8_02 (color2, color2, color2, color3); + else + product2b = INTERPOLATE8_02 (color2, color3); + + if (color6 == color3 && color6 == colorB1 && color5 != colorB2 && color6 != colorB0) + product1b = Q_INTERPOLATE8_02 (color6, color6, color6, color5); + else + if (color5 == color2 && color5 == colorB2 && colorB1 != color6 && color5 != colorB3) + product1b = Q_INTERPOLATE8_02 (color6, color5, color5, color5); + else + product1b = INTERPOLATE8_02 (color5, color6); + } + + if (color5 == color3 && color2 != color6 && color4 == color5 && color5 != colorA2) + product2a = INTERPOLATE8_02(color2, color5); + else + if (color5 == color1 && color6 == color5 && color4 != color2 && color5 != colorA0) + product2a = INTERPOLATE8_02(color2, color5); + else + product2a = color2; + + if (color2 == color6 && color5 != color3 && color1 == color2 && color2 != colorB2) + product1a = INTERPOLATE8_02(color2, color5); + else + if (color4 == color2 && color3 == color2 && color1 != color5 && color2 != colorB0) + product1a = INTERPOLATE8_02(color2, color5); + else + product1a = color5; + + *dP=product1a; + *(dP+1)=product1b; + *(dP+(width2))=product2a; + *(dP+1+(width2))=product2b; + + bP += 1; + dP += 2; + }//end of for ( finish= width etc..) + + line += 2; + srcPtr += srcPitch; + }; //endof: for (; height; height--) + } +} + + +void Super2xSaI_ex8(u8 *srcPtr, DWORD srcPitch, + u8 *dstBitmap, int width, int height) +{ + DWORD dstPitch = srcPitch * 2; + DWORD line; + DWORD *dP; + DWORD *bP; + int width2 = width*2; + int iXA,iXB,iXC,iYA,iYB,iYC,finish; + DWORD color4, color5, color6; + DWORD color1, color2, color3; + DWORD colorA0, colorA1, colorA2, colorA3, + colorB0, colorB1, colorB2, colorB3, + colorS1, colorS2; + DWORD product1a, product1b, + product2a, product2b; + + line = 0; + + { + for (; height; height-=1) + { + bP = (DWORD *)srcPtr; + dP = (DWORD *)(dstBitmap + line*dstPitch); + for (finish = width; finish; finish -= 1 ) + { +//--------------------------------------- B1 B2 +// 4 5 6 S2 +// 1 2 3 S1 +// A1 A2 + if(finish==width) iXA=0; + else iXA=1; + if(finish>4) {iXB=1;iXC=2;} + else + if(finish>3) {iXB=1;iXC=1;} + else {iXB=0;iXC=0;} + if(line==0) iYA=0; + else iYA=width; + if(height>4) {iYB=width;iYC=width2;} + else + if(height>3) {iYB=width;iYC=width;} + else {iYB=0;iYC=0;} + + + colorB0 = *(bP- iYA - iXA); + colorB1 = *(bP- iYA); + colorB2 = *(bP- iYA + iXB); + colorB3 = *(bP- iYA + iXC); + + color4 = *(bP - iXA); + color5 = *(bP); + color6 = *(bP + iXB); + colorS2 = *(bP + iXC); + + color1 = *(bP + iYB - iXA); + color2 = *(bP + iYB); + color3 = *(bP + iYB + iXB); + colorS1= *(bP + iYB + iXC); + + colorA0 = *(bP + iYC - iXA); + colorA1 = *(bP + iYC); + colorA2 = *(bP + iYC + iXB); + colorA3 = *(bP + iYC + iXC); + +//-------------------------------------- + if (color2 == color6 && color5 != color3) + { + product2b = product1b = color2; + } + else + if (color5 == color3 && color2 != color6) + { + product2b = product1b = color5; + } + else + if (color5 == color3 && color2 == color6) + { + register int r = 0; + + r += GET_RESULT ((color6&0x00ffffff), (color5&0x00ffffff), (color1&0x00ffffff), (colorA1&0x00ffffff)); + r += GET_RESULT ((color6&0x00ffffff), (color5&0x00ffffff), (color4&0x00ffffff), (colorB1&0x00ffffff)); + r += GET_RESULT ((color6&0x00ffffff), (color5&0x00ffffff), (colorA2&0x00ffffff), (colorS1&0x00ffffff)); + r += GET_RESULT ((color6&0x00ffffff), (color5&0x00ffffff), (colorB2&0x00ffffff), (colorS2&0x00ffffff)); + + if (r > 0) + product2b = product1b = color6; + else + if (r < 0) + product2b = product1b = color5; + else + { + product2b = product1b = INTERPOLATE8(color5, color6); + } + } + else + { + if (color6 == color3 && color3 == colorA1 && color2 != colorA2 && color3 != colorA0) + product2b = Q_INTERPOLATE8 (color3, color3, color3, color2); + else + if (color5 == color2 && color2 == colorA2 && colorA1 != color3 && color2 != colorA3) + product2b = Q_INTERPOLATE8 (color2, color2, color2, color3); + else + product2b = INTERPOLATE8 (color2, color3); + + if (color6 == color3 && color6 == colorB1 && color5 != colorB2 && color6 != colorB0) + product1b = Q_INTERPOLATE8 (color6, color6, color6, color5); + else + if (color5 == color2 && color5 == colorB2 && colorB1 != color6 && color5 != colorB3) + product1b = Q_INTERPOLATE8 (color6, color5, color5, color5); + else + product1b = INTERPOLATE8 (color5, color6); + } + + if (color5 == color3 && color2 != color6 && color4 == color5 && color5 != colorA2) + product2a = INTERPOLATE8(color2, color5); + else + if (color5 == color1 && color6 == color5 && color4 != color2 && color5 != colorA0) + product2a = INTERPOLATE8(color2, color5); + else + product2a = color2; + + if (color2 == color6 && color5 != color3 && color1 == color2 && color2 != colorB2) + product1a = INTERPOLATE8(color2, color5); + else + if (color4 == color2 && color3 == color2 && color1 != color5 && color2 != colorB0) + product1a = INTERPOLATE8(color2, color5); + else + product1a = color5; + + *dP=product1a; + *(dP+1)=product1b; + *(dP+(width2))=product2a; + *(dP+1+(width2))=product2b; + + bP += 1; + dP += 2; + }//end of for ( finish= width etc..) + + line += 2; + srcPtr += srcPitch; + }; //endof: for (; height; height--) + } +} +///////////////////////////////////////////////////////////////////////////// + +#define colorMask4 0x0000EEE0 +#define lowPixelMask4 0x00001110 +#define qcolorMask4 0x0000CCC0 +#define qlowpixelMask4 0x00003330 + +#define INTERPOLATE4(A, B) ((((A & colorMask4) >> 1) + ((B & colorMask4) >> 1) + (A & B & lowPixelMask4))|((((A&0x0000000F)==0x00000006)?0x00000006:(((B&0x0000000F)==0x00000006)?0x00000006:(((A&0x0000000F)==0x00000000)?0x00000000:(((B&0x0000000F)==0x00000000)?0x00000000:0x0000000F)))))) + +#define Q_INTERPOLATE4(A, B, C, D) ((((A & qcolorMask4) >> 2) + ((B & qcolorMask4) >> 2) + ((C & qcolorMask4) >> 2) + ((D & qcolorMask4) >> 2) + ((((A & qlowpixelMask4) + (B & qlowpixelMask4) + (C & qlowpixelMask4) + (D & qlowpixelMask4)) >> 2) & qlowpixelMask4))| ((((A&0x0000000F)==0x00000006)?0x00000006:(((B&0x0000000F)==0x00000006)?0x00000006:(((C&0x0000000F)==0x00000006)?0x00000006:(((D&0x0000000F)==0x00000006)?0x00000006:(((A&0x0000000F)==0x00000000)?0x00000000:(((B&0x0000000F)==0x00000000)?0x00000000:(((C&0x0000000F)==0x00000000)?0x00000000:(((D&0x0000000F)==0x00000000)?0x00000000:0x0000000F)))))))))) + + +#define colorMask5 0x0000F7BC +#define lowPixelMask5 0x00000842 +#define qcolorMask5 0x0000E738 +#define qlowpixelMask5 0x000018C6 + +#define INTERPOLATE5(A, B) ((((A & colorMask5) >> 1) + ((B & colorMask5) >> 1) + (A & B & lowPixelMask5))|((((A&0x00000001)==0x00000000)?0x00000000:(((B&0x00000001)==0x00000000)?0x00000000:0x00000001)))) + +#define Q_INTERPOLATE5(A, B, C, D) ((((A & qcolorMask5) >> 2) + ((B & qcolorMask5) >> 2) + ((C & qcolorMask5) >> 2) + ((D & qcolorMask5) >> 2) + ((((A & qlowpixelMask5) + (B & qlowpixelMask5) + (C & qlowpixelMask5) + (D & qlowpixelMask5)) >> 2) & qlowpixelMask5))| ((((A&0x00000001)==0x00000000)?0x00000000:(((B&0x00000001)==0x00000000)?0x00000000:(((C&0x00000001)==0x00000000)?0x00000000:(((D&0x00000001)==0x00000000)?0x00000000:0x00000001)))))) +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +// +// ogl texture defines +// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// + +void DefineSubTextureSortHiRes(void) +{ + int x,y,dx2; + + if(!gTexName) + { + glGenTextures(1, &gTexName); + glBindTexture(GL_TEXTURE_2D, gTexName); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, iClampType); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, iClampType); + + if(iFilterType) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + } + else + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, iFilter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, iFilter); + } + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 512, 512, 0, GL_RGBA, GL_UNSIGNED_BYTE, texturebuffer); + } + else glBindTexture(GL_TEXTURE_2D, gTexName); + + glTexSubImage2D(GL_TEXTURE_2D, 0, XTexS<<1, YTexS<<1, + DXTexS<<1, DYTexS<<1, + GL_RGBA, GL_UNSIGNED_BYTE, texturebuffer); +} + +///////////////////////////////////////////////////////////////////////////// + +void DefineSubTextureSort(void) +{ + + if(!gTexName) + { + glGenTextures(1, &gTexName); + glBindTexture(GL_TEXTURE_2D, gTexName); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, iClampType); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, iClampType); + + if(iFilterType) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + } + else + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, iFilter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, iFilter); + } + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0,GL_RGBA, GL_UNSIGNED_BYTE, texturepart); + } + else glBindTexture(GL_TEXTURE_2D, gTexName); + + glTexSubImage2D(GL_TEXTURE_2D, 0, XTexS, YTexS, + DXTexS, DYTexS, + GL_RGBA, GL_UNSIGNED_BYTE, texturepart); +} + +///////////////////////////////////////////////////////////////////////////// + +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +// +// texture cache garbage collection +// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// + +void DoTexGarbageCollection(void) +{ + static unsigned short LRUCleaned=0; + unsigned short iC,iC1,iC2; + int i,j,iMax;textureSubCacheEntryS * tsb; + + iC=4;//=iSortTexCnt/2, + LRUCleaned+=iC; // we clean different textures each time + if((LRUCleaned+iC)>=iSortTexCnt) LRUCleaned=0; // wrap? wrap! + iC1=LRUCleaned; // range of textures to clean + iC2=LRUCleaned+iC; + + for(iC=iC1;iCl=0; + } + + for(i=0;i<3;i++) // remove all references to that textures + for(j=0;jpos.l; + if(iMax) + do + { + tsb++; + if(tsb->cTexID>=iC1 && tsb->cTexIDClutID=0; + } + while(--iMax); + } + + usLRUTexPage=LRUCleaned; +} + +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +// +// search cache for existing (already used) parts +// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// + +u8 * CheckTextureInSubSCache(long TextureMode,unsigned long GivenClutId,unsigned short * pCache) +{ + textureSubCacheEntryS * tsx, * tsb, *tsg;//, *tse=NULL; + int i,iMax;EXLong npos; + u8 cx,cy; + int iC,j,k;unsigned long rx,ry,mx,my; + EXLong * ul=0, * uls; + EXLong rfree; + u8 cXAdj,cYAdj; + + npos.l=*((unsigned long *)&gl_ux[4]); + + //--------------------------------------------------------------// + // find matching texturepart first... speed up... + //--------------------------------------------------------------// + + tsg=pscSubtexStore[TextureMode][GlobalTexturePage]; + tsg+=((GivenClutId&CLUTCHK)>>CLUTSHIFT)*SOFFB; + + iMax=tsg->pos.l; + if(iMax) + { + i=iMax; + tsb=tsg+1; + do + { + if(GivenClutId==tsb->ClutID && + (INCHECK(tsb->pos,npos))) + { + { + cx=tsb->pos.c[3]-tsb->posTX; + cy=tsb->pos.c[1]-tsb->posTY; + + gl_ux[0]-=cx; + gl_ux[1]-=cx; + gl_ux[2]-=cx; + gl_ux[3]-=cx; + gl_vy[0]-=cy; + gl_vy[1]-=cy; + gl_vy[2]-=cy; + gl_vy[3]-=cy; + + ubOpaqueDraw=tsb->Opaque; + *pCache=tsb->cTexID; + return NULL; + } + } + tsb++; + } + while(--i); + } + + //----------------------------------------------------// + + cXAdj=1;cYAdj=1; + + rx=(int)gl_ux[6]-(int)gl_ux[7]; + ry=(int)gl_ux[4]-(int)gl_ux[5]; + + tsx=NULL;tsb=tsg+1; + for(i=0;iClutID) {tsx=tsb;break;} + } + + if(!tsx) + { + iMax++; + if(iMax>=SOFFB-2) + { + if(iTexGarbageCollection) // gc mode? + { + if(*pCache==0) + { + dwTexPageComp|=(1<ClutID) + { + if(!tsx) {tsx=tsb;rfree.l=npos.l;} // + else tsb->ClutID=0; + rfree.c[3]=min(rfree.c[3],tsb->pos.c[3]); + rfree.c[2]=max(rfree.c[2],tsb->pos.c[2]); + rfree.c[1]=min(rfree.c[1],tsb->pos.c[1]); + rfree.c[0]=max(rfree.c[0],tsb->pos.c[0]); + MarkFree(tsb); + } + + if(tsx) // 3. if one or more found, create a new rect with bigger size + { + *((unsigned long *)&gl_ux[4])=npos.l=rfree.l; + rx=(int)rfree.c[2]-(int)rfree.c[3]; + ry=(int)rfree.c[0]-(int)rfree.c[1]; + DoTexGarbageCollection(); + + goto ENDLOOP3; + } + } + + iMax=1; + } + tsx=tsg+iMax; + tsg->pos.l=iMax; + } + + //----------------------------------------------------// + // now get a free texture space + //----------------------------------------------------// + + if(iTexGarbageCollection) usLRUTexPage=0; + +ENDLOOP3: + + rx+=3;if(rx>255) {cXAdj=0;rx=255;} + ry+=3;if(ry>255) {cYAdj=0;ry=255;} + + iC=usLRUTexPage; + + for(k=0;kl;ul=uls+1; + + //--------------------------------------------------// + // first time + + if(!iMax) + { + rfree.l=0; + + if(rx>252 && ry>252) + {uls->l=1;ul->l=0xffffffff;ul=0;goto ENDLOOP;} + + if(rx<253) + { + uls->l=uls->l+1; + ul->c[3]=rx; + ul->c[2]=255-rx; + ul->c[1]=0; + ul->c[0]=ry; + ul++; + } + + if(ry<253) + { + uls->l=uls->l+1; + ul->c[3]=0; + ul->c[2]=255; + ul->c[1]=ry; + ul->c[0]=255-ry; + } + ul=0; + goto ENDLOOP; + } + + //--------------------------------------------------// + for(i=0;il!=0xffffffff && + ry<=ul->c[0] && + rx<=ul->c[2]) + { + rfree=*ul; + mx=ul->c[2]-2; + my=ul->c[0]-2; + if(rxc[3]+=rx; + ul->c[2]-=rx; + ul->c[0]=ry; + + for(ul=uls+1,j=0;jl==0xffffffff) break; + + if(jl=uls->l+1; + + ul->c[3]=rfree.c[3]; + ul->c[2]=rfree.c[2]; + ul->c[1]=rfree.c[1]+ry; + ul->c[0]=rfree.c[0]-ry; + } + } + else if(rxc[3]+=rx; + ul->c[2]-=rx; + } + else if(ryc[1]+=ry; + ul->c[0]-=ry; + } + else + { + ul->l=0xffffffff; + } + ul=0; + goto ENDLOOP; + } + } + + //--------------------------------------------------// + + iC++; if(iC>=iSortTexCnt) iC=0; + } + + //----------------------------------------------------// + // check, if free space got + //----------------------------------------------------// + +ENDLOOP: + if(ul) + { + ////////////////////////////////////////////////////// + + { + dwTexPageComp=0; + + for(i=0;i<3;i++) // cleaning up + for(j=0;jpos.l=0; + (tsb+SOFFB)->pos.l=0; + (tsb+SOFFC)->pos.l=0; + (tsb+SOFFD)->pos.l=0; + } + for(i=0;il=0;} + usLRUTexPage=0; + } + + ////////////////////////////////////////////////////// + iC=usLRUTexPage; + uls=pxSsubtexLeft[usLRUTexPage]; + uls->l=0;ul=uls+1; + rfree.l=0; + + if(rx>252 && ry>252) + {uls->l=1;ul->l=0xffffffff;} + else + { + if(rx<253) + { + uls->l=uls->l+1; + ul->c[3]=rx; + ul->c[2]=255-rx; + ul->c[1]=0; + ul->c[0]=ry; + ul++; + } + if(ry<253) + { + uls->l=uls->l+1; + ul->c[3]=0; + ul->c[2]=255; + ul->c[1]=ry; + ul->c[0]=255-ry; + } + } + tsg->pos.l=1;tsx=tsg+1; + } + + rfree.c[3]+=cXAdj; + rfree.c[1]+=cYAdj; + + tsx->cTexID =*pCache=iC; + tsx->pos = npos; + tsx->ClutID = GivenClutId; + tsx->posTX = rfree.c[3]; + tsx->posTY = rfree.c[1]; + + cx=gl_ux[7]-rfree.c[3]; + cy=gl_ux[5]-rfree.c[1]; + + gl_ux[0]-=cx; + gl_ux[1]-=cx; + gl_ux[2]-=cx; + gl_ux[3]-=cx; + gl_vy[0]-=cy; + gl_vy[1]-=cy; + gl_vy[2]-=cy; + gl_vy[3]-=cy; + + XTexS=rfree.c[3]; + YTexS=rfree.c[1]; + + return &tsx->Opaque; +} + +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +// +// search cache for free place (on compress) +// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// + +BOOL GetCompressTexturePlace(textureSubCacheEntryS * tsx) +{ + int i,j,k,iMax,iC;unsigned long rx,ry,mx,my; + EXLong * ul=0, * uls, rfree; + u8 cXAdj=1,cYAdj=1; + + rx=(int)tsx->pos.c[2]-(int)tsx->pos.c[3]; + ry=(int)tsx->pos.c[0]-(int)tsx->pos.c[1]; + + rx+=3;if(rx>255) {cXAdj=0;rx=255;} + ry+=3;if(ry>255) {cYAdj=0;ry=255;} + + iC=usLRUTexPage; + + for(k=0;kl;ul=uls+1; + + //--------------------------------------------------// + // first time + + if(!iMax) + { + rfree.l=0; + + if(rx>252 && ry>252) + {uls->l=1;ul->l=0xffffffff;ul=0;goto TENDLOOP;} + + if(rx<253) + { + uls->l=uls->l+1; + ul->c[3]=rx; + ul->c[2]=255-rx; + ul->c[1]=0; + ul->c[0]=ry; + ul++; + } + + if(ry<253) + { + uls->l=uls->l+1; + ul->c[3]=0; + ul->c[2]=255; + ul->c[1]=ry; + ul->c[0]=255-ry; + } + ul=0; + goto TENDLOOP; + } + + //--------------------------------------------------// + for(i=0;il!=0xffffffff && + ry<=ul->c[0] && + rx<=ul->c[2]) + { + rfree=*ul; + mx=ul->c[2]-2; + my=ul->c[0]-2; + + if(rxc[3]+=rx; + ul->c[2]-=rx; + ul->c[0]=ry; + + for(ul=uls+1,j=0;jl==0xffffffff) break; + + if(jl=uls->l+1; + + ul->c[3]=rfree.c[3]; + ul->c[2]=rfree.c[2]; + ul->c[1]=rfree.c[1]+ry; + ul->c[0]=rfree.c[0]-ry; + } + } + else if(rxc[3]+=rx; + ul->c[2]-=rx; + } + else if(ryc[1]+=ry; + ul->c[0]-=ry; + } + else + { + ul->l=0xffffffff; + } + ul=0; + goto TENDLOOP; + } + } + + //--------------------------------------------------// + + iC++; if(iC>=iSortTexCnt) iC=0; + } + + //----------------------------------------------------// + // check, if free space got + //----------------------------------------------------// + +TENDLOOP: + if(ul) return FALSE; + + rfree.c[3]+=cXAdj; + rfree.c[1]+=cYAdj; + + tsx->cTexID = iC; + tsx->posTX = rfree.c[3]; + tsx->posTY = rfree.c[1]; + + XTexS=rfree.c[3]; + YTexS=rfree.c[1]; + + return TRUE; +} + +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +// +// compress texture cache (to make place for new texture part, if needed) +// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// + +void CompressTextureSpace(void) +{ + textureSubCacheEntryS * tsx, * tsg, * tsb; + int i,j,k,m,n,iMax;EXLong * ul, r,opos; + short sOldDST=DrawSemiTrans,cx,cy; + long lOGTP=GlobalTexturePage; + unsigned long l,row; + unsigned long * lSRCPtr; + + opos.l=*((unsigned long *)&gl_ux[4]); + + // 1. mark all textures as free + for(i=0;il=0;} + usLRUTexPage=0; + + // 2. compress + for(j=0;j<3;j++) + { + for(k=0;kpos.l=0; + (tsg+SOFFB)->pos.l=0; + (tsg+SOFFC)->pos.l=0; + (tsg+SOFFD)->pos.l=0; + continue; + } + + for(m=0;m<4;m++,tsg+=SOFFB) + { + iMax=tsg->pos.l; + + tsx=tsg+1; + for(i=0;iClutID) + { + r.l=tsx->pos.l; + for(n=i+1,tsb=tsx+1;nClutID==tsb->ClutID) + { + r.c[3]=min(r.c[3],tsb->pos.c[3]); + r.c[2]=max(r.c[2],tsb->pos.c[2]); + r.c[1]=min(r.c[1],tsb->pos.c[1]); + r.c[0]=max(r.c[0],tsb->pos.c[0]); + tsb->ClutID=0; + } + } + +// if(r.l!=tsx->pos.l) + { + cx=((tsx->ClutID << 4) & 0x3F0); + cy=((tsx->ClutID >> 6) & CLUTYMASK); + + if(j!=2) + { + // palette check sum + l=0;lSRCPtr=(unsigned long *)(psxVuw+cx+(cy*1024)); + if(j==1) for(row=1;row<129;row++) l+=((*lSRCPtr++)-1)*row; + else for(row=1;row<9;row++) l+=((*lSRCPtr++)-1)<ClutID&(0x00003fff<<16))) + { + tsx->ClutID=0;continue; + } + } + + tsx->pos.l=r.l; + if(!GetCompressTexturePlace(tsx)) // no place? + { + for(i=0;i<3;i++) // -> clean up everything + for(j=0;jpos.l=0; + (tsb+SOFFB)->pos.l=0; + (tsb+SOFFC)->pos.l=0; + (tsb+SOFFD)->pos.l=0; + } + for(i=0;il=0;} + usLRUTexPage=0; + DrawSemiTrans=sOldDST; + GlobalTexturePage=lOGTP; + *((unsigned long *)&gl_ux[4])=opos.l; + dwTexPageComp=0; + + return; + } + + if(tsx->ClutID&(1<<30)) DrawSemiTrans=1; + else DrawSemiTrans=0; + *((unsigned long *)&gl_ux[4])=r.l; + + gTexName=uiStexturePage[tsx->cTexID]; + LoadSubTexFn(k,j,cx,cy); + uiStexturePage[tsx->cTexID]=gTexName; + tsx->Opaque=ubOpaqueDraw; + } + } + } + + if(iMax) + { + tsx=tsg+iMax; + while(!tsx->ClutID && iMax) {tsx--;iMax--;} + tsg->pos.l=iMax; + } + + } + } + } + + if(dwTexPageComp==0xffffffff) dwTexPageComp=0; + + *((unsigned long *)&gl_ux[4])=opos.l; + GlobalTexturePage=lOGTP; + DrawSemiTrans=sOldDST; +} + +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +// +// main entry for searching/creating textures, called from prim.c +// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// + +GLuint SelectSubTextureS(long TextureMode, unsigned long GivenClutId) +{ + u8 * OPtr;unsigned short iCache;short cx,cy; + + // sort sow/tow infos for fast access + + u8 ma1,ma2,mi1,mi2; + if(gl_ux[0]>gl_ux[1]) {mi1=gl_ux[1];ma1=gl_ux[0];} + else {mi1=gl_ux[0];ma1=gl_ux[1];} + if(gl_ux[2]>gl_ux[3]) {mi2=gl_ux[3];ma2=gl_ux[2];} + else {mi2=gl_ux[2];ma2=gl_ux[3];} + if(mi1>mi2) gl_ux[7]=mi2; + else gl_ux[7]=mi1; + if(ma1>ma2) gl_ux[6]=ma1; + else gl_ux[6]=ma2; + + if(gl_vy[0]>gl_vy[1]) {mi1=gl_vy[1];ma1=gl_vy[0];} + else {mi1=gl_vy[0];ma1=gl_vy[1];} + if(gl_vy[2]>gl_vy[3]) {mi2=gl_vy[3];ma2=gl_vy[2];} + else {mi2=gl_vy[2];ma2=gl_vy[3];} + if(mi1>mi2) gl_ux[5]=mi2; + else gl_ux[5]=mi1; + if(ma1>ma2) gl_ux[4]=ma1; + else gl_ux[4]=ma2; + + // get clut infos in one 32 bit val + + if(TextureMode==2) // no clut here + { + GivenClutId=CLUTUSED|(DrawSemiTrans<<30);cx=cy=0; + + if(iFrameTexType && Fake15BitTexture()) + return (GLuint)gTexName; + } + else + { + cx=((GivenClutId << 4) & 0x3F0); // but here + cy=((GivenClutId >> 6) & CLUTYMASK); + GivenClutId=(GivenClutId&CLUTMASK)|(DrawSemiTrans<<30)|CLUTUSED; + + // palette check sum.. removed MMX asm, this easy func works as well + { + unsigned long l=0,row; + + unsigned long * lSRCPtr=(unsigned long *)(psxVuw+cx+(cy*1024)); + if(TextureMode==1) for(row=1;row<129;row++) l+=((*lSRCPtr++)-1)*row; + else for(row=1;row<9;row++) l+=((*lSRCPtr++)-1)<