4737 lines
121 KiB
C
Executable File
4737 lines
121 KiB
C
Executable File
/***************************************************************************
|
|
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. *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
#include "stdafx.h"
|
|
|
|
#define _IN_PRIMDRAW
|
|
|
|
#include "externals.h"
|
|
#include "gpu.h"
|
|
#include "draw.h"
|
|
#include "soft.h"
|
|
#include "texture.h"
|
|
#include "PGXP_gpu.h"
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
// defines
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
#define DEFOPAQUEON glAlphaFunc(GL_EQUAL,0.0f);bBlendEnable=FALSE;glDisable(GL_BLEND);
|
|
#define DEFOPAQUEOFF glAlphaFunc(GL_GREATER,0.49f);
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
// globals
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
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; //
|
|
uint32_t ulOLDCOL=0; // active color
|
|
uint32_t ulClutID; // clut
|
|
|
|
uint32_t dwCfgFixes; // game fixes
|
|
uint32_t dwActFixes=0;
|
|
uint32_t dwEmuFixes=0;
|
|
BOOL bUseFixes;
|
|
|
|
int 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
|
|
}
|
|
|
|
unsigned int DoubleBGR2RGB (unsigned int BGR)
|
|
{
|
|
unsigned int 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 (uint32_t BGR)
|
|
{
|
|
return ((BGR>>3)&0x1f)|((BGR&0xf80000)>>9)|((BGR&0xf800)>>6);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
// OpenGL primitive drawing commands
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
static __inline void PRIMdrawTexturedQuad(OGLVertex* vertex1, OGLVertex* vertex2,
|
|
OGLVertex* vertex3, OGLVertex* vertex4)
|
|
{
|
|
if (PGXP_vDebug)
|
|
{
|
|
if(PGXP_DrawDebugTriQuad(vertex1, vertex2, vertex4, vertex3))
|
|
return;
|
|
}
|
|
|
|
|
|
glBegin(GL_TRIANGLE_STRIP);
|
|
glTexCoord2fv(&vertex1->sow);
|
|
PGXP_glVertexfv(&vertex1->x);
|
|
|
|
glTexCoord2fv(&vertex2->sow);
|
|
PGXP_glVertexfv(&vertex2->x);
|
|
|
|
glTexCoord2fv(&vertex4->sow);
|
|
PGXP_glVertexfv(&vertex4->x);
|
|
|
|
glTexCoord2fv(&vertex3->sow);
|
|
PGXP_glVertexfv(&vertex3->x);
|
|
glEnd();
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////
|
|
|
|
static __inline void PRIMdrawTexturedTri(OGLVertex* vertex1, OGLVertex* vertex2,
|
|
OGLVertex* vertex3)
|
|
{
|
|
if (PGXP_vDebug)
|
|
{
|
|
if(PGXP_DrawDebugTri(vertex1, vertex2, vertex3))
|
|
return;
|
|
}
|
|
|
|
glBegin(GL_TRIANGLES);
|
|
glTexCoord2fv(&vertex1->sow);
|
|
PGXP_glVertexfv(&vertex1->x);
|
|
|
|
glTexCoord2fv(&vertex2->sow);
|
|
PGXP_glVertexfv(&vertex2->x);
|
|
|
|
glTexCoord2fv(&vertex3->sow);
|
|
PGXP_glVertexfv(&vertex3->x);
|
|
glEnd();
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////
|
|
|
|
static __inline void PRIMdrawTexGouraudTriColor(OGLVertex* vertex1, OGLVertex* vertex2,
|
|
OGLVertex* vertex3)
|
|
{
|
|
if (PGXP_vDebug)
|
|
{
|
|
if(PGXP_DrawDebugTri(vertex1, vertex2, vertex3))
|
|
return;
|
|
}
|
|
|
|
glBegin(GL_TRIANGLES);
|
|
|
|
SETPCOL(vertex1);
|
|
glTexCoord2fv(&vertex1->sow);
|
|
PGXP_glVertexfv(&vertex1->x);
|
|
|
|
SETPCOL(vertex2);
|
|
glTexCoord2fv(&vertex2->sow);
|
|
PGXP_glVertexfv(&vertex2->x);
|
|
|
|
SETPCOL(vertex3);
|
|
glTexCoord2fv(&vertex3->sow);
|
|
PGXP_glVertexfv(&vertex3->x);
|
|
glEnd();
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////
|
|
|
|
static __inline void PRIMdrawTexGouraudTriColorQuad(OGLVertex* vertex1, OGLVertex* vertex2,
|
|
OGLVertex* vertex3, OGLVertex* vertex4)
|
|
{
|
|
if (PGXP_vDebug)
|
|
{
|
|
if(PGXP_DrawDebugTriQuad(vertex1, vertex2, vertex4, vertex3))
|
|
return;
|
|
}
|
|
|
|
glBegin(GL_TRIANGLE_STRIP);
|
|
SETPCOL(vertex1);
|
|
glTexCoord2fv(&vertex1->sow);
|
|
PGXP_glVertexfv(&vertex1->x);
|
|
|
|
SETPCOL(vertex2);
|
|
glTexCoord2fv(&vertex2->sow);
|
|
PGXP_glVertexfv(&vertex2->x);
|
|
|
|
SETPCOL(vertex4);
|
|
glTexCoord2fv(&vertex4->sow);
|
|
PGXP_glVertexfv(&vertex4->x);
|
|
|
|
SETPCOL(vertex3);
|
|
glTexCoord2fv(&vertex3->sow);
|
|
PGXP_glVertexfv(&vertex3->x);
|
|
glEnd();
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////
|
|
|
|
static __inline void PRIMdrawTri(OGLVertex* vertex1, OGLVertex* vertex2, OGLVertex* vertex3)
|
|
{
|
|
if (PGXP_vDebug)
|
|
{
|
|
if(PGXP_DrawDebugTri(vertex1, vertex2, vertex3))
|
|
return;
|
|
}
|
|
|
|
glBegin(GL_TRIANGLES);
|
|
PGXP_glVertexfv(&vertex1->x);
|
|
PGXP_glVertexfv(&vertex2->x);
|
|
PGXP_glVertexfv(&vertex3->x);
|
|
glEnd();
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////
|
|
|
|
static __inline void PRIMdrawTri2(OGLVertex* vertex1, OGLVertex* vertex2,
|
|
OGLVertex* vertex3, OGLVertex* vertex4)
|
|
{
|
|
if (PGXP_vDebug)
|
|
{
|
|
if(PGXP_DrawDebugTriQuad(vertex1, vertex3, vertex2, vertex4))
|
|
return;
|
|
}
|
|
|
|
glBegin(GL_TRIANGLE_STRIP);
|
|
PGXP_glVertexfv(&vertex1->x);
|
|
PGXP_glVertexfv(&vertex3->x);
|
|
PGXP_glVertexfv(&vertex2->x);
|
|
PGXP_glVertexfv(&vertex4->x);
|
|
glEnd();
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////
|
|
|
|
static __inline void PRIMdrawGouraudTriColor(OGLVertex* vertex1, OGLVertex* vertex2,
|
|
OGLVertex* vertex3)
|
|
{
|
|
if (PGXP_vDebug)
|
|
{
|
|
if(PGXP_DrawDebugTri(vertex1, vertex2, vertex3))
|
|
return;
|
|
}
|
|
|
|
glBegin(GL_TRIANGLES);
|
|
SETPCOL(vertex1);
|
|
PGXP_glVertexfv(&vertex1->x);
|
|
|
|
SETPCOL(vertex2);
|
|
PGXP_glVertexfv(&vertex2->x);
|
|
|
|
SETPCOL(vertex3);
|
|
PGXP_glVertexfv(&vertex3->x);
|
|
glEnd();
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////
|
|
|
|
static __inline void PRIMdrawGouraudTri2Color(OGLVertex* vertex1, OGLVertex* vertex2,
|
|
OGLVertex* vertex3, OGLVertex* vertex4)
|
|
{
|
|
if (PGXP_vDebug)
|
|
{
|
|
if(PGXP_DrawDebugTriQuad(vertex1, vertex3, vertex2, vertex4))
|
|
return;
|
|
}
|
|
|
|
glBegin(GL_TRIANGLE_STRIP);
|
|
SETPCOL(vertex1);
|
|
PGXP_glVertexfv(&vertex1->x);
|
|
|
|
SETPCOL(vertex3);
|
|
PGXP_glVertexfv(&vertex3->x);
|
|
|
|
SETPCOL(vertex2);
|
|
PGXP_glVertexfv(&vertex2->x);
|
|
|
|
SETPCOL(vertex4);
|
|
PGXP_glVertexfv(&vertex4->x);
|
|
glEnd();
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////
|
|
|
|
static __inline void PRIMdrawFlatLine(OGLVertex* vertex1, OGLVertex* vertex2,OGLVertex* vertex3, OGLVertex* vertex4)
|
|
{
|
|
if (PGXP_vDebug)
|
|
{
|
|
if(PGXP_DrawDebugQuad(vertex1, vertex2, vertex3, vertex4))
|
|
return;
|
|
}
|
|
|
|
glBegin(GL_QUADS);
|
|
|
|
SETPCOL(vertex1);
|
|
|
|
PGXP_glVertexfv(&vertex1->x);
|
|
PGXP_glVertexfv(&vertex2->x);
|
|
PGXP_glVertexfv(&vertex3->x);
|
|
PGXP_glVertexfv(&vertex4->x);
|
|
glEnd();
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////
|
|
|
|
static __inline void PRIMdrawGouraudLine(OGLVertex* vertex1, OGLVertex* vertex2,OGLVertex* vertex3, OGLVertex* vertex4)
|
|
{
|
|
if (PGXP_vDebug)
|
|
{
|
|
if(PGXP_DrawDebugQuad(vertex1, vertex2, vertex3, vertex4))
|
|
return;
|
|
}
|
|
|
|
glBegin(GL_QUADS);
|
|
|
|
SETPCOL(vertex1);
|
|
PGXP_glVertexfv(&vertex1->x);
|
|
|
|
SETPCOL(vertex2);
|
|
PGXP_glVertexfv(&vertex2->x);
|
|
|
|
SETPCOL(vertex3);
|
|
PGXP_glVertexfv(&vertex3->x);
|
|
|
|
SETPCOL(vertex4);
|
|
PGXP_glVertexfv(&vertex4->x);
|
|
glEnd();
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////
|
|
|
|
static __inline void PRIMdrawQuad(OGLVertex* vertex1, OGLVertex* vertex2,
|
|
OGLVertex* vertex3, OGLVertex* vertex4)
|
|
{
|
|
if (PGXP_vDebug)
|
|
{
|
|
if(PGXP_DrawDebugQuad(vertex1, vertex2, vertex3, vertex4))
|
|
return;
|
|
}
|
|
|
|
glBegin(GL_QUADS);
|
|
PGXP_glVertexfv(&vertex1->x);
|
|
PGXP_glVertexfv(&vertex2->x);
|
|
PGXP_glVertexfv(&vertex3->x);
|
|
PGXP_glVertexfv(&vertex4->x);
|
|
glEnd();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
// 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
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
static __inline void SetZMask3O(void)
|
|
{
|
|
if(iUseMask && DrawSemiTrans && !iSetMask)
|
|
{
|
|
vertex[0].z=vertex[1].z=vertex[2].z=gl_z;
|
|
gl_z+=0.00004f;
|
|
}
|
|
}
|
|
|
|
static __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;
|
|
}
|
|
}
|
|
}
|
|
|
|
static __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;
|
|
}
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
static __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;
|
|
}
|
|
}
|
|
|
|
static __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;
|
|
}
|
|
}
|
|
}
|
|
|
|
static __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;
|
|
}
|
|
}
|
|
}
|
|
|
|
static __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;}
|
|
}
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
static __inline void SetRenderState(uint32_t DrawAttributes)
|
|
{
|
|
bDrawNonShaded = (SHADETEXBIT(DrawAttributes)) ? TRUE : FALSE;
|
|
DrawSemiTrans = (SEMITRANSBIT(DrawAttributes)) ? TRUE : FALSE;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
static __inline void SetRenderColor(uint32_t 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(uint32_t 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(uint32_t 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(sxmax<drawX) return FALSE;
|
|
sxmin=min(lx0,min(lx1,min(lx2,lx3)));
|
|
if(sxmin>drawW) return FALSE;
|
|
symax=max(ly0,max(ly1,max(ly2,ly3)));
|
|
if(symax<drawY) return FALSE;
|
|
symin=min(ly0,min(ly1,min(ly2,ly3)));
|
|
if(symin>drawH) 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(sxmax<drawX) return FALSE;
|
|
sxmin=min(lx0,min(lx1,lx2));
|
|
if(sxmin>drawW) return FALSE;
|
|
symax=max(ly0,max(ly1,ly2));
|
|
if(symax<drawY) return FALSE;
|
|
symin=min(ly0,min(ly1,ly2));
|
|
if(symin>drawH) 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 (int 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)
|
|
////////////////////////////////////////////////////////////////////////
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
unsigned char * LoadDirectMovieFast(void);
|
|
|
|
void UploadScreenEx(int 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(int 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((uint32_t)0x01000000);
|
|
SetRenderMode((uint32_t)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(unsigned char * baseAddr)
|
|
{
|
|
uint32_t gdata = ((uint32_t*)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(unsigned char * baseAddr)
|
|
{
|
|
uint32_t gdata = ((uint32_t *)baseAddr)[0];
|
|
UpdateGlobalTP((unsigned short)gdata);
|
|
GlobalTextREST = (gdata&0x00ffffff)>>9;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
// cmd: turn on/off texture window
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
void cmdTextureWindow(unsigned char *baseAddr)
|
|
{
|
|
uint32_t gdata = ((uint32_t *)baseAddr)[0];
|
|
uint32_t 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 = (uint32_t)(32 - (TWin.Position.y1 >> 3));
|
|
XAlign = (uint32_t)(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(unsigned char * baseAddr)
|
|
{
|
|
uint32_t gdata = ((uint32_t *)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(unsigned char * baseAddr)
|
|
{
|
|
uint32_t gdata = ((uint32_t *)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(unsigned char * baseAddr)
|
|
{
|
|
uint32_t gdata = ((uint32_t *)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(unsigned char * 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(unsigned char * 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(unsigned char * baseAddr)
|
|
{
|
|
uint32_t *gpuData = ((uint32_t *) 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(baseAddr);
|
|
|
|
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 ||
|
|
ly2<pd->DisplayEnd.y))
|
|
{
|
|
bDrawTextured = FALSE;
|
|
bDrawSmoothShaded = FALSE;
|
|
SetRenderState((uint32_t)0x01000000);
|
|
SetRenderMode((uint32_t)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(ly2<pd->DisplayEnd.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((uint32_t)0x01000000);
|
|
SetRenderMode((uint32_t)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;j<imageSY;j++)
|
|
for(i=0;i<imageSX;i++)
|
|
psxVuw [(1024*((imageY1+j)&iGPUHeightMask))+((imageX1+i)&0x3ff)]=
|
|
psxVuw[(1024*((imageY0+j)&iGPUHeightMask))+((imageX0+i)&0x3ff)];
|
|
|
|
if(!PSXDisplay.RGB24)
|
|
{
|
|
imageXE=imageX1+imageSX;
|
|
imageYE=imageY1+imageSY;
|
|
|
|
if(imageYE>iGPUHeight && 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(unsigned char * 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<imageSY;j++)
|
|
{
|
|
for(i=0;i<imageSX;i++) *DSTPtr++ = *SRCPtr++;
|
|
SRCPtr += LineOffset;
|
|
DSTPtr += LineOffset;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
uint32_t *SRCPtr, *DSTPtr;
|
|
unsigned short LineOffset;
|
|
int dx=imageSX>>1;
|
|
|
|
SRCPtr = (uint32_t *)(psxVuw + (1024*imageY0) + imageX0);
|
|
DSTPtr = (uint32_t *)(psxVuw + (1024*imageY1) + imageX1);
|
|
|
|
LineOffset = 512 - dx;
|
|
|
|
for(j=0;j<imageSY;j++)
|
|
{
|
|
for(i=0;i<dx;i++) *DSTPtr++ = *SRCPtr++;
|
|
SRCPtr += LineOffset;
|
|
DSTPtr += LineOffset;
|
|
}
|
|
}
|
|
|
|
if (!PSXDisplay.RGB24)
|
|
{
|
|
InvalidateTextureArea(imageX1,imageY1,imageSX-1,imageSY-1);
|
|
|
|
if (CheckAgainstScreen(imageX1,imageY1,imageSX,imageSY))
|
|
{
|
|
if(imageX1>=PreviousPSXDisplay.DisplayPosition.x &&
|
|
imageX1<PreviousPSXDisplay.DisplayEnd.x &&
|
|
imageY1>=PreviousPSXDisplay.DisplayPosition.y &&
|
|
imageY1<PreviousPSXDisplay.DisplayEnd.y)
|
|
{
|
|
imageX1 += imageSX;
|
|
imageY1 += imageSY;
|
|
|
|
if(imageX1>=PreviousPSXDisplay.DisplayPosition.x &&
|
|
imageX1<=PreviousPSXDisplay.DisplayEnd.x &&
|
|
imageY1>=PreviousPSXDisplay.DisplayPosition.y &&
|
|
imageY1<=PreviousPSXDisplay.DisplayEnd.y)
|
|
{
|
|
if(!(
|
|
imageX0>=PSXDisplay.DisplayPosition.x &&
|
|
imageX0<PSXDisplay.DisplayEnd.x &&
|
|
imageY0>=PSXDisplay.DisplayPosition.y &&
|
|
imageY0<PSXDisplay.DisplayEnd.y
|
|
))
|
|
{
|
|
if(bRenderFrontBuffer)
|
|
{
|
|
updateFrontDisplay();
|
|
}
|
|
|
|
UploadScreen(FALSE);
|
|
}
|
|
else bFakeFrontBuffer=TRUE;
|
|
}
|
|
}
|
|
|
|
bNeedUploadTest=TRUE;
|
|
}
|
|
else
|
|
if(iOffscreenDrawing)
|
|
{
|
|
if (CheckAgainstFrontScreen(imageX1,imageY1,imageSX,imageSY))
|
|
{
|
|
if(!PSXDisplay.InterlacedTest &&
|
|
// !bFullVRam &&
|
|
((
|
|
imageX0>=PreviousPSXDisplay.DisplayPosition.x &&
|
|
imageX0<PreviousPSXDisplay.DisplayEnd.x &&
|
|
imageY0>=PreviousPSXDisplay.DisplayPosition.y &&
|
|
imageY0<PreviousPSXDisplay.DisplayEnd.y
|
|
) ||
|
|
(
|
|
imageX0>=PSXDisplay.DisplayPosition.x &&
|
|
imageX0<PSXDisplay.DisplayEnd.x &&
|
|
imageY0>=PSXDisplay.DisplayPosition.y &&
|
|
imageY0<PSXDisplay.DisplayEnd.y
|
|
)))
|
|
return;
|
|
|
|
bNeedUploadTest=TRUE;
|
|
|
|
if(!bNeedUploadAfter)
|
|
{
|
|
bNeedUploadAfter = TRUE;
|
|
xrUploadArea.x0=imageX0;
|
|
xrUploadArea.x1=imageX0+imageSX;
|
|
xrUploadArea.y0=imageY0;
|
|
xrUploadArea.y1=imageY0+imageSY;
|
|
}
|
|
else
|
|
{
|
|
xrUploadArea.x0=min(xrUploadArea.x0,imageX0);
|
|
xrUploadArea.x1=max(xrUploadArea.x1,imageX0+imageSX);
|
|
xrUploadArea.y0=min(xrUploadArea.y0,imageY0);
|
|
xrUploadArea.y1=max(xrUploadArea.y1,imageY0+imageSY);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
// cmd: draw free-size Tile
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
void primTileS(unsigned char * baseAddr)
|
|
{
|
|
uint32_t *gpuData = ((uint32_t *)baseAddr);
|
|
short *sgpuData = ((short *) baseAddr);
|
|
|
|
sprtX = sgpuData[2];
|
|
sprtY = sgpuData[3];
|
|
sprtW = sgpuData[4] & 0x3ff;
|
|
sprtH = sgpuData[5] & iGPUHeightMask;
|
|
|
|
// x and y of start
|
|
|
|
lx0 = sprtX;
|
|
ly0 = sprtY;
|
|
|
|
offsetST(baseAddr);
|
|
|
|
if((dwActFixes&1) && // FF7 special game gix (battle cursor)
|
|
sprtX==0 && sprtY==0 && sprtW==24 && sprtH==16)
|
|
return;
|
|
|
|
bDrawTextured = FALSE;
|
|
bDrawSmoothShaded = FALSE;
|
|
|
|
SetRenderState(gpuData[0]);
|
|
|
|
if(iOffscreenDrawing)
|
|
{
|
|
if(IsPrimCompleteInsideNextScreen(lx0,ly0,lx2,ly2) ||
|
|
(ly0==-6 && ly2==10)) // OH MY GOD... I DIDN'T WANT TO DO IT... BUT I'VE FOUND NO OTHER WAY... HACK FOR GRADIUS SHOOTER :(
|
|
{
|
|
lClearOnSwapColor = COLOR(gpuData[0]);
|
|
lClearOnSwap = 1;
|
|
}
|
|
|
|
offsetPSX4();
|
|
if(bDrawOffscreen4())
|
|
{
|
|
if(!(iTileCheat && sprtH==32 && gpuData[0]==0x60ffffff)) // special cheat for certain ZiNc games
|
|
{
|
|
InvalidateTextureAreaEx();
|
|
FillSoftwareAreaTrans(lx0,ly0,lx2,ly2,
|
|
BGR24to16(gpuData[0]));
|
|
}
|
|
}
|
|
}
|
|
|
|
SetRenderMode(gpuData[0], FALSE);
|
|
SetZMask4NT();
|
|
|
|
if(bIgnoreNextTile) {bIgnoreNextTile=FALSE;return;}
|
|
|
|
vertex[0].c.lcol=gpuData[0];
|
|
vertex[0].c.col[3]=ubGloColAlpha;
|
|
SETCOL(vertex[0]);
|
|
|
|
PRIMdrawQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]);
|
|
|
|
iDrawnSomething=1;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
// cmd: draw 1 dot Tile (point)
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
void primTile1(unsigned char * baseAddr)
|
|
{
|
|
uint32_t *gpuData = ((uint32_t *)baseAddr);
|
|
short *sgpuData = ((short *)baseAddr);
|
|
|
|
sprtX = sgpuData[2];
|
|
sprtY = sgpuData[3];
|
|
sprtW = 1;
|
|
sprtH = 1;
|
|
|
|
lx0 = sprtX;
|
|
ly0 = sprtY;
|
|
|
|
offsetST(baseAddr);
|
|
|
|
bDrawTextured = FALSE;
|
|
bDrawSmoothShaded = FALSE;
|
|
|
|
SetRenderState(gpuData[0]);
|
|
|
|
if(iOffscreenDrawing)
|
|
{
|
|
offsetPSX4();
|
|
|
|
if(bDrawOffscreen4())
|
|
{
|
|
InvalidateTextureAreaEx();
|
|
FillSoftwareAreaTrans(lx0,ly0,lx2,ly2,
|
|
BGR24to16(gpuData[0]));
|
|
}
|
|
}
|
|
|
|
SetRenderMode(gpuData[0], FALSE);
|
|
SetZMask4NT();
|
|
|
|
vertex[0].c.lcol=gpuData[0];vertex[0].c.col[3]=ubGloColAlpha;
|
|
SETCOL(vertex[0]);
|
|
|
|
PRIMdrawQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]);
|
|
|
|
iDrawnSomething=1;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
// cmd: draw 8 dot Tile (small rect)
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
void primTile8(unsigned char * baseAddr)
|
|
{
|
|
uint32_t *gpuData = ((uint32_t *)baseAddr);
|
|
short *sgpuData = ((short *) baseAddr);
|
|
|
|
sprtX = sgpuData[2];
|
|
sprtY = sgpuData[3];
|
|
sprtW = 8;
|
|
sprtH = 8;
|
|
|
|
lx0 = sprtX;
|
|
ly0 = sprtY;
|
|
|
|
offsetST(baseAddr);
|
|
|
|
bDrawTextured = FALSE;
|
|
bDrawSmoothShaded = FALSE;
|
|
SetRenderState(gpuData[0]);
|
|
|
|
if(iOffscreenDrawing)
|
|
{
|
|
offsetPSX4();
|
|
|
|
if(bDrawOffscreen4())
|
|
{
|
|
InvalidateTextureAreaEx();
|
|
FillSoftwareAreaTrans(lx0,ly0,lx2,ly2,
|
|
BGR24to16(gpuData[0]));
|
|
}
|
|
}
|
|
|
|
SetRenderMode(gpuData[0], FALSE);
|
|
SetZMask4NT();
|
|
|
|
vertex[0].c.lcol=gpuData[0];
|
|
vertex[0].c.col[3]=ubGloColAlpha;
|
|
SETCOL(vertex[0]);
|
|
|
|
PRIMdrawQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]);
|
|
|
|
iDrawnSomething=1;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
// cmd: draw 16 dot Tile (medium rect)
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
void primTile16(unsigned char * baseAddr)
|
|
{
|
|
uint32_t *gpuData = ((uint32_t *)baseAddr);
|
|
short *sgpuData = ((short *)baseAddr);
|
|
|
|
sprtX = sgpuData[2];
|
|
sprtY = sgpuData[3];
|
|
sprtW = 16;
|
|
sprtH = 16;
|
|
// x and y of start
|
|
lx0 = sprtX;
|
|
ly0 = sprtY;
|
|
|
|
offsetST(baseAddr);
|
|
|
|
bDrawTextured = FALSE;
|
|
bDrawSmoothShaded = FALSE;
|
|
SetRenderState(gpuData[0]);
|
|
|
|
if(iOffscreenDrawing)
|
|
{
|
|
offsetPSX4();
|
|
|
|
if(bDrawOffscreen4())
|
|
{
|
|
InvalidateTextureAreaEx();
|
|
FillSoftwareAreaTrans(lx0,ly0,lx2,ly2,
|
|
BGR24to16(gpuData[0]));
|
|
}
|
|
}
|
|
|
|
SetRenderMode(gpuData[0], FALSE);
|
|
SetZMask4NT();
|
|
|
|
vertex[0].c.lcol=gpuData[0];
|
|
vertex[0].c.col[3]=ubGloColAlpha;
|
|
SETCOL(vertex[0]);
|
|
|
|
PRIMdrawQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]);
|
|
|
|
iDrawnSomething=1;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
// helper: filter effect by multipass rendering
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
void DrawMultiBlur(void)
|
|
{
|
|
int lABR,lDST;
|
|
float fx,fy;
|
|
|
|
lABR=GlobalTextABR;
|
|
lDST=DrawSemiTrans;
|
|
|
|
fx=(float)PSXDisplay.DisplayMode.x/(float)(iResX);
|
|
fy=(float)PSXDisplay.DisplayMode.y/(float)(iResY);
|
|
|
|
|
|
for (unsigned int i = 0; i < 4; ++i)
|
|
{
|
|
vertex[i].PGXP_flag = 5;
|
|
vertex[i].w = 1.f;
|
|
}
|
|
|
|
vertex[0].x+=fx;vertex[1].x+=fx;
|
|
vertex[2].x+=fx;vertex[3].x+=fx;
|
|
|
|
GlobalTextABR=0;
|
|
DrawSemiTrans=1;
|
|
SetSemiTrans();
|
|
|
|
PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]);
|
|
|
|
vertex[0].y+=fy;vertex[1].y+=fy;
|
|
vertex[2].y+=fy;vertex[3].y+=fy;
|
|
PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]);
|
|
|
|
if(bDrawMultiPass) {obm1=obm2=GL_SRC_ALPHA;}
|
|
|
|
GlobalTextABR=lABR;
|
|
DrawSemiTrans=lDST;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
#define POFF 0.375f
|
|
|
|
void DrawMultiFilterSprite(void)
|
|
{
|
|
int lABR,lDST;
|
|
|
|
if(bUseMultiPass || DrawSemiTrans || ubOpaqueDraw)
|
|
{
|
|
PRIMdrawTexturedQuad(&vertex[0], &vertex[1], &vertex[2], &vertex[3]);
|
|
return;
|
|
}
|
|
|
|
lABR=GlobalTextABR;
|
|
lDST=DrawSemiTrans;
|
|
vertex[0].c.col[3]=ubGloAlpha/2; // -> 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(unsigned char * baseAddr)
|
|
{
|
|
uint32_t *gpuData = ((uint32_t *) baseAddr);
|
|
short *sgpuData = ((short *) baseAddr);
|
|
short s;
|
|
|
|
iSpriteTex=1;
|
|
|
|
sprtX = sgpuData[2];
|
|
sprtY = sgpuData[3];
|
|
sprtW = 8;
|
|
sprtH = 8;
|
|
|
|
lx0 = sprtX;
|
|
ly0 = sprtY;
|
|
|
|
offsetST(baseAddr);
|
|
|
|
// 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_NEAREST);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
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(unsigned char * baseAddr)
|
|
{
|
|
uint32_t *gpuData = ((uint32_t *) baseAddr);
|
|
short *sgpuData = ((short *) baseAddr);
|
|
short s;
|
|
|
|
iSpriteTex=1;
|
|
|
|
sprtX = sgpuData[2];
|
|
sprtY = sgpuData[3];
|
|
sprtW = 16;
|
|
sprtH = 16;
|
|
|
|
lx0 = sprtX;
|
|
ly0 = sprtY;
|
|
|
|
offsetST(baseAddr);
|
|
|
|
// 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_NEAREST);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
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(unsigned char * baseAddr,unsigned short type)
|
|
{
|
|
uint32_t *gpuData = ((uint32_t *)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(baseAddr);
|
|
|
|
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_NEAREST);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
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(unsigned char * baseAddr)
|
|
{
|
|
uint32_t *gpuData = ((uint32_t *) 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(baseAddr);
|
|
|
|
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_NEAREST);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
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(unsigned char *baseAddr)
|
|
{
|
|
uint32_t *gpuData = ((uint32_t *) 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(baseAddr)) 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(unsigned char * 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(unsigned char * baseAddr)
|
|
{
|
|
static unsigned char 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)
|
|
{
|
|
int labr=GlobalTextABR;
|
|
GlobalTextABR = 1;
|
|
primPolyG4(pFF9G4Cache);
|
|
GlobalTextABR = labr;
|
|
}
|
|
iFF9Fix = 0;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
void primPolyG4(unsigned char * baseAddr)
|
|
{
|
|
uint32_t *gpuData = (uint32_t *)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(baseAddr)) 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(uint32_t *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(unsigned char * baseAddr)
|
|
{
|
|
uint32_t *gpuData = ((uint32_t *) 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(baseAddr)) 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<ly2)
|
|
{
|
|
if (vertex[0].tow > 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<ly1)
|
|
{
|
|
if (vertex[0].tow > 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<ly1)
|
|
{
|
|
if (vertex[0].tow > vertex[1].tow)
|
|
VFlipped = 5;
|
|
}
|
|
else
|
|
{
|
|
if (vertex[0].tow < vertex[1].tow)
|
|
VFlipped = 6;
|
|
}
|
|
}
|
|
else return;
|
|
|
|
if(lx0==lx1)
|
|
{
|
|
if(lx0<lx2)
|
|
{
|
|
if (vertex[0].sow > vertex[2].sow)
|
|
UFlipped = 1;
|
|
}
|
|
else
|
|
{
|
|
if (vertex[0].sow < vertex[2].sow)
|
|
UFlipped = 2;
|
|
}
|
|
}
|
|
else
|
|
if(lx0==lx2)
|
|
{
|
|
if(lx0<lx1)
|
|
{
|
|
if (vertex[0].sow > vertex[1].sow)
|
|
UFlipped = 3;
|
|
}
|
|
else
|
|
{
|
|
if (vertex[0].sow < vertex[1].sow)
|
|
UFlipped = 4;
|
|
}
|
|
}
|
|
else
|
|
if(lx0==lx3)
|
|
{
|
|
if(lx0<lx1)
|
|
{
|
|
if (vertex[0].sow > 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(unsigned char * baseAddr)
|
|
{
|
|
uint32_t *gpuData = ((uint32_t *)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(baseAddr)) 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_NEAREST);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
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(unsigned char *baseAddr)
|
|
{
|
|
uint32_t *gpuData = ((uint32_t *) 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(baseAddr)) 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(unsigned char *baseAddr)
|
|
{
|
|
uint32_t *gpuData = ((uint32_t *)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(baseAddr)) 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(unsigned char *baseAddr)
|
|
{
|
|
uint32_t *gpuData = ((uint32_t *)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(baseAddr)) 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(unsigned char *baseAddr)
|
|
{
|
|
uint32_t *gpuData = ((uint32_t *) 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(baseAddr)) 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(unsigned char *baseAddr)
|
|
{
|
|
uint32_t *gpuData = ((uint32_t *) 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(unsigned char *baseAddr)
|
|
{
|
|
uint32_t *gpuData = ((uint32_t *) 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(baseAddr)) 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(unsigned char *baseAddr)
|
|
{
|
|
uint32_t *gpuData = ((uint32_t *) 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(baseAddr)) 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(unsigned char *baseAddr)
|
|
{
|
|
uint32_t *gpuData = ((uint32_t *) 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(unsigned char *baseAddr)
|
|
{
|
|
uint32_t *gpuData = ((uint32_t *) 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(baseAddr))
|
|
{
|
|
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(unsigned char *baseAddr)
|
|
{
|
|
uint32_t *gpuData = ((uint32_t *) baseAddr);
|
|
short *sgpuData = ((short *) baseAddr);
|
|
|
|
lx0 = sgpuData[2];
|
|
ly0 = sgpuData[3];
|
|
lx1 = sgpuData[4];
|
|
ly1 = sgpuData[5];
|
|
|
|
if(offsetline(baseAddr)) 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(unsigned char *bA)
|
|
{
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
// cmd func ptr table
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
void (*primTableJ[256])(unsigned char *) =
|
|
{
|
|
// 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])(unsigned char *) =
|
|
{
|
|
// 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
|
|
};
|