1
0
mirror of https://github.com/blawar/GLideN64.git synced 2024-07-02 09:03:37 +00:00

Implement CBFD microcode.

This commit is contained in:
Sergey Lipskiy 2014-10-16 17:49:32 +07:00
parent 11381ad369
commit 3db3e02cab
22 changed files with 530 additions and 28 deletions

View File

@ -141,7 +141,7 @@ End:
}
inline float DotProduct(float v0[3], float v1[3])
inline float DotProduct(const float v0[3], const float v1[3])
{
float dot;
#ifdef WIN32_ASM

View File

@ -10,10 +10,11 @@ set(GLideN64_SOURCES
DepthBuffer.cpp
F3D.cpp
F3DDKR.cpp
F3DEX2.cpp
F3DEX.cpp
F3DPD.cpp
F3DWRUS.cpp
F3DEX2.cpp
F3DEX2CBFD.cpp
FrameBuffer.cpp
GBI.cpp
gDP.cpp

View File

@ -335,6 +335,7 @@ void F3D_Tri4( u32 w0, u32 w1 )
void F3D_Init()
{
gSPSetupFunctions();
// Set GeometryMode flags
GBI_InitFlags( F3D );

View File

@ -3,7 +3,7 @@
#include "F3D.h"
#include "F3DDKR.h"
#include "N64.h"
#include "RSP.h"
#include "RSP.h"
#include "RDP.h"
#include "gSP.h"
#include "gDP.h"
@ -108,6 +108,7 @@ void F3DDKR_MoveWord( u32 w0, u32 w1 )
void F3DDKR_Init()
{
gSPSetupFunctions();
// Set GeometryMode flags
GBI_InitFlags( F3D );
@ -145,4 +146,4 @@ void F3DJFG_Init()
{
F3DDKR_Init();
GBI_SetGBI(G_DMA_VTX, F3DDKR_DMA_VTX, F3DJFG_DMA_Vtx);
}
}

View File

@ -16,7 +16,7 @@ void F3DEX_Vtx( u32 w0, u32 w1 )
void F3DEX_Tri1( u32 w0, u32 w1 )
{
gSP1Triangle( _SHIFTR( w1, 17, 7 ), _SHIFTR( w1, 9, 7 ), _SHIFTR( w1, 1, 7 ));
gSP1Triangle( _SHIFTR( w1, 17, 7 ), _SHIFTR( w1, 9, 7 ), _SHIFTR( w1, 1, 7 ));
}
void F3DEX_CullDL( u32 w0, u32 w1 )
@ -52,6 +52,7 @@ void F3DEX_Load_uCode( u32 w0, u32 w1 )
void F3DEX_Init()
{
gSPSetupFunctions();
// Set GeometryMode flags
GBI_InitFlags( F3DEX );

View File

@ -63,6 +63,16 @@ void F3DEX2_Tri1( u32 w0, u32 w1 )
_SHIFTR( w0, 1, 7 ));
}
void F3DEX2_Line3D( u32 w0, u32 w1 )
{
/*
u16 width = (u16)(w0 + 3)&0xFF;
gSP1Triangle( _SHIFTR( w0, 17, 7 ),
_SHIFTR( w0, 9, 7 ),
_SHIFTR( w0, 9, 7 ));
*/
}
void F3DEX2_PopMtx( u32 w0, u32 w1 )
{
gSPPopMatrixN( 0, w1 >> 6 );
@ -224,6 +234,7 @@ void F3DEX2_Quad( u32 w0, u32 w1 )
void F3DEX2_Init()
{
gSPSetupFunctions();
// Set GeometryMode flags
GBI_InitFlags( F3DEX2 );
@ -256,6 +267,6 @@ void F3DEX2_Init()
GBI_SetGBI( G_TRI1, F3DEX2_TRI1, F3DEX2_Tri1 );
GBI_SetGBI( G_TRI2, F3DEX2_TRI2, F3DEX_Tri2 );
GBI_SetGBI( G_QUAD, F3DEX2_QUAD, F3DEX2_Quad );
// GBI_SetGBI( G_LINE3D, F3DEX2_LINE3D, F3DEX2_Line3D );
GBI_SetGBI( G_LINE3D, F3DEX2_LINE3D, F3DEX2_Line3D );
}

View File

@ -63,7 +63,7 @@
#define F3DEX2_TRI1 0x05
#define F3DEX2_TRI2 0x06
#define F3DEX2_QUAD 0x07
//#define F3DEX2_LINE3D 0x08
#define F3DEX2_LINE3D 0x08
void F3DEX2_Mtx( u32 w0, u32 w1 );
@ -77,7 +77,7 @@ void F3DEX2_Texture( u32 w0, u32 w1 );
void F3DEX2_SetOtherMode_H( u32 w0, u32 w1 );
void F3DEX2_SetOtherMode_L( u32 w0, u32 w1 );
void F3DEX2_GeometryMode( u32 w0, u32 w1 );
//void F3DEX2_Line3D( u32 w0, u32 w1 );
void F3DEX2_Line3D( u32 w0, u32 w1 );
void F3DEX2_DMAIO( u32 w0, u32 w1 );
void F3DEX2_Special_1( u32 w0, u32 w1 );
void F3DEX2_Special_2( u32 w0, u32 w1 );

120
F3DEX2CBFD.cpp Normal file
View File

@ -0,0 +1,120 @@
#include "GLideN64.h"
#include "Debug.h"
#include "F3D.h"
#include "F3DEX.h"
#include "F3DEX2.h"
#include "F3DEX2CBFD.h"
#include "N64.h"
#include "RSP.h"
#include "RDP.h"
#include "gSP.h"
#include "gDP.h"
#include "GBI.h"
#include "OpenGL.h"
void F3DEX2CBFD_Vtx( u32 w0, u32 w1 )
{
u32 n = _SHIFTR( w0, 12, 8 );
gSPCBFDVertex( w1, n, _SHIFTR( w0, 1, 7 ) - n );
}
void F3DEX2CBFD_MoveWord( u32 w0, u32 w1 )
{
switch (_SHIFTR( w0, 16, 8 ))
{
case G_MW_NUMLIGHT:
gSPNumLights( w1 / 48 );
break;
case G_MW_CLIP:
gSPClipRatio( w1 );
break;
case G_MW_SEGMENT:
gSPSegment( _SHIFTR( w0, 0, 16 ) >> 2, w1 & 0x00FFFFFF );
break;
case G_MW_FOG:
gSPFogFactor( (s16)_SHIFTR( w1, 16, 16 ), (s16)_SHIFTR( w1, 0, 16 ) );
break;
case G_MW_PERSPNORM:
gSPPerspNormalize( w1 );
break;
case G_MW_COORD_MOD:
gSPCoordMod( w0, w1 );
break;
}
}
void F3DEX2CBFD_MoveMem( u32 w0, u32 w1 )
{
#ifdef __TRIBUFFER_OPT
gSPFlushTriangles();
#endif
switch (_SHIFTR( w0, 0, 8 ))
{
case F3DEX2_MV_VIEWPORT:
gSPViewport( w1 );
break;
case G_MV_LIGHT:
{
const u32 offset = _SHIFTR(w0, 5, 14);
const u32 n = offset / 48;
if (n < 2)
gSPLookAt(w1, n);
else
gSPLightCBFD(w1, n - 2);
}
break;
case G_MV_NORMALES:
gSPSetVertexNormaleBase(w1);
//RSP.PC[RSP.PCi] += 8;
break;
}
}
void F3DEX2CBFD_Tri4( u32 w0, u32 w1 )
{
gSP4Triangles( _SHIFTR( w0, 23, 5 ), _SHIFTR( w0, 18, 5 ), (_SHIFTR( w0, 15, 3 )<<2)|_SHIFTR( w1, 30, 2 ),
_SHIFTR( w0, 10, 5 ), _SHIFTR( w0, 5, 5 ), _SHIFTR( w0, 0, 5 ),
_SHIFTR( w1, 25, 5 ), _SHIFTR( w1, 20, 5 ), _SHIFTR( w1, 15, 5 ),
_SHIFTR( w1, 10, 5 ), _SHIFTR( w1, 5, 5 ), _SHIFTR( w1, 0, 5 ) );
}
void F3DEX2CBFD_Init()
{
gSPSetupFunctions();
// Set GeometryMode flags
GBI_InitFlags( F3DEX2 );
GBI.PCStackSize = 18;
// GBI Command Command Value Command Function
GBI_SetGBI( G_RDPHALF_2, F3DEX2_RDPHALF_2, F3D_RDPHalf_2 );
GBI_SetGBI( G_SETOTHERMODE_H, F3DEX2_SETOTHERMODE_H, F3DEX2_SetOtherMode_H );
GBI_SetGBI( G_SETOTHERMODE_L, F3DEX2_SETOTHERMODE_L, F3DEX2_SetOtherMode_L );
GBI_SetGBI( G_RDPHALF_1, F3DEX2_RDPHALF_1, F3D_RDPHalf_1 );
GBI_SetGBI( G_SPNOOP, F3DEX2_SPNOOP, F3D_SPNoOp );
GBI_SetGBI( G_ENDDL, F3DEX2_ENDDL, F3D_EndDL );
GBI_SetGBI( G_DL, F3DEX2_DL, F3D_DList );
GBI_SetGBI( G_LOAD_UCODE, F3DEX2_LOAD_UCODE, F3DEX_Load_uCode );
GBI_SetGBI( G_MOVEMEM, F3DEX2_MOVEMEM, F3DEX2CBFD_MoveMem );
GBI_SetGBI( G_MOVEWORD, F3DEX2_MOVEWORD, F3DEX2CBFD_MoveWord );
GBI_SetGBI( G_MTX, F3DEX2_MTX, F3DEX2_Mtx );
GBI_SetGBI( G_GEOMETRYMODE, F3DEX2_GEOMETRYMODE, F3DEX2_GeometryMode );
GBI_SetGBI( G_POPMTX, F3DEX2_POPMTX, F3DEX2_PopMtx );
GBI_SetGBI( G_TEXTURE, F3DEX2_TEXTURE, F3DEX2_Texture );
GBI_SetGBI( G_DMA_IO, F3DEX2_DMA_IO, F3DEX2_DMAIO );
GBI_SetGBI( G_SPECIAL_1, F3DEX2_SPECIAL_1, F3DEX2_Special_1 );
GBI_SetGBI( G_SPECIAL_2, F3DEX2_SPECIAL_2, F3DEX2_Special_2 );
GBI_SetGBI( G_SPECIAL_3, F3DEX2_SPECIAL_3, F3DEX2_Special_3 );
GBI_SetGBI( G_VTX, F3DEX2_VTX, F3DEX2CBFD_Vtx );
GBI_SetGBI( G_MODIFYVTX, F3DEX2_MODIFYVTX, F3DEX_ModifyVtx );
GBI_SetGBI( G_CULLDL, F3DEX2_CULLDL, F3DEX_CullDL );
GBI_SetGBI( G_BRANCH_Z, F3DEX2_BRANCH_Z, F3DEX_Branch_Z );
GBI_SetGBI( G_TRI1, F3DEX2_TRI1, F3DEX2_Tri1 );
GBI_SetGBI( G_TRI2, F3DEX2_TRI2, F3DEX_Tri2 );
GBI_SetGBI( G_QUAD, F3DEX2_QUAD, F3DEX2_Quad );
GBI_SetGBI( G_LINE3D, F3DEX2_LINE3D, F3DEX2_Line3D );
for (u32 i = 0; i < 16; ++i)
GBI.cmd[F3DEX2CBFD_TRI4+i] = F3DEX2CBFD_Tri4;
}

8
F3DEX2CBFD.h Normal file
View File

@ -0,0 +1,8 @@
#ifndef F3DEX2CBFD_H
#define F3DEX2CBFD_H
#define F3DEX2CBFD_TRI4 16
void F3DEX2CBFD_Init();
#endif // F3DEX2CBFD_H

View File

@ -3,7 +3,7 @@
#include "F3D.h"
#include "F3DPD.h"
#include "N64.h"
#include "RSP.h"
#include "RSP.h"
#include "RDP.h"
#include "gSP.h"
#include "gDP.h"
@ -21,6 +21,7 @@ void F3DPD_VtxColorBase( u32 w0, u32 w1 )
void F3DPD_Init()
{
gSPSetupFunctions();
// Set GeometryMode flags
GBI_InitFlags( F3D );

View File

@ -4,7 +4,7 @@
#include "F3DEX.h"
#include "F3DWRUS.h"
#include "N64.h"
#include "RSP.h"
#include "RSP.h"
#include "RDP.h"
#include "gSP.h"
#include "gDP.h"
@ -18,7 +18,7 @@ void F3DWRUS_Vtx( u32 w0, u32 w1 )
void F3DWRUS_Tri1( u32 w0, u32 w1 )
{
gSP1Triangle( _SHIFTR( w1, 16, 8 ) / 5,
_SHIFTR( w1, 8, 8 ) / 5,
_SHIFTR( w1, 8, 8 ) / 5,
_SHIFTR( w1, 0, 8 ) / 5);
}
@ -36,6 +36,7 @@ void F3DWRUS_Quad( u32 w0, u32 w1 )
void F3DWRUS_Init()
{
gSPSetupFunctions();
// Set GeometryMode flags
GBI_InitFlags( F3D );

10
GBI.cpp
View File

@ -19,6 +19,7 @@
#include "F3DDKR.h"
#include "F3DWRUS.h"
#include "F3DPD.h"
#include "F3DEX2CBFD.h"
#include "CRC.h"
#include "Log.h"
#include "Debug.h"
@ -35,7 +36,8 @@ SpecialMicrocodeInfo specialMicrocodes[] =
{ F3DDKR, FALSE, 0x8d91244f, "Diddy Kong Racing" },
{ F3DDKR, FALSE, 0x6e6fc893, "Diddy Kong Racing" },
{ F3DJFG, FALSE, 0xbde9d1fb, "Jet Force Gemini" },
{ F3DPD, FALSE, 0x1c4f7869, "Perfect Dark" }
{ F3DPD, FALSE, 0x1c4f7869, "Perfect Dark" },
{ F3DEX2CBFD,TRUE, 0x1b4ace88, "Conker's Bad Fur Day"}
};
u32 G_RDPHALF_1, G_RDPHALF_2, G_RDPHALF_CONT;
@ -121,12 +123,13 @@ void GBIInfo::_makeCurrent(MicrocodeInfo * _pCurrent)
}
if (m_pCurrent == NULL || (m_pCurrent->type != _pCurrent->type)) {
m_pCurrent = _pCurrent;
for (int i = 0; i <= 0xFF; ++i)
cmd[i] = GBI_Unknown;
RDP_Init();
switch (_pCurrent->type) {
switch (m_pCurrent->type) {
case F3D: F3D_Init(); break;
case F3DEX: F3DEX_Init(); break;
case F3DEX2: F3DEX2_Init(); break;
@ -139,10 +142,9 @@ void GBIInfo::_makeCurrent(MicrocodeInfo * _pCurrent)
case F3DJFG: F3DJFG_Init(); break;
case F3DWRUS: F3DWRUS_Init(); break;
case F3DPD: F3DPD_Init(); break;
case F3DEX2CBFD:F3DEX2CBFD_Init();break;
}
}
m_pCurrent = _pCurrent;
}
int MicrocodeDialog(u32 _crc, const char * _str);

6
GBI.h
View File

@ -18,7 +18,8 @@
#define F3DDKR 9
#define F3DJFG 10
#define F3DWRUS 11
#define NONE 12
#define F3DEX2CBFD 12
#define NONE 13
// Fixed point conversion factors
#define FIXED2FLOATRECIP1 0.5f
@ -84,6 +85,7 @@
#define G_MV_LIGHT 10
#define G_MV_POINT 12
#define G_MV_MATRIX 14
#define G_MV_NORMALES 14
#define G_MVO_LOOKATX 0
#define G_MVO_LOOKATY 24
@ -121,6 +123,7 @@
#define G_MW_FORCEMTX 0x0C
#define G_MW_POINTS 0x0C
#define G_MW_PERSPNORM 0x0E
#define G_MW_COORD_MOD 0x10
#define G_MWO_NUMLIGHT 0x00
#define G_MWO_CLIP_RNX 0x04
@ -683,6 +686,7 @@ struct GBIInfo
void init();
void destroy();
void loadMicrocode(u32 uc_start, u32 uc_dstart, u16 uc_dsize);
u32 getMicrocodeType() const {return m_pCurrent != NULL ? m_pCurrent->type : NONE;}
private:
void _makeCurrent(MicrocodeInfo * _pCurrent);

View File

@ -249,6 +249,7 @@
</ClCompile>
<ClCompile Include="CRC.cpp" />
<ClCompile Include="DepthBuffer.cpp" />
<ClCompile Include="F3DEX2CBFD.cpp" />
<ClCompile Include="FrameBuffer.cpp" />
<ClCompile Include="GBI.cpp" />
<ClCompile Include="gDP.cpp" />
@ -338,6 +339,7 @@
<ClInclude Include="CRC.h" />
<ClInclude Include="Debug.h" />
<ClInclude Include="DepthBuffer.h" />
<ClInclude Include="F3DEX2CBFD.h" />
<ClInclude Include="FrameBuffer.h" />
<ClInclude Include="GBI.h" />
<ClInclude Include="gDP.h" />

View File

@ -177,6 +177,9 @@
<ClCompile Include="windows\ZilmarAPIImpl_windows.cpp">
<Filter>Source Files\windows</Filter>
</ClCompile>
<ClCompile Include="F3DEX2CBFD.cpp">
<Filter>Source Files\uCodes</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="3DMath.h">
@ -302,6 +305,9 @@
<ClInclude Include="Log.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="F3DEX2CBFD.h">
<Filter>Header Files\uCodes</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="Resource.rc">

View File

@ -3,7 +3,7 @@
#include "F3D.h"
#include "L3D.h"
#include "N64.h"
#include "RSP.h"
#include "RSP.h"
#include "RDP.h"
#include "gSP.h"
#include "gDP.h"
@ -21,6 +21,7 @@ void L3D_Line3D( u32 w0, u32 w1 )
void L3D_Init()
{
gSPSetupFunctions();
// Set GeometryMode flags
GBI_InitFlags( F3D );

View File

@ -5,7 +5,7 @@
#include "L3D.h"
#include "L3DEX.h"
#include "N64.h"
#include "RSP.h"
#include "RSP.h"
#include "RDP.h"
#include "gSP.h"
#include "gDP.h"
@ -23,6 +23,7 @@ void L3DEX_Line3D( u32 w0, u32 w1 )
void L3DEX_Init()
{
gSPSetupFunctions();
// Set GeometryMode flags
GBI_InitFlags( F3DEX );

View File

@ -5,7 +5,7 @@
#include "F3DEX2.h"
#include "L3DEX2.h"
#include "N64.h"
#include "RSP.h"
#include "RSP.h"
#include "RDP.h"
#include "gSP.h"
#include "gDP.h"
@ -23,6 +23,7 @@ void L3DEX2_Line3D( u32 w0, u32 w1 )
void L3DEX2_Init()
{
gSPSetupFunctions();
// Set GeometryMode flags
GBI_InitFlags( F3DEX2 );

View File

@ -3,13 +3,13 @@
#include "F3D.h"
#include "F3DEX.h"
#include "GBI.h"
#include "gSP.h"
#include "gSP.h"
#include "gDP.h"
#include "RSP.h"
#include "Types.h"
void S2DEX_BG_1Cyc( u32 w0, u32 w1 )
{
{
gSPBgRect1Cyc( w1 );
}
@ -69,6 +69,7 @@ void S2DEX_Obj_LdTx_Rect_R( u32 w0, u32 w1 )
void S2DEX_Init()
{
gSPSetupFunctions();
// Set GeometryMode flags
GBI_InitFlags( F3DEX );

View File

@ -5,13 +5,14 @@
#include "F3DEX.h"
#include "F3DEX2.h"
#include "GBI.h"
#include "gSP.h"
#include "gSP.h"
#include "gDP.h"
#include "RSP.h"
#include "Types.h"
void S2DEX2_Init()
{
gSPSetupFunctions();
// Set GeometryMode flags
GBI_InitFlags( F3DEX2 );

335
gSP.cpp
View File

@ -181,7 +181,7 @@ static void gSPPointLightVertex4_default(u32 v, float _vPos[4][3])
const float light_len = sqrtf(light_len2);
const float at = gSP.lights[l].ca + light_len/65535.0f*gSP.lights[l].la + light_len2/65535.0f*gSP.lights[l].qa;
if (at > 0.0f)
light_intensity = 1/at;//DotProduct (lvec, nvec) / (light_len * normal_len * at);
light_intensity = 1/at;
else
light_intensity = 0.0f;
if (light_intensity > 0.0f) {
@ -196,6 +196,90 @@ static void gSPPointLightVertex4_default(u32 v, float _vPos[4][3])
}
}
static void gSPLightVertex4_CBFD(u32 v)
{
gSPTransformNormal4(v, gSP.matrix.modelView[gSP.matrix.modelViewi]);
OGLRender & render = video().getRender();
for(int j = 0; j < 4; ++j) {
SPVertex & vtx = render.getVertex(v+j);
f32 r = gSP.lights[gSP.numLights].r;
f32 g = gSP.lights[gSP.numLights].g;
f32 b = gSP.lights[gSP.numLights].b;
for (u32 l = 0; l < gSP.numLights; ++l) {
const SPLight & light = gSP.lights[l];
const f32 vx = (vtx.x + gSP.vertexCoordMod[ 8])*gSP.vertexCoordMod[12] - light.posx;
const f32 vy = (vtx.y + gSP.vertexCoordMod[ 9])*gSP.vertexCoordMod[13] - light.posy;
const f32 vz = (vtx.z + gSP.vertexCoordMod[10])*gSP.vertexCoordMod[14] - light.posz;
const f32 vw = (vtx.w + gSP.vertexCoordMod[11])*gSP.vertexCoordMod[15] - light.posw;
const f32 len = (vx*vx+vy*vy+vz*vz+vw*vw)/65536.0f;
f32 intensity = light.ca / len;
if (intensity > 1.0f) intensity = 1.0f;
r += light.r * intensity;
g += light.g * intensity;
b += light.b * intensity;
}
r = min(1.0f, r);
g = min(1.0f, g);
b = min(1.0f, b);
vtx.r *= r;
vtx.g *= g;
vtx.b *= b;
vtx.HWLight = 0;
}
}
static void gSPPointLightVertex4_CBFD(u32 v, float _vPos[4][3])
{
gSPTransformNormal4(v, gSP.matrix.modelView[gSP.matrix.modelViewi]);
OGLRender & render = video().getRender();
for(int j = 0; j < 4; ++j) {
SPVertex & vtx = render.getVertex(v+j);
f32 r = gSP.lights[gSP.numLights].r;
f32 g = gSP.lights[gSP.numLights].g;
f32 b = gSP.lights[gSP.numLights].b;
f32 intensity = 0.0f;
for (u32 l = 0; l < gSP.numLights-1; ++l) {
const SPLight & light = gSP.lights[l];
intensity = DotProduct( &vtx.nx, &light.x );
if (intensity < 0.0f)
continue;
if (light.ca > 0.0f) {
const f32 vx = (vtx.x + gSP.vertexCoordMod[ 8])*gSP.vertexCoordMod[12] - light.posx;
const f32 vy = (vtx.y + gSP.vertexCoordMod[ 9])*gSP.vertexCoordMod[13] - light.posy;
const f32 vz = (vtx.z + gSP.vertexCoordMod[10])*gSP.vertexCoordMod[14] - light.posz;
const f32 vw = (vtx.w + gSP.vertexCoordMod[11])*gSP.vertexCoordMod[15] - light.posw;
const f32 len = (vx*vx+vy*vy+vz*vz+vw*vw)/65536.0f;
float p_i = light.ca / len;
if (p_i > 1.0f) p_i = 1.0f;
intensity *= p_i;
}
r += light.r * intensity;
g += light.g * intensity;
b += light.b * intensity;
}
const SPLight & light = gSP.lights[gSP.numLights-1];
intensity = DotProduct( &vtx.nx, &light.x );
if (intensity > 0.0f) {
r += light.r * intensity;
g += light.g * intensity;
b += light.b * intensity;
}
r = min(1.0f, r);
g = min(1.0f, g);
b = min(1.0f, b);
vtx.r *= r;
vtx.g *= g;
vtx.b *= b;
vtx.HWLight = 0;
}
}
static void gSPBillboardVertex4_default(u32 v)
{
OGLRender & render = video().getRender();
@ -367,6 +451,80 @@ static void gSPPointLightVertex_default(SPVertex & _vtx, float * _vPos)
if (_vtx.b > 1.0f) _vtx.b = 1.0f;
}
static void gSPLightVertex_CBFD(SPVertex & _vtx)
{
f32 r = gSP.lights[gSP.numLights].r;
f32 g = gSP.lights[gSP.numLights].g;
f32 b = gSP.lights[gSP.numLights].b;
for (u32 l = 0; l < gSP.numLights; ++l) {
const SPLight & light = gSP.lights[l];
const f32 vx = (_vtx.x + gSP.vertexCoordMod[ 8])*gSP.vertexCoordMod[12] - light.posx;
const f32 vy = (_vtx.y + gSP.vertexCoordMod[ 9])*gSP.vertexCoordMod[13] - light.posy;
const f32 vz = (_vtx.z + gSP.vertexCoordMod[10])*gSP.vertexCoordMod[14] - light.posz;
const f32 vw = (_vtx.w + gSP.vertexCoordMod[11])*gSP.vertexCoordMod[15] - light.posw;
const f32 len = (vx*vx+vy*vy+vz*vz+vw*vw)/65536.0f;
f32 intensity = light.ca / len;
if (intensity > 1.0f) intensity = 1.0f;
r += light.r * intensity;
g += light.g * intensity;
b += light.b * intensity;
}
r = min(1.0f, r);
g = min(1.0f, g);
b = min(1.0f, b);
_vtx.r *= r;
_vtx.g *= g;
_vtx.b *= b;
_vtx.HWLight = 0;
}
static void gSPPointLightVertex_CBFD(SPVertex & _vtx, float * /*_vPos*/)
{
f32 r = gSP.lights[gSP.numLights].r;
f32 g = gSP.lights[gSP.numLights].g;
f32 b = gSP.lights[gSP.numLights].b;
f32 intensity = 0.0f;
for (u32 l = 0; l < gSP.numLights-1; ++l) {
const SPLight & light = gSP.lights[l];
intensity = DotProduct( &_vtx.nx, &light.x );
if (intensity < 0.0f)
continue;
if (light.ca > 0.0f) {
const f32 vx = (_vtx.x + gSP.vertexCoordMod[ 8])*gSP.vertexCoordMod[12] - light.posx;
const f32 vy = (_vtx.y + gSP.vertexCoordMod[ 9])*gSP.vertexCoordMod[13] - light.posy;
const f32 vz = (_vtx.z + gSP.vertexCoordMod[10])*gSP.vertexCoordMod[14] - light.posz;
const f32 vw = (_vtx.w + gSP.vertexCoordMod[11])*gSP.vertexCoordMod[15] - light.posw;
const f32 len = (vx*vx+vy*vy+vz*vz+vw*vw)/65536.0f;
float p_i = light.ca / len;
if (p_i > 1.0f) p_i = 1.0f;
intensity *= p_i;
}
r += light.r * intensity;
g += light.g * intensity;
b += light.b * intensity;
}
const SPLight & light = gSP.lights[gSP.numLights-1];
intensity = DotProduct( &_vtx.nx, &light.x );
if (intensity > 0.0f) {
r += light.r * intensity;
g += light.g * intensity;
b += light.b * intensity;
}
r = min(1.0f, r);
g = min(1.0f, g);
b = min(1.0f, b);
_vtx.r *= r;
_vtx.g *= g;
_vtx.b *= b;
_vtx.HWLight = 0;
}
static void gSPBillboardVertex_default(u32 v, u32 i)
{
OGLRender & render = video().getRender();
@ -677,6 +835,52 @@ void gSPLight( u32 l, s32 n )
#endif
}
void gSPLightCBFD( u32 l, s32 n )
{
u32 addrByte = RSP_SegmentToPhysical( l );
if ((addrByte + sizeof( Light )) > RDRAMSize) {
#ifdef DEBUG
DebugMsg( DEBUG_HIGH | DEBUG_ERROR, "// Attempting to load light from invalid address\n" );
DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "gSPLight( 0x%08X, LIGHT_%i );\n",
l, n );
#endif
return;
}
Light *light = (Light*)&RDRAM[addrByte];
if (n < 12) {
gSP.lights[n].r = light->r * 0.0039215689f;
gSP.lights[n].g = light->g * 0.0039215689f;
gSP.lights[n].b = light->b * 0.0039215689f;
gSP.lights[n].x = light->x;
gSP.lights[n].y = light->y;
gSP.lights[n].z = light->z;
Normalize( &gSP.lights[n].x );
u32 addrShort = addrByte >> 1;
gSP.lights[n].posx = (float)(((short*)RDRAM)[(addrShort+16)^1]);
gSP.lights[n].posy = (float)(((short*)RDRAM)[(addrShort+17)^1]);
gSP.lights[n].posz = (float)(((short*)RDRAM)[(addrShort+18)^1]);
gSP.lights[n].posw = (float)(((short*)RDRAM)[(addrShort+19)^1]);
gSP.lights[n].ca = (float)(RDRAM[(addrByte + 12) ^ 3]) / 16.0f;
}
if (config.enableHWLighting)
gSP.changed |= CHANGED_LIGHT;
#ifdef DEBUG
DebugMsg( DEBUG_DETAIL | DEBUG_HANDLED, "// x = %2.6f y = %2.6f z = %2.6f\n",
_FIXED2FLOAT( light->x, 7 ), _FIXED2FLOAT( light->y, 7 ), _FIXED2FLOAT( light->z, 7 ) );
DebugMsg( DEBUG_DETAIL | DEBUG_HANDLED, "// r = %3i g = %3i b = %3i\n",
light->r, light->g, light->b );
DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "gSPLight( 0x%08X, LIGHT_%i );\n",
l, n );
#endif
}
void gSPLookAt( u32 _l, u32 _n )
{
u32 address = RSP_SegmentToPhysical(_l);
@ -934,6 +1138,83 @@ void gSPDMAVertex( u32 a, u32 n, u32 v0 )
}
}
void gSPCBFDVertex( u32 a, u32 n, u32 v0 )
{
//flush batched triangles:
#ifdef __TRIBUFFER_OPT
gSPFlushTriangles();
#endif
u32 address = RSP_SegmentToPhysical(a);
if ((address + sizeof( Vertex ) * n) > RDRAMSize)
return;
Vertex *vertex = (Vertex*)&RDRAM[address];
OGLRender & render = video().getRender();
if ((n + v0) <= INDEXMAP_SIZE) {
unsigned int i = v0;
#ifdef __VEC4_OPT
for (; i < n - (n%4) + v0; i += 4) {
u32 v = i;
#ifdef __TRIBUFFER_OPT
v = render.getIndexmapNew(v, 4);
#endif
for(int j = 0; j < 4; ++j) {
SPVertex & vtx = render.getVertex(v+j);
vtx.x = vertex->x;
vtx.y = vertex->y;
vtx.z = vertex->z;
vtx.s = _FIXED2FLOAT( vertex->s, 5 );
vtx.t = _FIXED2FLOAT( vertex->t, 5 );
vtx.st_scaled = 0;
if (gSP.geometryMode & G_LIGHTING) {
const u32 normaleAddrOffset = ((v0+v+j)<<1);
vtx.nx = (float)(((s8*)RDRAM)[(gSP.vertexNormalBase + normaleAddrOffset + 0)^3]);
vtx.ny = (float)(((s8*)RDRAM)[(gSP.vertexNormalBase + normaleAddrOffset + 1)^3]);
vtx.nz = (float)((s16)(vertex->flag&0xFF));
vtx.a = vertex->color.a * 0.0039215689f;
}
vtx.r = vertex->color.r * 0.0039215689f;
vtx.g = vertex->color.g * 0.0039215689f;
vtx.b = vertex->color.b * 0.0039215689f;
vtx.a = vertex->color.a * 0.0039215689f;
vertex++;
}
gSPProcessVertex4(v);
}
#endif
for (; i < n + v0; ++i) {
u32 v = i;
#ifdef __TRIBUFFER_OPT
v = render.getIndexmapNew(v, 1);
#endif
SPVertex & vtx = render.getVertex(v);
vtx.x = vertex->x;
vtx.y = vertex->y;
vtx.z = vertex->z;
vtx.s = _FIXED2FLOAT( vertex->s, 5 );
vtx.t = _FIXED2FLOAT( vertex->t, 5 );
vtx.st_scaled = 0;
if (gSP.geometryMode & G_LIGHTING) {
const u32 normaleAddrOffset = (v<<1);
vtx.nx = (float)(((s8*)RDRAM)[(gSP.vertexNormalBase + normaleAddrOffset + 0)^3]);
vtx.ny = (float)(((s8*)RDRAM)[(gSP.vertexNormalBase + normaleAddrOffset + 1)^3]);
vtx.nz = (float)((s8)(vertex->flag&0xFF));
}
vtx.r = vertex->color.r * 0.0039215689f;
vtx.g = vertex->color.g * 0.0039215689f;
vtx.b = vertex->color.b * 0.0039215689f;
vtx.a = vertex->color.a * 0.0039215689f;
gSPProcessVertex(v);
vertex++;
}
} else {
LOG(LOG_ERROR, "Using Vertex outside buffer v0=%i, n=%i\n", v0, n);
}
}
void gSPDisplayList( u32 dl )
{
u32 address = RSP_SegmentToPhysical( dl );
@ -1117,6 +1398,16 @@ void gSPSetVertexColorBase( u32 base )
#endif
}
void gSPSetVertexNormaleBase( u32 base )
{
gSP.vertexNormalBase = RSP_SegmentToPhysical( base );
#ifdef DEBUG
DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "gSPSetVertexNormaleBase( 0x%08X );\n",
base );
#endif
}
void gSPSprite2DBase( u32 base )
{
}
@ -1418,7 +1709,7 @@ void gSPModifyVertex( u32 _vtx, u32 _where, u32 _val )
void gSPNumLights( s32 n )
{
if (n <= 8) {
if (n <= 12) {
gSP.numLights = n;
if (config.enableHWLighting)
gSP.changed |= CHANGED_LIGHT;
@ -1470,6 +1761,27 @@ void gSPPerspNormalize( u16 scale )
#endif
}
void gSPCoordMod(u32 _w0, u32 _w1)
{
if ((_w0&8) != 0)
return;
u32 idx = _SHIFTR(_w0, 1, 2);
u32 pos = _w0&0x30;
if (pos == 0) {
gSP.vertexCoordMod[0+idx] = (f32)(s16)_SHIFTR(_w1, 16, 16);
gSP.vertexCoordMod[1+idx] = (f32)(s16)_SHIFTR(_w1, 0, 16);
} else if (pos == 0x10) {
gSP.vertexCoordMod[4+idx] = _SHIFTR(_w1, 16, 16)/65536.0f;
gSP.vertexCoordMod[5+idx] = _SHIFTR(_w1, 0, 16)/65536.0f;
gSP.vertexCoordMod[12+idx] = gSP.vertexCoordMod[0+idx] + gSP.vertexCoordMod[4+idx];
gSP.vertexCoordMod[13+idx] = gSP.vertexCoordMod[1+idx] + gSP.vertexCoordMod[5+idx];
} else if (pos == 0x20) {
gSP.vertexCoordMod[8+idx] = (f32)(s16)_SHIFTR(_w1, 16, 16);
gSP.vertexCoordMod[9+idx] = (f32)(s16)_SHIFTR(_w1, 0, 16);
}
}
void gSPTexture( f32 sc, f32 tc, s32 level, s32 tile, s32 on )
{
gSP.texture.scales = sc;
@ -1954,3 +2266,22 @@ void (*gSPTransformVertex)(float vtx[4], float mtx[4][4]) =
void (*gSPLightVertex)(SPVertex & _vtx) = gSPLightVertex_default;
void (*gSPPointLightVertex)(SPVertex & _vtx, float * _vPos) = gSPPointLightVertex_default;
void (*gSPBillboardVertex)(u32 v, u32 i) = gSPBillboardVertex_default;
void gSPSetupFunctions()
{
if (GBI.getMicrocodeType() != F3DEX2CBFD) {
#ifdef __VEC4_OPT
gSPLightVertex4 = gSPLightVertex4_default;
gSPPointLightVertex4 = gSPPointLightVertex4_default;
#endif
gSPLightVertex = gSPLightVertex_default;
gSPPointLightVertex = gSPPointLightVertex_default;
return;
}
#ifdef __VEC4_OPT
gSPLightVertex4 = gSPLightVertex4_CBFD;
gSPPointLightVertex4 = gSPPointLightVertex4_CBFD;
#endif
gSPLightVertex = gSPLightVertex_CBFD;
gSPPointLightVertex = gSPPointLightVertex_CBFD;
}

15
gSP.h
View File

@ -81,7 +81,7 @@ struct SPLight
{
f32 r, g, b;
f32 x, y, z;
f32 posx, posy, posz;
f32 posx, posy, posz, posw;
f32 ca, la, qa;
};
@ -107,7 +107,7 @@ struct gSPInfo
u32 vertexColorBase;
u32 vertexi;
SPLight lights[8];
SPLight lights[12];
SPLight lookat[2];
bool lookatEnable;
@ -149,6 +149,10 @@ struct gSPInfo
{
u32 vtx, mtx, tex_offset, tex_shift, tex_count;
} DMAOffsets;
// CBFD
u32 vertexNormalBase;
f32 vertexCoordMod[16];
};
extern gSPInfo gSP;
@ -160,10 +164,12 @@ void gSPDMAMatrix( u32 matrix, u8 index, u8 multiply );
void gSPViewport( u32 v );
void gSPForceMatrix( u32 mptr );
void gSPLight( u32 l, s32 n );
void gSPLightCBFD( u32 l, s32 n );
void gSPLookAt( u32 l, u32 n );
void gSPVertex( u32 v, u32 n, u32 v0 );
void gSPCIVertex( u32 v, u32 n, u32 v0 );
void gSPDMAVertex( u32 v, u32 n, u32 v0 );
void gSPCBFDVertex( u32 v, u32 n, u32 v0 );
void gSPDisplayList( u32 dl );
void gSPDMADisplayList( u32 dl, u32 n );
void gSPBranchList( u32 dl );
@ -202,7 +208,9 @@ void gSPObjSubMatrix( u32 mtx );
void gSPSetDMAOffsets( u32 mtxoffset, u32 vtxoffset );
void gSPSetDMATexOffset(u32 _addr);
void gSPSetVertexColorBase( u32 base );
void gSPSetVertexNormaleBase( u32 base );
void gSPProcessVertex(u32 v);
void gSPCoordMod(u32 _w0, u32 _w1);
void gSPTriangleUnknown();
@ -225,6 +233,5 @@ extern void (*gSPTransformVertex)(float vtx[4], float mtx[4][4]);
extern void (*gSPLightVertex)(SPVertex & _vtx);
extern void (*gSPPointLightVertex)(SPVertex & _vtx, float * _vPos);
extern void (*gSPBillboardVertex)(u32 v, u32 i);
void gSPSetupFunctions();
#endif