2012-11-01 15:19:01 +00:00
// Copyright (c) 2012- PPSSPP Project.
// 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
2012-11-04 22:58:25 +00:00
// the Free Software Foundation, version 2.0 or later versions.
2012-11-01 15:19:01 +00:00
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
2012-11-05 13:09:49 +00:00
# if defined(ANDROID) || defined(BLACKBERRY)
2012-11-01 15:19:01 +00:00
# include <GLES2/gl2.h>
# include <GLES2/gl2ext.h>
# else
# include <GL/glew.h>
# if defined(__APPLE__)
# include <OpenGL/gl.h>
# else
# include <GL/gl.h>
# endif
# endif
# include "../../Core/MemMap.h"
# include "../../Core/Host.h"
2012-11-19 20:23:29 +00:00
# include "../../Core/Config.h"
2012-11-19 22:29:14 +00:00
# include "../../Core/System.h"
2012-11-01 15:19:01 +00:00
# include "../GPUState.h"
# include "../ge_constants.h"
# include "ShaderManager.h"
# include "DisplayListInterpreter.h"
2012-11-19 20:23:29 +00:00
# include "Framebuffer.h"
2012-11-01 15:19:01 +00:00
# include "TransformPipeline.h"
# include "../../Core/HLE/sceKernelThread.h"
# include "../../Core/HLE/sceKernelInterrupt.h"
inline void glEnDis ( GLuint cmd , int value )
{
( value ? glEnable : glDisable ) ( cmd ) ;
}
ShaderManager shaderManager ;
extern u32 curTextureWidth ;
extern u32 curTextureHeight ;
2012-11-19 22:29:14 +00:00
GLES_GPU : : ~ GLES_GPU ( )
{
for ( auto iter = vfbs_ . begin ( ) ; iter ! = vfbs_ . end ( ) ; + + iter )
{
fbo_destroy ( ( * iter ) - > fbo ) ;
delete ( * iter ) ;
}
vfbs_ . clear ( ) ;
}
2012-11-19 20:23:29 +00:00
void GLES_GPU : : InitClear ( int renderWidth , int renderHeight )
2012-11-01 15:19:01 +00:00
{
2012-11-19 20:23:29 +00:00
renderWidth_ = renderWidth ;
renderHeight_ = renderHeight ;
2012-11-19 22:29:14 +00:00
widthFactor_ = ( float ) renderWidth / 480.0f ;
heightFactor_ = ( float ) renderHeight / 272.0f ;
2012-11-01 15:19:01 +00:00
2012-11-19 23:31:19 +00:00
//glClearColor(0,0,0,1);
2012-11-19 20:23:29 +00:00
// glClearColor(1,0,1,1);
2012-11-19 23:31:19 +00:00
//glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
2012-11-19 22:29:14 +00:00
glViewport ( 0 , 0 , renderWidth_ , renderHeight_ ) ;
2012-11-19 20:23:29 +00:00
}
2012-11-01 15:19:01 +00:00
2012-11-19 20:23:29 +00:00
void GLES_GPU : : BeginFrame ( )
{
if ( g_Config . bDisplayFramebuffer & & displayFramebufPtr_ )
{
INFO_LOG ( HLE , " Drawing the framebuffer " ) ;
u8 * pspframebuf = Memory : : GetPointer ( ( 0x44000000 ) | ( displayFramebufPtr_ & 0x1FFFFF ) ) ; // TODO - check
DisplayDrawer_DrawFramebuffer ( pspframebuf , displayFormat_ , displayStride_ ) ;
}
}
2012-11-01 15:19:01 +00:00
2012-11-19 20:23:29 +00:00
void GLES_GPU : : SetDisplayFramebuffer ( u32 framebuf , u32 stride , int format )
{
2012-11-19 22:53:38 +00:00
if ( framebuf & 0x04000000 ) {
displayFramebufPtr_ = framebuf ;
displayStride_ = stride ;
displayFormat_ = format ;
} else {
DEBUG_LOG ( HLE , " Bogus framebufffer address: %08x " , framebuf ) ;
}
2012-11-19 20:23:29 +00:00
}
2012-11-01 15:19:01 +00:00
2012-11-19 20:23:29 +00:00
void GLES_GPU : : CopyDisplayToOutput ( )
2012-11-18 12:14:22 +00:00
{
2012-11-19 22:29:14 +00:00
VirtualFramebuffer * vfb = GetDisplayFBO ( ) ;
fbo_unbind ( ) ;
glViewport ( 0 , 0 , PSP_CoreParameter ( ) . outputWidth , PSP_CoreParameter ( ) . outputHeight ) ;
currentRenderVfb_ = 0 ;
if ( ! vfb ) {
2012-11-19 23:31:19 +00:00
DEBUG_LOG ( HLE , " Found no FBO! displayFBPtr = %08x " , displayFramebufPtr_ ) ;
2012-11-19 22:29:14 +00:00
// No framebuffer to display! Clear to black.
glClearColor ( 0 , 0 , 0 , 1 ) ;
glClear ( GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT ) ;
return ;
}
2012-11-19 23:31:19 +00:00
DEBUG_LOG ( HLE , " Displaying FBO %08x " , vfb - > fb_address ) ;
2012-11-19 22:29:14 +00:00
glDisable ( GL_CULL_FACE ) ;
glDisable ( GL_DEPTH_TEST ) ;
fbo_bind_color_as_texture ( vfb - > fbo , 0 ) ;
// These are in the output pixel coordinates
DrawActiveTexture ( 480 , 272 , true ) ;
shaderManager . DirtyShader ( ) ;
shaderManager . DirtyUniform ( DIRTY_ALL ) ;
2012-11-19 23:31:19 +00:00
gstate_c . textureChanged = true ;
2012-11-19 22:29:14 +00:00
// Restore some state
ExecuteOp ( gstate . cmdmem [ GE_CMD_CULLFACEENABLE ] , 0xFFFFFFFF ) ;
ExecuteOp ( gstate . cmdmem [ GE_CMD_ZTESTENABLE ] , 0xFFFFFFFF ) ;
}
GLES_GPU : : VirtualFramebuffer * GLES_GPU : : GetDisplayFBO ( )
{
for ( auto iter = vfbs_ . begin ( ) ; iter ! = vfbs_ . end ( ) ; + + iter )
{
if ( ( ( * iter ) - > fb_address & 0x3FFFFFF ) = = ( displayFramebufPtr_ & 0x3FFFFFF ) ) {
// Could check w to but whatever
return * iter ;
}
}
2012-11-19 22:53:38 +00:00
2012-11-19 22:29:14 +00:00
return 0 ;
2012-11-18 12:14:22 +00:00
}
2012-11-19 22:29:14 +00:00
void GLES_GPU : : SetRenderFrameBuffer ( )
{
// Get parameters
u32 fb_address = ( gstate . fbptr & 0xFFE000 ) | ( ( gstate . fbwidth & 0xFF0000 ) < < 8 ) ;
int fb_stride = gstate . fbwidth & 0x3C0 ;
u32 z_address = ( gstate . zbptr & 0xFFE000 ) | ( ( gstate . zbwidth & 0xFF0000 ) < < 8 ) ;
int z_stride = gstate . zbwidth & 0x3C0 ;
// Yeah this is not completely right. but it'll do for now.
int drawing_width = ( ( gstate . region2 ) & 0x3FF ) + 1 ;
int drawing_height = ( ( gstate . region2 > > 10 ) & 0x3FF ) + 1 ;
int fmt = gstate . framebufpixformat & 3 ;
// Find a matching framebuffer
VirtualFramebuffer * vfb = 0 ;
for ( auto iter = vfbs_ . begin ( ) ; iter ! = vfbs_ . end ( ) ; + + iter )
{
VirtualFramebuffer * v = * iter ;
if ( v - > fb_address = = fb_address ) {
// Let's not be so picky for now. Let's say this is the one.
vfb = v ;
// Update fb stride in case it changed
vfb - > fb_stride = fb_stride ;
break ;
}
}
// None found? Create one.
if ( ! vfb ) {
vfb = new VirtualFramebuffer ;
vfb - > fb_address = fb_address ;
vfb - > fb_stride = fb_stride ;
vfb - > z_address = z_address ;
vfb - > z_stride = z_stride ;
vfb - > width = drawing_width ;
vfb - > height = drawing_height ;
2012-11-19 23:31:19 +00:00
vfb - > format = fmt ;
2012-11-19 22:29:14 +00:00
vfb - > fbo = fbo_create ( vfb - > width * widthFactor_ , vfb - > height * heightFactor_ , 1 , true ) ;
vfbs_ . push_back ( vfb ) ;
fbo_bind_as_render_target ( vfb - > fbo ) ;
glViewport ( 0 , 0 , renderWidth_ , renderHeight_ ) ;
currentRenderVfb_ = vfb ;
glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT ) ;
2012-11-19 23:31:19 +00:00
DEBUG_LOG ( HLE , " Creating FBO for %08x " , vfb - > fb_address ) ;
2012-11-19 22:29:14 +00:00
return ;
}
if ( vfb ! = currentRenderVfb_ )
{
// Use it as a render target.
2012-11-19 23:31:19 +00:00
DEBUG_LOG ( HLE , " Switching to FBO for %08x " , vfb - > fb_address ) ;
2012-11-19 22:29:14 +00:00
fbo_bind_as_render_target ( vfb - > fbo ) ;
glViewport ( 0 , 0 , renderWidth_ , renderHeight_ ) ;
currentRenderVfb_ = vfb ;
}
}
2012-11-19 20:23:29 +00:00
2012-11-19 23:31:19 +00:00
// Render queue
2012-11-06 16:05:27 +00:00
bool GLES_GPU : : ProcessDLQueue ( )
2012-11-01 15:19:01 +00:00
{
std : : vector < DisplayList > : : iterator iter = dlQueue . begin ( ) ;
while ( ! ( iter = = dlQueue . end ( ) ) )
{
DisplayList & l = * iter ;
dcontext . pc = l . listpc ;
dcontext . stallAddr = l . stall ;
// DEBUG_LOG(G3D,"Okay, starting DL execution at %08 - stall = %08x", context.pc, stallAddr);
2012-11-06 16:05:27 +00:00
if ( ! InterpretList ( ) )
2012-11-01 15:19:01 +00:00
{
l . listpc = dcontext . pc ;
l . stall = dcontext . stallAddr ;
return false ;
}
else
{
//At the end, we can remove it from the queue and continue
dlQueue . erase ( iter ) ;
//this invalidated the iterator, let's fix it
iter = dlQueue . begin ( ) ;
}
}
return true ; //no more lists!
}
2012-11-06 16:05:27 +00:00
u32 GLES_GPU : : EnqueueList ( u32 listpc , u32 stall )
2012-11-01 15:19:01 +00:00
{
DisplayList dl ;
dl . id = dlIdGenerator + + ;
2012-11-18 16:51:14 +00:00
dl . listpc = listpc & 0xFFFFFFF ;
dl . stall = stall & 0xFFFFFFF ;
2012-11-01 15:19:01 +00:00
dlQueue . push_back ( dl ) ;
if ( ! ProcessDLQueue ( ) )
return dl . id ;
else
return 0 ;
}
2012-11-06 16:05:27 +00:00
void GLES_GPU : : UpdateStall ( int listid , u32 newstall )
2012-11-01 15:19:01 +00:00
{
// this needs improvement....
for ( std : : vector < DisplayList > : : iterator iter = dlQueue . begin ( ) ; iter ! = dlQueue . end ( ) ; iter + + )
{
DisplayList & l = * iter ;
if ( l . id = = listid )
{
l . stall = newstall & 0xFFFFFFF ;
}
}
ProcessDLQueue ( ) ;
}
2012-11-06 17:14:09 +00:00
void GLES_GPU : : DrawSync ( int mode )
{
}
2012-11-01 15:19:01 +00:00
// Just to get something on the screen, we'll just not subdivide correctly.
void drawBezier ( int ucount , int vcount )
{
u16 indices [ 3 * 3 * 6 ] ;
float customUV [ 32 ] ;
int c = 0 ;
for ( int y = 0 ; y < 3 ; y + + ) {
for ( int x = 0 ; x < 3 ; x + + ) {
indices [ c + + ] = y * 4 + x ;
indices [ c + + ] = y * 4 + x + 1 ;
indices [ c + + ] = ( y + 1 ) * 4 + x + 1 ;
indices [ c + + ] = ( y + 1 ) * 4 + x + 1 ;
indices [ c + + ] = ( y + 1 ) * 4 + x ;
indices [ c + + ] = y * 4 + x ;
}
}
for ( int y = 0 ; y < 4 ; y + + ) {
for ( int x = 0 ; x < 4 ; x + + ) {
customUV [ ( y * 4 + x ) * 2 + 0 ] = ( float ) x / 3.0f ;
customUV [ ( y * 4 + x ) * 2 + 1 ] = ( float ) y / 3.0f ;
}
}
LinkedShader * linkedShader = shaderManager . ApplyShader ( ) ;
2012-11-18 12:04:49 +00:00
TransformAndDrawPrim ( Memory : : GetPointer ( gstate_c . vertexAddr ) , & indices [ 0 ] , GE_PRIM_TRIANGLES , 3 * 3 * 6 , linkedShader , customUV , GE_VTYPE_IDX_16BIT ) ;
2012-11-01 15:19:01 +00:00
}
void EnterClearMode ( u32 data )
{
bool colMask = ( data > > 8 ) & 1 ;
bool alphaMask = ( data > > 9 ) & 1 ;
bool updateZ = ( data > > 10 ) & 1 ;
glColorMask ( colMask , colMask , colMask , alphaMask ) ;
glDepthMask ( updateZ ) ; // Update Z or not
// Note that depth test must be enabled for depth writes to go through! So we use GL_ALWAYS
2012-11-18 01:48:15 +00:00
glDisable ( GL_BLEND ) ;
2012-11-01 15:19:01 +00:00
glEnable ( GL_DEPTH_TEST ) ;
glDepthFunc ( GL_ALWAYS ) ;
glDisable ( GL_CULL_FACE ) ; // ??
}
void LeaveClearMode ( )
{
// We have to reset the following state as per the state of the command registers:
// Back face culling
// Texture map enable (meh)
// Fogging
// Antialiasing
// Alpha test
glDepthMask ( 1 ) ;
glColorMask ( 1 , 1 , 1 , 1 ) ;
glEnDis ( GL_DEPTH_TEST , gstate . zTestEnable & 1 ) ;
glDepthFunc ( GL_LEQUAL ) ; // TODO
2012-11-18 01:48:15 +00:00
glEnDis ( GL_BLEND , gstate . alphaBlendEnable & 1 ) ;
2012-11-01 15:19:01 +00:00
// dirtyshader?
}
void SetBlendModePSP ( u32 data )
{
// This can't be done exactly as there are several PSP blend modes that are impossible to do on OpenGL ES 2.0, and some even on regular OpenGL for desktop.
// HOWEVER - we should be able to approximate the 2x modes in the shader, although they will clip wrongly.
const GLint aLookup [ ] = {
GL_DST_COLOR ,
GL_ONE_MINUS_DST_COLOR ,
GL_SRC_ALPHA ,
GL_ONE_MINUS_SRC_ALPHA ,
GL_DST_ALPHA ,
GL_ONE_MINUS_DST_ALPHA ,
GL_SRC_ALPHA , // should be 2x
GL_ONE_MINUS_SRC_ALPHA , // should be 2x
GL_DST_ALPHA , // should be 2x
GL_ONE_MINUS_DST_ALPHA , // should be 2x - and COLOR?
GL_SRC_ALPHA , // should be FIXA
} ;
const GLint bLookup [ ] = {
GL_SRC_COLOR ,
GL_ONE_MINUS_SRC_COLOR ,
GL_SRC_ALPHA ,
GL_ONE_MINUS_SRC_ALPHA ,
GL_DST_ALPHA ,
GL_ONE_MINUS_DST_ALPHA ,
GL_SRC_ALPHA , // should be 2x
GL_ONE_MINUS_SRC_ALPHA , // should be 2x
GL_DST_ALPHA , // should be 2x
GL_ONE_MINUS_DST_ALPHA , // should be 2x
GL_SRC_ALPHA , // should be FIXB
} ;
const GLint eqLookup [ ] = {
GL_FUNC_ADD ,
GL_FUNC_SUBTRACT ,
GL_FUNC_REVERSE_SUBTRACT ,
2012-11-05 13:09:49 +00:00
# if defined(ANDROID) || defined(BLACKBERRY)
2012-11-01 15:19:01 +00:00
GL_FUNC_ADD ,
GL_FUNC_ADD ,
# else
GL_MIN ,
GL_MAX ,
# endif
GL_FUNC_ADD , // should be abs(diff)
} ;
int a = data & 0xF ;
int b = ( data > > 4 ) & 0xF ;
int eq = ( data > > 8 ) & 0x7 ;
glBlendFunc ( aLookup [ a ] , bLookup [ b ] ) ;
glBlendEquation ( eqLookup [ eq ] ) ;
}
2012-11-06 16:05:27 +00:00
void GLES_GPU : : ExecuteOp ( u32 op , u32 diff )
2012-11-01 15:19:01 +00:00
{
u32 cmd = op > > 24 ;
u32 data = op & 0xFFFFFF ;
// Handle control and drawing commands here directly. The others we delegate.
switch ( cmd )
{
case GE_CMD_BASE :
2012-11-18 12:04:49 +00:00
DEBUG_LOG ( G3D , " DL BASE: %06x " , data & 0xFFFFFF ) ;
2012-11-01 15:19:01 +00:00
break ;
case GE_CMD_VADDR : /// <<8????
2012-11-18 12:04:49 +00:00
gstate_c . vertexAddr = ( ( gstate . base & 0x00FF0000 ) < < 8 ) | data ;
DEBUG_LOG ( G3D , " DL VADDR: %06x " , gstate_c . vertexAddr ) ;
2012-11-01 15:19:01 +00:00
break ;
case GE_CMD_IADDR :
2012-11-18 12:04:49 +00:00
gstate_c . indexAddr = ( ( gstate . base & 0x00FF0000 ) < < 8 ) | data ;
DEBUG_LOG ( G3D , " DL IADDR: %06x " , gstate_c . indexAddr ) ;
2012-11-01 15:19:01 +00:00
break ;
case GE_CMD_PRIM :
{
2012-11-19 22:29:14 +00:00
SetRenderFrameBuffer ( ) ;
2012-11-01 15:19:01 +00:00
u32 count = data & 0xFFFF ;
u32 type = data > > 16 ;
static const char * types [ 7 ] = {
" POINTS=0, " ,
" LINES=1, " ,
" LINE_STRIP=2, " ,
" TRIANGLES=3, " ,
" TRIANGLE_STRIP=4, " ,
" TRIANGLE_FAN=5, " ,
" RECTANGLES=6, " ,
} ;
2012-11-18 12:04:49 +00:00
DEBUG_LOG ( G3D , " DL DrawPrim type: %s count: %i vaddr= %08x, iaddr= %08x " , type < 7 ? types [ type ] : " INVALID " , count , gstate_c . vertexAddr , gstate_c . indexAddr ) ;
2012-11-01 15:19:01 +00:00
LinkedShader * linkedShader = shaderManager . ApplyShader ( ) ;
// TODO: Split this so that we can collect sequences of primitives, can greatly speed things up
// on platforms where draw calls are expensive like mobile and D3D
2012-11-18 12:04:49 +00:00
void * verts = Memory : : GetPointer ( gstate_c . vertexAddr ) ;
2012-11-01 15:19:01 +00:00
void * inds = 0 ;
if ( ( gstate . vertType & GE_VTYPE_IDX_MASK ) ! = GE_VTYPE_IDX_NONE )
2012-11-18 12:04:49 +00:00
inds = Memory : : GetPointer ( gstate_c . indexAddr ) ;
2012-11-01 15:19:01 +00:00
TransformAndDrawPrim ( verts , inds , type , count , linkedShader ) ;
}
break ;
// The arrow and other rotary items in Puzbob are bezier patches, strangely enough.
case GE_CMD_BEZIER :
{
2012-11-02 11:33:16 +00:00
int bz_ucount = data & 0xFF ;
int bz_vcount = ( data > > 8 ) & 0xFF ;
drawBezier ( bz_ucount , bz_vcount ) ;
DEBUG_LOG ( G3D , " DL DRAW BEZIER: %i x %i " , bz_ucount , bz_vcount ) ;
2012-11-01 15:19:01 +00:00
}
break ;
case GE_CMD_SPLINE :
{
2012-11-02 11:33:16 +00:00
int sp_ucount = data & 0xFF ;
int sp_vcount = ( data > > 8 ) & 0xFF ;
int sp_utype = ( data > > 16 ) & 0x3 ;
int sp_vtype = ( data > > 18 ) & 0x3 ;
2012-11-01 15:19:01 +00:00
//drawSpline(sp_ucount, sp_vcount, sp_utype, sp_vtype);
2012-11-02 11:33:16 +00:00
DEBUG_LOG ( G3D , " DL DRAW SPLINE: %i x %i, %i x %i " , sp_ucount , sp_vcount , sp_utype , sp_vtype ) ;
2012-11-01 15:19:01 +00:00
}
break ;
case GE_CMD_JUMP :
{
2012-11-09 16:51:45 +00:00
u32 target = ( ( ( gstate . base & 0x00FF0000 ) < < 8 ) | ( op & 0xFFFFFC ) ) & 0x0FFFFFFF ;
2012-11-01 15:19:01 +00:00
DEBUG_LOG ( G3D , " DL CMD JUMP - %08x to %08x " , dcontext . pc , target ) ;
dcontext . pc = target - 4 ; // pc will be increased after we return, counteract that
}
break ;
case GE_CMD_CALL :
{
u32 retval = dcontext . pc + 4 ;
stack [ stackptr + + ] = retval ;
2012-11-09 16:51:45 +00:00
u32 target = ( ( ( gstate . base & 0x00FF0000 ) < < 8 ) | ( op & 0xFFFFFC ) ) & 0xFFFFFFF ;
2012-11-01 15:19:01 +00:00
DEBUG_LOG ( G3D , " DL CMD CALL - %08x to %08x, ret=%08x " , dcontext . pc , target , retval ) ;
dcontext . pc = target - 4 ; // pc will be increased after we return, counteract that
}
break ;
case GE_CMD_RET :
//TODO : debug!
{
u32 target = stack [ - - stackptr ] & 0xFFFFFFF ;
DEBUG_LOG ( G3D , " DL CMD RET - from %08x to %08x " , dcontext . pc , target ) ;
dcontext . pc = target - 4 ;
}
break ;
case GE_CMD_SIGNAL :
{
2012-11-06 17:14:09 +00:00
ERROR_LOG ( G3D , " DL GE_CMD_SIGNAL %08x " , data & 0xFFFFFF ) ;
int behaviour = ( data > > 16 ) & 0xFF ;
int signal = data & 0xFFFF ;
2012-11-01 15:19:01 +00:00
2012-11-18 12:04:49 +00:00
if ( interruptsEnabled_ )
__TriggerInterruptWithArg ( PSP_GE_INTR , PSP_GE_SUBINTR_SIGNAL , signal ) ;
2012-11-06 17:14:09 +00:00
}
2012-11-01 15:19:01 +00:00
break ;
case GE_CMD_BJUMP :
// bounding box jump. Let's just not jump, for now.
2012-11-09 16:51:45 +00:00
ERROR_LOG ( G3D , " DL BBOX JUMP - unimplemented " ) ;
2012-11-01 15:19:01 +00:00
break ;
case GE_CMD_BOUNDINGBOX :
// bounding box test. Let's do nothing.
2012-11-09 16:51:45 +00:00
ERROR_LOG ( G3D , " DL BBOX TEST - unimplemented " ) ;
2012-11-01 15:19:01 +00:00
break ;
case GE_CMD_ORIGIN :
gstate . offsetAddr = dcontext . pc & 0xFFFFFF ;
break ;
case GE_CMD_VERTEXTYPE :
DEBUG_LOG ( G3D , " DL SetVertexType: %06x " , data ) ;
if ( diff & GE_VTYPE_THROUGH ) {
// Throughmode changed, let's make the proj matrix dirty.
shaderManager . DirtyUniform ( DIRTY_PROJMATRIX ) ;
}
if ( data & GE_VTYPE_THROUGH ) {
glDisable ( GL_CULL_FACE ) ;
}
2012-11-16 14:35:41 +00:00
else {
// this might get spammy
glEnDis ( GL_CULL_FACE , gstate . cullfaceEnable & 1 ) ;
}
2012-11-01 15:19:01 +00:00
// This sets through-mode or not, as well.
break ;
case GE_CMD_OFFSETADDR :
// offsetAddr = data<<8;
break ;
case GE_CMD_FINISH :
DEBUG_LOG ( G3D , " DL CMD FINISH " ) ;
2012-11-18 12:04:49 +00:00
if ( interruptsEnabled_ )
__TriggerInterruptWithArg ( PSP_GE_INTR , PSP_GE_SUBINTR_FINISH , 0 ) ;
2012-11-01 15:19:01 +00:00
break ;
case GE_CMD_END :
DEBUG_LOG ( G3D , " DL CMD END " ) ;
{
switch ( prev > > 24 )
{
case GE_CMD_FINISH :
finished = true ;
break ;
default :
DEBUG_LOG ( G3D , " Ah, not finished: %06x " , prev & 0xFFFFFF ) ;
break ;
}
}
// This should generate a Reading Ended interrupt
2012-11-18 12:04:49 +00:00
// if (interruptsEnabled_)
// __TriggerInterrupt(PSP_GE_INTR);
2012-11-01 15:19:01 +00:00
break ;
case GE_CMD_REGION1 :
{
int x1 = data & 0x3ff ;
int y1 = data > > 10 ;
//topleft
DEBUG_LOG ( G3D , " DL Region TL: %d %d " , x1 , y1 ) ;
}
break ;
case GE_CMD_REGION2 :
{
int x2 = data & 0x3ff ;
int y2 = data > > 10 ;
DEBUG_LOG ( G3D , " DL Region BR: %d %d " , x2 , y2 ) ;
}
break ;
case GE_CMD_CLIPENABLE :
2012-11-02 11:33:16 +00:00
DEBUG_LOG ( G3D , " DL Clip Enable: %i (ignoring) " , data ) ;
2012-11-01 15:19:01 +00:00
//we always clip, this is opengl
break ;
case GE_CMD_CULLFACEENABLE :
2012-11-02 11:33:16 +00:00
DEBUG_LOG ( G3D , " DL CullFace Enable: %i (ignoring) " , data ) ;
2012-11-01 15:19:01 +00:00
glEnDis ( GL_CULL_FACE , data & 1 ) ;
break ;
case GE_CMD_TEXTUREMAPENABLE :
2012-11-02 11:33:16 +00:00
DEBUG_LOG ( G3D , " DL Texture map enable: %i " , data ) ;
2012-11-01 15:19:01 +00:00
glEnDis ( GL_TEXTURE_2D , data & 1 ) ;
break ;
case GE_CMD_LIGHTINGENABLE :
2012-11-02 11:33:16 +00:00
DEBUG_LOG ( G3D , " DL Lighting enable: %i " , data ) ;
2012-11-01 15:19:01 +00:00
data + = 1 ;
//We don't use OpenGL lighting
break ;
case GE_CMD_FOGENABLE :
2012-11-02 11:33:16 +00:00
DEBUG_LOG ( G3D , " DL Fog Enable: %i " , gstate . fogEnable ) ;
2012-11-01 15:19:01 +00:00
break ;
case GE_CMD_DITHERENABLE :
2012-11-02 11:33:16 +00:00
DEBUG_LOG ( G3D , " DL Dither Enable: %i " , gstate . ditherEnable ) ;
2012-11-01 15:19:01 +00:00
break ;
case GE_CMD_OFFSETX :
2012-11-02 11:33:16 +00:00
DEBUG_LOG ( G3D , " DL Offset X: %i " , gstate . offsetx ) ;
2012-11-01 15:19:01 +00:00
break ;
case GE_CMD_OFFSETY :
2012-11-02 11:33:16 +00:00
DEBUG_LOG ( G3D , " DL Offset Y: %i " , gstate . offsety ) ;
2012-11-01 15:19:01 +00:00
break ;
case GE_CMD_TEXSCALEU :
2012-11-18 12:04:49 +00:00
gstate_c . uScale = getFloat24 ( data ) ;
DEBUG_LOG ( G3D , " DL Texture U Scale: %f " , gstate_c . uScale ) ;
2012-11-01 15:19:01 +00:00
break ;
case GE_CMD_TEXSCALEV :
2012-11-18 12:04:49 +00:00
gstate_c . vScale = getFloat24 ( data ) ;
DEBUG_LOG ( G3D , " DL Texture V Scale: %f " , gstate_c . vScale ) ;
2012-11-01 15:19:01 +00:00
break ;
case GE_CMD_TEXOFFSETU :
2012-11-18 12:04:49 +00:00
gstate_c . uOff = getFloat24 ( data ) ;
DEBUG_LOG ( G3D , " DL Texture U Offset: %f " , gstate_c . uOff ) ;
2012-11-01 15:19:01 +00:00
break ;
case GE_CMD_TEXOFFSETV :
2012-11-18 12:04:49 +00:00
gstate_c . vOff = getFloat24 ( data ) ;
DEBUG_LOG ( G3D , " DL Texture V Offset: %f " , gstate_c . vOff ) ;
2012-11-01 15:19:01 +00:00
break ;
case GE_CMD_SCISSOR1 :
{
int x1 = data & 0x3ff ;
int y1 = data > > 10 ;
2012-11-02 11:33:16 +00:00
DEBUG_LOG ( G3D , " DL Scissor TL: %i, %i " , x1 , y1 ) ;
2012-11-01 15:19:01 +00:00
}
break ;
case GE_CMD_SCISSOR2 :
{
int x2 = data & 0x3ff ;
int y2 = data > > 10 ;
2012-11-02 11:33:16 +00:00
DEBUG_LOG ( G3D , " DL Scissor BR: %i, %i " , x2 , y2 ) ;
2012-11-01 15:19:01 +00:00
}
break ;
case GE_CMD_MINZ :
2012-11-02 11:33:16 +00:00
DEBUG_LOG ( G3D , " DL MinZ: %i " , data ) ;
2012-11-01 15:19:01 +00:00
break ;
case GE_CMD_MAXZ :
2012-11-02 11:33:16 +00:00
DEBUG_LOG ( G3D , " DL MaxZ: %i " , data ) ;
2012-11-01 15:19:01 +00:00
break ;
case GE_CMD_FRAMEBUFPTR :
{
u32 ptr = op & 0xFFE000 ;
DEBUG_LOG ( G3D , " DL FramebufPtr: %08x " , ptr ) ;
}
break ;
case GE_CMD_FRAMEBUFWIDTH :
{
u32 w = data & 0xFFFFFF ;
DEBUG_LOG ( G3D , " DL FramebufWidth: %i " , w ) ;
}
break ;
case GE_CMD_FRAMEBUFPIXFORMAT :
break ;
case GE_CMD_TEXADDR0 :
2012-11-18 12:04:49 +00:00
gstate_c . textureChanged = true ;
2012-11-01 15:19:01 +00:00
case GE_CMD_TEXADDR1 :
case GE_CMD_TEXADDR2 :
case GE_CMD_TEXADDR3 :
case GE_CMD_TEXADDR4 :
case GE_CMD_TEXADDR5 :
case GE_CMD_TEXADDR6 :
case GE_CMD_TEXADDR7 :
DEBUG_LOG ( G3D , " DL Texture address %i: %06x " , cmd - GE_CMD_TEXADDR0 , data ) ;
break ;
case GE_CMD_TEXBUFWIDTH0 :
2012-11-18 12:04:49 +00:00
gstate_c . textureChanged = true ;
2012-11-01 15:19:01 +00:00
case GE_CMD_TEXBUFWIDTH1 :
case GE_CMD_TEXBUFWIDTH2 :
case GE_CMD_TEXBUFWIDTH3 :
case GE_CMD_TEXBUFWIDTH4 :
case GE_CMD_TEXBUFWIDTH5 :
case GE_CMD_TEXBUFWIDTH6 :
case GE_CMD_TEXBUFWIDTH7 :
DEBUG_LOG ( G3D , " DL Texture BUFWIDTHess %i: %06x " , cmd - GE_CMD_TEXBUFWIDTH0 , data ) ;
break ;
case GE_CMD_CLUTADDR :
//DEBUG_LOG(G3D,"CLUT base addr: %06x", data);
break ;
case GE_CMD_CLUTADDRUPPER :
2012-11-02 11:33:16 +00:00
DEBUG_LOG ( G3D , " DL CLUT addr: %08x " , ( ( gstate . clutaddrupper & 0xFF0000 ) < < 8 ) | ( gstate . clutaddr & 0xFFFFFF ) ) ;
2012-11-01 15:19:01 +00:00
break ;
case GE_CMD_LOADCLUT :
2012-11-18 12:04:49 +00:00
// This could be used to "dirty" textures with clut.
2012-11-01 15:19:01 +00:00
{
2012-11-18 12:04:49 +00:00
u32 clutAddr = ( ( gstate . clutaddrupper & 0xFF0000 ) < < 8 ) | ( gstate . clutaddr & 0xFFFFFF ) ;
if ( clutAddr )
2012-11-01 15:19:01 +00:00
{
2012-11-18 12:04:49 +00:00
DEBUG_LOG ( G3D , " DL Clut load: %08x " , clutAddr ) ;
2012-11-01 15:19:01 +00:00
}
else
{
2012-11-02 11:33:16 +00:00
DEBUG_LOG ( G3D , " DL Empty Clut load " ) ;
2012-11-01 15:19:01 +00:00
}
// Should hash and invalidate all paletted textures on use
}
break ;
2012-11-19 22:29:14 +00:00
case GE_CMD_TRANSFERSRC :
{
// Nothing to do, the next one prints
}
break ;
2012-11-01 15:19:01 +00:00
case GE_CMD_TRANSFERSRCW :
{
u32 xferSrc = gstate . transfersrc | ( ( data & 0xFF0000 ) < < 8 ) ;
u32 xferSrcW = gstate . transfersrcw & 1023 ;
DEBUG_LOG ( G3D , " Block Transfer Src: %08x W: %i " , xferSrc , xferSrcW ) ;
break ;
}
2012-11-19 22:29:14 +00:00
case GE_CMD_TRANSFERDST :
{
// Nothing to do, the next one prints
}
break ;
2012-11-01 15:19:01 +00:00
case GE_CMD_TRANSFERDSTW :
{
u32 xferDst = gstate . transferdst | ( ( data & 0xFF0000 ) < < 8 ) ;
u32 xferDstW = gstate . transferdstw & 1023 ;
DEBUG_LOG ( G3D , " Block Transfer Dest: %08x W: %i " , xferDst , xferDstW ) ;
break ;
}
case GE_CMD_TRANSFERSRCPOS :
{
u32 x = ( data & 1023 ) + 1 ;
u32 y = ( ( data > > 10 ) & 1023 ) + 1 ;
2012-11-02 11:33:16 +00:00
DEBUG_LOG ( G3D , " DL Block Transfer Src Rect TL: %i, %i " , x , y ) ;
2012-11-01 15:19:01 +00:00
break ;
}
case GE_CMD_TRANSFERDSTPOS :
{
u32 x = ( data & 1023 ) + 1 ;
u32 y = ( ( data > > 10 ) & 1023 ) + 1 ;
2012-11-02 11:33:16 +00:00
DEBUG_LOG ( G3D , " DL Block Transfer Dest Rect TL: %i, %i " , x , y ) ;
2012-11-01 15:19:01 +00:00
break ;
}
case GE_CMD_TRANSFERSIZE :
{
u32 w = ( data & 1023 ) + 1 ;
u32 h = ( ( data > > 10 ) & 1023 ) + 1 ;
2012-11-02 11:33:16 +00:00
DEBUG_LOG ( G3D , " DL Block Transfer Rect Size: %i x %i " , w , h ) ;
2012-11-01 15:19:01 +00:00
break ;
}
case GE_CMD_TRANSFERSTART :
{
2012-11-19 22:29:14 +00:00
ERROR_LOG ( G3D , " UNIMPL DL Block Transfer Start: PixFormat %i " , data ) ;
2012-11-02 11:33:16 +00:00
// TODO: Here we should check if the transfer overlaps a framebuffer or any textures,
// and take appropriate action. If not, this should just be a block transfer within
// GPU memory which could be implemented by a copy loop.
2012-11-01 15:19:01 +00:00
break ;
}
case GE_CMD_TEXSIZE0 :
2012-11-18 12:04:49 +00:00
gstate_c . textureChanged = true ;
gstate_c . curTextureWidth = 1 < < ( gstate . texsize [ 0 ] & 0xf ) ;
gstate_c . curTextureHeight = 1 < < ( ( gstate . texsize [ 0 ] > > 8 ) & 0xf ) ;
2012-11-01 15:19:01 +00:00
//fall thru - ignoring the mipmap sizes for now
case GE_CMD_TEXSIZE1 :
case GE_CMD_TEXSIZE2 :
case GE_CMD_TEXSIZE3 :
case GE_CMD_TEXSIZE4 :
case GE_CMD_TEXSIZE5 :
case GE_CMD_TEXSIZE6 :
case GE_CMD_TEXSIZE7 :
DEBUG_LOG ( G3D , " DL Texture Size: %06x " , data ) ;
break ;
case GE_CMD_ZBUFPTR :
{
u32 ptr = op & 0xFFE000 ;
DEBUG_LOG ( G3D , " Zbuf Ptr: %06x " , ptr ) ;
}
break ;
case GE_CMD_ZBUFWIDTH :
{
u32 w = data & 0xFFFFFF ;
DEBUG_LOG ( G3D , " Zbuf Width: %i " , w ) ;
}
break ;
case GE_CMD_AMBIENTCOLOR :
DEBUG_LOG ( G3D , " DL Ambient Color: %06x " , data ) ;
break ;
case GE_CMD_AMBIENTALPHA :
DEBUG_LOG ( G3D , " DL Ambient Alpha: %06x " , data ) ;
break ;
case GE_CMD_MATERIALAMBIENT :
DEBUG_LOG ( G3D , " DL Material Ambient Color: %06x " , data ) ;
break ;
case GE_CMD_MATERIALDIFFUSE :
DEBUG_LOG ( G3D , " DL Material Diffuse Color: %06x " , data ) ;
break ;
case GE_CMD_MATERIALEMISSIVE :
DEBUG_LOG ( G3D , " DL Material Emissive Color: %06x " , data ) ;
break ;
case GE_CMD_MATERIALSPECULAR :
DEBUG_LOG ( G3D , " DL Material Specular Color: %06x " , data ) ;
break ;
case GE_CMD_MATERIALALPHA :
DEBUG_LOG ( G3D , " DL Material Alpha Color: %06x " , data ) ;
break ;
case GE_CMD_MATERIALSPECULARCOEF :
DEBUG_LOG ( G3D , " DL Material specular coef: %f " , getFloat24 ( data ) ) ;
break ;
case GE_CMD_LIGHTTYPE0 :
case GE_CMD_LIGHTTYPE1 :
case GE_CMD_LIGHTTYPE2 :
case GE_CMD_LIGHTTYPE3 :
DEBUG_LOG ( G3D , " DL Light %i type: %06x " , cmd - GE_CMD_LIGHTTYPE0 , data ) ;
break ;
case GE_CMD_LX0 : case GE_CMD_LY0 : case GE_CMD_LZ0 :
case GE_CMD_LX1 : case GE_CMD_LY1 : case GE_CMD_LZ1 :
case GE_CMD_LX2 : case GE_CMD_LY2 : case GE_CMD_LZ2 :
case GE_CMD_LX3 : case GE_CMD_LY3 : case GE_CMD_LZ3 :
{
int n = cmd - GE_CMD_LX0 ;
int l = n / 3 ;
int c = n % 3 ;
float val = getFloat24 ( data ) ;
DEBUG_LOG ( G3D , " DL Light %i %c pos: %f " , l , c + ' X ' , val ) ;
2012-11-18 12:04:49 +00:00
gstate_c . lightpos [ l ] [ c ] = val ;
2012-11-01 15:19:01 +00:00
}
break ;
case GE_CMD_LDX0 : case GE_CMD_LDY0 : case GE_CMD_LDZ0 :
case GE_CMD_LDX1 : case GE_CMD_LDY1 : case GE_CMD_LDZ1 :
case GE_CMD_LDX2 : case GE_CMD_LDY2 : case GE_CMD_LDZ2 :
case GE_CMD_LDX3 : case GE_CMD_LDY3 : case GE_CMD_LDZ3 :
{
int n = cmd - GE_CMD_LDX0 ;
int l = n / 3 ;
int c = n % 3 ;
float val = getFloat24 ( data ) ;
DEBUG_LOG ( G3D , " DL Light %i %c dir: %f " , l , c + ' X ' , val ) ;
2012-11-18 12:04:49 +00:00
gstate_c . lightdir [ l ] [ c ] = val ;
2012-11-01 15:19:01 +00:00
}
break ;
case GE_CMD_LKA0 : case GE_CMD_LKB0 : case GE_CMD_LKC0 :
case GE_CMD_LKA1 : case GE_CMD_LKB1 : case GE_CMD_LKC1 :
case GE_CMD_LKA2 : case GE_CMD_LKB2 : case GE_CMD_LKC2 :
case GE_CMD_LKA3 : case GE_CMD_LKB3 : case GE_CMD_LKC3 :
{
int n = cmd - GE_CMD_LKA0 ;
int l = n / 3 ;
int c = n % 3 ;
float val = getFloat24 ( data ) ;
DEBUG_LOG ( G3D , " DL Light %i %c att: %f " , l , c + ' X ' , val ) ;
2012-11-18 12:04:49 +00:00
gstate_c . lightatt [ l ] [ c ] = val ;
2012-11-01 15:19:01 +00:00
}
break ;
case GE_CMD_LAC0 : case GE_CMD_LAC1 : case GE_CMD_LAC2 : case GE_CMD_LAC3 :
case GE_CMD_LDC0 : case GE_CMD_LDC1 : case GE_CMD_LDC2 : case GE_CMD_LDC3 :
case GE_CMD_LSC0 : case GE_CMD_LSC1 : case GE_CMD_LSC2 : case GE_CMD_LSC3 :
{
2012-11-11 16:27:39 +00:00
float r = ( float ) ( data & 0xff ) / 255.0f ;
2012-11-01 15:19:01 +00:00
float g = ( float ) ( ( data > > 8 ) & 0xff ) / 255.0f ;
2012-11-11 16:27:39 +00:00
float b = ( float ) ( data > > 16 ) / 255.0f ;
2012-11-01 15:19:01 +00:00
int l = ( cmd - GE_CMD_LAC0 ) / 3 ;
int t = ( cmd - GE_CMD_LAC0 ) % 3 ;
2012-11-18 12:04:49 +00:00
gstate_c . lightColor [ t ] [ l ] . r = r ;
gstate_c . lightColor [ t ] [ l ] . g = g ;
gstate_c . lightColor [ t ] [ l ] . b = b ;
2012-11-01 15:19:01 +00:00
}
break ;
case GE_CMD_VIEWPORTX1 :
case GE_CMD_VIEWPORTY1 :
case GE_CMD_VIEWPORTZ1 :
case GE_CMD_VIEWPORTX2 :
case GE_CMD_VIEWPORTY2 :
case GE_CMD_VIEWPORTZ2 :
DEBUG_LOG ( G3D , " DL Viewport param %i: %f " , cmd - GE_CMD_VIEWPORTX1 , getFloat24 ( data ) ) ;
break ;
case GE_CMD_LIGHTENABLE0 :
case GE_CMD_LIGHTENABLE1 :
case GE_CMD_LIGHTENABLE2 :
case GE_CMD_LIGHTENABLE3 :
DEBUG_LOG ( G3D , " DL Light %i enable: %d " , cmd - GE_CMD_LIGHTENABLE0 , data ) ;
break ;
case GE_CMD_CULL :
DEBUG_LOG ( G3D , " DL cull: %06x " , data ) ;
2012-11-16 14:35:41 +00:00
glCullFace ( data & 1 ? GL_FRONT : GL_BACK ) ;
//glCullFace(data & 1 ? GL_BACK : GL_FRONT);
2012-11-01 15:19:01 +00:00
break ;
case GE_CMD_LMODE :
DEBUG_LOG ( G3D , " DL Shade mode: %06x " , data ) ;
break ;
case GE_CMD_PATCHDIVISION :
2012-11-18 12:04:49 +00:00
gstate_c . patch_div_s = data & 0xFF ;
gstate_c . patch_div_t = ( data > > 8 ) & 0xFF ;
DEBUG_LOG ( G3D , " DL Patch subdivision: %i x %i " , gstate_c . patch_div_s , gstate_c . patch_div_t ) ;
2012-11-01 15:19:01 +00:00
break ;
case GE_CMD_MATERIALUPDATE :
DEBUG_LOG ( G3D , " DL Material Update: %d " , data ) ;
break ;
//////////////////////////////////////////////////////////////////
// CLEARING
//////////////////////////////////////////////////////////////////
case GE_CMD_CLEARMODE :
// If it becomes a performance problem, check diff&1
if ( data & 1 )
EnterClearMode ( data ) ;
else
LeaveClearMode ( ) ;
DEBUG_LOG ( G3D , " DL Clear mode: %06x " , data ) ;
break ;
//////////////////////////////////////////////////////////////////
// ALPHA BLENDING
//////////////////////////////////////////////////////////////////
case GE_CMD_ALPHABLENDENABLE :
DEBUG_LOG ( G3D , " DL Alpha blend enable: %d " , data ) ;
glEnDis ( GL_BLEND , data ) ;
break ;
case GE_CMD_BLENDMODE :
DEBUG_LOG ( G3D , " DL Blend mode: %06x " , data ) ;
SetBlendModePSP ( data ) ;
break ;
case GE_CMD_BLENDFIXEDA :
DEBUG_LOG ( G3D , " DL Blend fix A: %06x " , data ) ;
break ;
case GE_CMD_BLENDFIXEDB :
DEBUG_LOG ( G3D , " DL Blend fix B: %06x " , data ) ;
break ;
case GE_CMD_ALPHATESTENABLE :
DEBUG_LOG ( G3D , " DL Alpha test enable: %d " , data ) ;
// This is done in the shader.
break ;
case GE_CMD_ALPHATEST :
DEBUG_LOG ( G3D , " DL Alpha test settings " ) ;
shaderManager . DirtyUniform ( DIRTY_ALPHAREF ) ;
break ;
case GE_CMD_TEXFUNC :
{
DEBUG_LOG ( G3D , " DL TexFunc %i " , data & 7 ) ;
/*
int m = GL_MODULATE ;
switch ( data & 7 )
{
case 0 : m = GL_MODULATE ; break ;
case 1 : m = GL_DECAL ; break ;
case 2 : m = GL_BLEND ; break ;
case 3 : m = GL_REPLACE ; break ;
case 4 : m = GL_ADD ; break ;
} */
/*
glTexEnvi ( GL_TEXTURE_ENV , GL_TEXTURE_ENV_MODE , GL_COMBINE ) ;
glTexEnvi ( GL_TEXTURE_ENV , GL_COMBINE_RGB , GL_MODULATE ) ;
glTexEnvi ( GL_TEXTURE_ENV , GL_SOURCE0_RGB , GL_CONSTANT ) ;
glTexEnvi ( GL_TEXTURE_ENV , GL_OPERAND0_RGB , GL_SRC_COLOR ) ;
glTexEnvi ( GL_TEXTURE_ENV , GL_SOURCE1_RGB , GL_TEXTURE ) ;
glTexEnvi ( GL_TEXTURE_ENV , GL_OPERAND1_RGB , GL_SRC_COLOR ) ;
glTexEnvi ( GL_TEXTURE_ENV , GL_RGB_SCALE , 1 ) ;
glTexEnvi ( GL_TEXTURE_ENV , GL_TEXTURE_ENV_MODE , m ) ;
glTexEnvi ( GL_TEXTURE_ENV , GL_COMBINE_ALPHA , GL_MODULATE ) ; */
break ;
}
case GE_CMD_TEXFILTER :
{
int min = data & 7 ;
int mag = ( data > > 8 ) & 1 ;
DEBUG_LOG ( G3D , " DL TexFilter min: %i mag: %i " , min , mag ) ;
}
break ;
//////////////////////////////////////////////////////////////////
// Z/STENCIL TESTING
//////////////////////////////////////////////////////////////////
case GE_CMD_ZTESTENABLE :
glEnDis ( GL_DEPTH_TEST , data & 1 ) ;
DEBUG_LOG ( G3D , " DL Z test enable: %d " , data & 1 ) ;
break ;
case GE_CMD_STENCILTESTENABLE :
DEBUG_LOG ( G3D , " DL Stencil test enable: %d " , data ) ;
break ;
case GE_CMD_ZTEST :
{
2012-11-05 09:05:09 +00:00
static const GLuint ztests [ 8 ] =
{
GL_NEVER , GL_ALWAYS , GL_EQUAL , GL_NOTEQUAL ,
GL_LESS , GL_LEQUAL , GL_GREATER , GL_GEQUAL
} ;
2012-11-01 15:19:01 +00:00
//glDepthFunc(ztests[data&7]);
glDepthFunc ( GL_LEQUAL ) ;
DEBUG_LOG ( G3D , " DL Z test mode: %i " , data ) ;
}
break ;
case GE_CMD_MORPHWEIGHT0 :
case GE_CMD_MORPHWEIGHT1 :
case GE_CMD_MORPHWEIGHT2 :
case GE_CMD_MORPHWEIGHT3 :
case GE_CMD_MORPHWEIGHT4 :
case GE_CMD_MORPHWEIGHT5 :
case GE_CMD_MORPHWEIGHT6 :
case GE_CMD_MORPHWEIGHT7 :
2012-11-02 11:33:16 +00:00
{
int index = cmd - GE_CMD_MORPHWEIGHT0 ;
float weight = getFloat24 ( data ) ;
DEBUG_LOG ( G3D , " DL MorphWeight %i = %f " , index , weight ) ;
2012-11-18 12:04:49 +00:00
gstate_c . morphWeights [ index ] = weight ;
2012-11-02 11:33:16 +00:00
}
2012-11-01 15:19:01 +00:00
break ;
case GE_CMD_DITH0 :
case GE_CMD_DITH1 :
case GE_CMD_DITH2 :
case GE_CMD_DITH3 :
DEBUG_LOG ( G3D , " DL DitherMatrix %i = %06x " , cmd - GE_CMD_DITH0 , data ) ;
break ;
case GE_CMD_WORLDMATRIXNUMBER :
DEBUG_LOG ( G3D , " DL World matrix # %i " , data ) ;
gstate . worldmtxnum = data & 0xF ;
break ;
case GE_CMD_WORLDMATRIXDATA :
DEBUG_LOG ( G3D , " DL World matrix data # %f " , getFloat24 ( data ) ) ;
gstate . worldMatrix [ gstate . worldmtxnum + + ] = getFloat24 ( data ) ;
break ;
case GE_CMD_VIEWMATRIXNUMBER :
DEBUG_LOG ( G3D , " DL VIEW matrix # %i " , data ) ;
gstate . viewmtxnum = data & 0xF ;
break ;
case GE_CMD_VIEWMATRIXDATA :
DEBUG_LOG ( G3D , " DL VIEW matrix data # %f " , getFloat24 ( data ) ) ;
gstate . viewMatrix [ gstate . viewmtxnum + + ] = getFloat24 ( data ) ;
break ;
case GE_CMD_PROJMATRIXNUMBER :
DEBUG_LOG ( G3D , " DL PROJECTION matrix # %i " , data ) ;
gstate . projmtxnum = data & 0xF ;
break ;
case GE_CMD_PROJMATRIXDATA :
DEBUG_LOG ( G3D , " DL PROJECTION matrix data # %f " , getFloat24 ( data ) ) ;
gstate . projMatrix [ gstate . projmtxnum + + ] = getFloat24 ( data ) ;
shaderManager . DirtyUniform ( DIRTY_PROJMATRIX ) ;
break ;
case GE_CMD_TGENMATRIXNUMBER :
DEBUG_LOG ( G3D , " DL TGEN matrix # %i " , data ) ;
gstate . texmtxnum = data & 0xF ;
break ;
case GE_CMD_TGENMATRIXDATA :
DEBUG_LOG ( G3D , " DL TGEN matrix data # %f " , getFloat24 ( data ) ) ;
gstate . tgenMatrix [ gstate . texmtxnum + + ] = getFloat24 ( data ) ;
break ;
case GE_CMD_BONEMATRIXNUMBER :
DEBUG_LOG ( G3D , " DL BONE matrix #%i " , data ) ;
gstate . boneMatrixNumber = data ;
break ;
case GE_CMD_BONEMATRIXDATA :
DEBUG_LOG ( G3D , " DL BONE matrix data #%i %f " , gstate . boneMatrixNumber , getFloat24 ( data ) ) ;
gstate . boneMatrix [ gstate . boneMatrixNumber + + ] = getFloat24 ( data ) ;
break ;
default :
DEBUG_LOG ( G3D , " DL Unknown: %08x @ %08x " , op , dcontext . pc ) ;
break ;
//ETC...
}
}
2012-11-06 16:05:27 +00:00
bool GLES_GPU : : InterpretList ( )
2012-11-01 15:19:01 +00:00
{
// Reset stackptr for safety
stackptr = 0 ;
u32 op = 0 ;
prev = 0 ;
finished = false ;
while ( ! finished )
{
2012-11-07 14:40:46 +00:00
if ( ! Memory : : IsValidAddress ( dcontext . pc ) ) {
ERROR_LOG ( G3D , " DL PC = %08x WTF!!!! " , dcontext . pc ) ;
return true ;
}
2012-11-01 15:19:01 +00:00
if ( dcontext . pc = = dcontext . stallAddr )
return false ;
op = Memory : : ReadUnchecked_U32 ( dcontext . pc ) ; //read from memory
u32 cmd = op > > 24 ;
u32 diff = op ^ gstate . cmdmem [ cmd ] ;
gstate . cmdmem [ cmd ] = op ; // crashes if I try to put the whole op there??
ExecuteOp ( op , diff ) ;
dcontext . pc + = 4 ;
prev = op ;
}
return true ;
}