/*************************************************************************** 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 #define MODE_RAW 0 #define MODE_X11 1 #define MODE_SDL 2 int pandora_driver_mode = MODE_RAW; int use_fsaa = 0; EGLDisplay display; EGLConfig config; EGLContext context; EGLSurface surface; #if defined(USE_X11) #include "X11/Xlib.h" #include "X11/Xutil.h" #include "X11/Xatom.h" Window x11Window = 0; Display* x11Display = 0; long x11Screen = 0; XVisualInfo x11Visual; XVisualInfo* px11Visual = 0; Colormap x11Colormap = 0; #endif EGLint attrib_list_fsaa[] = { EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_BUFFER_SIZE, 0, EGL_DEPTH_SIZE, 16, EGL_SAMPLE_BUFFERS, 1, EGL_SAMPLES, 4, EGL_NONE }; EGLint attrib_list[] = { EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_BUFFER_SIZE, 0, EGL_DEPTH_SIZE, 16, EGL_NONE }; 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(){ printf ("GL init\n"); EGLint numConfigs; EGLint majorVersion; EGLint minorVersion; #if defined(USE_X11) enum { _NET_WM_STATE_REMOVE =0, _NET_WM_STATE_ADD = 1, _NET_WM_STATE_TOGGLE =2 }; Window sRootWindow; XSetWindowAttributes sWA; unsigned int ui32Mask; int i32Depth; #endif EGLint *attribList = NULL; if (use_fsaa) { printf( "GLES: Using Full Scene Antialiasing\n" ); attribList = attrib_list_fsaa; } else { attribList = attrib_list; } #if defined(USE_X11) pandora_driver_mode = MODE_X11; // TODO make configurable #else pandora_driver_mode = MODE_RAW; // TODO make configurable #endif switch(pandora_driver_mode) { #if defined(USE_X11) case MODE_X11: // Initializes the display and screen x11Display = XOpenDisplay( ":0" ); if (!x11Display) { printf("GLES Error: Unable to open X display\n"); } x11Screen = XDefaultScreen( x11Display ); // Gets the display parameters so we can pass the same parameters to the window to be created. sRootWindow = RootWindow(x11Display, x11Screen); i32Depth = DefaultDepth(x11Display, x11Screen); px11Visual = &x11Visual; XMatchVisualInfo( x11Display, x11Screen, i32Depth, TrueColor, px11Visual); if (!px11Visual) { printf("GLES Error: Unable to acquire visual\n"); } // Colormap of the specified visual type for the display. x11Colormap = XCreateColormap( x11Display, sRootWindow, px11Visual->visual, AllocNone ); sWA.colormap = x11Colormap; // List of events to be handled by the application. Add to these for handling other events. sWA.event_mask = StructureNotifyMask | ExposureMask | ButtonPressMask | ButtonReleaseMask | KeyPressMask | KeyReleaseMask; // Display capabilities list. ui32Mask = CWBackPixel | CWBorderPixel | CWEventMask | CWColormap; // Creates the X11 window x11Window = XCreateWindow( x11Display, RootWindow(x11Display, x11Screen), 0, 0, iResX, iResY, 0, CopyFromParent, InputOutput, CopyFromParent, ui32Mask, &sWA); // Make the window viewable and flush the output buffer. XMapWindow(x11Display, x11Window); XFlush(x11Display); // Make the window fullscreen unsigned char fullScreen = 1; Atom wmState = XInternAtom(x11Display, "_NET_WM_STATE", False); Atom wmFullScreen = XInternAtom(x11Display,"_NET_WM_STATE_FULLSCREEN", False); XEvent xev; xev.xclient.type = ClientMessage; xev.xclient.serial = 0; xev.xclient.send_event = True; xev.xclient.window = x11Window; xev.xclient.message_type = wmState; xev.xclient.format = 32; xev.xclient.data.l[0] = (fullScreen ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE); xev.xclient.data.l[1] = wmFullScreen; xev.xclient.data.l[2] = 0; XSendEvent(x11Display, DefaultRootWindow(x11Display), False, SubstructureRedirectMask | SubstructureNotifyMask, &xev); display = eglGetDisplay( (EGLNativeDisplayType)x11Display ); break; #endif case MODE_RAW: default: display = eglGetDisplay( (EGLNativeDisplayType)0 ); break; } if( display == EGL_NO_DISPLAY ) { printf( "GLES EGL Error: GL No Display\n" ); } if( !eglInitialize( display, &majorVersion, &minorVersion ) ) { printf( "GLES EGL Error: eglInitialize failed\n" ); } if( !eglChooseConfig( display, attribList, &config, 1, &numConfigs ) ) { printf( "GLES EGL Error: eglChooseConfig failed\n" ); } context = eglCreateContext( display, config, NULL, NULL ); if( context==0 ) { printf( "GLES EGL Error: eglCreateContext failed\n" ); } switch(pandora_driver_mode) { #if defined(USE_X11) case MODE_X11: surface = eglCreateWindowSurface( display, config, (EGLNativeDisplayType)x11Window, NULL ); break; #endif case MODE_RAW: default: surface = eglCreateWindowSurface( display, config, (EGLNativeDisplayType)0, NULL ); break; } eglMakeCurrent( display, surface, surface, context ); if (!TestEGLError("eglMakeCurrent")) printf("error eglMakeCurrent"); else printf("GLES Window Opened\n"); } #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 eglMakeCurrent( display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT ); eglDestroySurface( display, surface ); eglDestroyContext( display, context ); eglTerminate( display ); #if defined(USE_X11) if (pandora_driver_mode == MODE_X11) { if (x11Window) XDestroyWindow(x11Display, x11Window); if (x11Colormap) XFreeColormap( x11Display, x11Colormap ); if (x11Display) XCloseDisplay(x11Display); } #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; } } //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////