aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--GPU3D.cpp160
1 files changed, 150 insertions, 10 deletions
diff --git a/GPU3D.cpp b/GPU3D.cpp
index 60fe733..9a656d7 100644
--- a/GPU3D.cpp
+++ b/GPU3D.cpp
@@ -178,6 +178,17 @@ u32 PolygonMode;
s16 CurVertex[3];
u8 VertexColor[3];
s16 TexCoords[2];
+s16 Normal[3];
+
+s16 LightDirection[4][3];
+u8 LightColor[4][3];
+u8 MatDiffuse[3];
+u8 MatAmbient[3];
+u8 MatSpecular[3];
+u8 MatEmission[3];
+
+bool UseShininessTable;
+u8 ShininessTable[128];
u32 PolygonAttr;
u32 CurPolygonAttr;
@@ -780,14 +791,14 @@ void SubmitPolygon()
poly->NumVertices += 2;
}
-//if (c==4 && NumPolygons>340) printf("polygon:\n");
+
for (int i = clipstart; i < c; i++)
{
CurVertexRAM[NumVertices] = clippedvertices[1][i];
poly->Vertices[i] = &CurVertexRAM[NumVertices];
NumVertices++;
- poly->NumVertices++;//if (c==4 && NumPolygons>340)printf(" - v%d: %08X %08X %08X\n", i, poly->Vertices[i]->Position[0], poly->Vertices[i]->Position[1],poly->Vertices[i]->Position[3]);
+ poly->NumVertices++;
}
if (PolygonMode >= 2)
@@ -800,9 +811,7 @@ void SubmitVertex()
{
s64 vertex[4] = {(s64)CurVertex[0], (s64)CurVertex[1], (s64)CurVertex[2], 0x1000};
Vertex* vertextrans = &TempVertexBuffer[VertexNumInPoly];
-if (PolygonMode==0&&NumPolygons>440&&false)printf("raw vertex %d: %08X %08X | %08X %08X %08X %08X\n",
- VertexNum, CurVertex[0], CurVertex[1],
- ClipMatrix[1],ClipMatrix[5],ClipMatrix[9],ClipMatrix[13]);
+
UpdateClipMatrix();
vertextrans->Position[0] = (vertex[0]*ClipMatrix[0] + vertex[1]*ClipMatrix[4] + vertex[2]*ClipMatrix[8] + vertex[3]*ClipMatrix[12]) >> 12;
vertextrans->Position[1] = (vertex[0]*ClipMatrix[1] + vertex[1]*ClipMatrix[5] + vertex[2]*ClipMatrix[9] + vertex[3]*ClipMatrix[13]) >> 12;
@@ -815,8 +824,8 @@ if (PolygonMode==0&&NumPolygons>440&&false)printf("raw vertex %d: %08X %08X | %0
if ((TexParam >> 30) == 3)
{
- vertextrans->TexCoords[0] = (CurVertex[0]*TexMatrix[0] + CurVertex[1]*TexMatrix[4] + CurVertex[2]*TexMatrix[8] + 0x1000*TexCoords[0]) >> 12;
- vertextrans->TexCoords[1] = (CurVertex[0]*TexMatrix[1] + CurVertex[1]*TexMatrix[5] + CurVertex[2]*TexMatrix[9] + 0x1000*TexCoords[1]) >> 12;
+ vertextrans->TexCoords[0] = (CurVertex[0]*TexMatrix[0] + CurVertex[1]*TexMatrix[4] + CurVertex[2]*TexMatrix[8] + 0x1000*TexCoords[0]) >> 20;
+ vertextrans->TexCoords[1] = (CurVertex[0]*TexMatrix[1] + CurVertex[1]*TexMatrix[5] + CurVertex[2]*TexMatrix[9] + 0x1000*TexCoords[1]) >> 20;
}
else
{
@@ -892,6 +901,71 @@ if (PolygonMode==0&&NumPolygons>440&&false)printf("raw vertex %d: %08X %08X | %0
}
}
+s32 CalculateLighting()
+{
+ if ((TexParam >> 30) == 2)
+ {
+ TexCoords[0] = (Normal[0]*TexMatrix[0] + Normal[1]*TexMatrix[4] + Normal[2]*TexMatrix[8] + 0x200*TexCoords[0]) >> 17;
+ TexCoords[1] = (Normal[0]*TexMatrix[1] + Normal[1]*TexMatrix[5] + Normal[2]*TexMatrix[9] + 0x200*TexCoords[1]) >> 17;
+ }
+
+ s32 normaltrans[3];
+ normaltrans[0] = (Normal[0]*VecMatrix[0] + Normal[1]*VecMatrix[4] + Normal[2]*VecMatrix[8]) >> 12;
+ normaltrans[1] = (Normal[0]*VecMatrix[1] + Normal[1]*VecMatrix[5] + Normal[2]*VecMatrix[9]) >> 12;
+ normaltrans[2] = (Normal[0]*VecMatrix[2] + Normal[1]*VecMatrix[6] + Normal[2]*VecMatrix[10]) >> 12;
+
+ VertexColor[0] = MatEmission[0];
+ VertexColor[1] = MatEmission[1];
+ VertexColor[2] = MatEmission[2];
+
+ s32 c = 0;
+ for (int i = 0; i < 4; i++)
+ {
+ if (!(CurPolygonAttr & (1<<i)))
+ continue;
+
+ s32 difflevel = (LightDirection[i][0]*normaltrans[0] +
+ LightDirection[i][1]*normaltrans[1] +
+ LightDirection[i][2]*normaltrans[2]) >> 10;
+ difflevel = -difflevel;
+ if (difflevel < 0) difflevel = 0;
+
+ s32 shinelevel = (-(LightDirection[i][0]>>1)*normaltrans[0] -
+ (LightDirection[i][1]>>1)*normaltrans[1] -
+ ((LightDirection[i][2]-0x200)>>1)*normaltrans[2]) >> 10;
+ if (shinelevel < 0) shinelevel = 0;
+ shinelevel = (shinelevel * shinelevel) >> 8;
+
+ // checkme
+ if (UseShininessTable)
+ {
+ if (shinelevel > 127) shinelevel = 127;
+ shinelevel = ShininessTable[shinelevel];
+ }
+
+ VertexColor[0] += ((((MatSpecular[0]+1) * (LightColor[i][0]+1) * (shinelevel+1)) - 1) >> 13);
+ VertexColor[0] += ((((MatDiffuse[0]+1) * (LightColor[i][0]+1) * (difflevel+1)) - 1) >> 13);
+ VertexColor[0] += ((((MatAmbient[0]+1) * (LightColor[i][0]+1)) - 1) >> 5);
+
+ VertexColor[1] += ((((MatSpecular[1]+1) * (LightColor[i][1]+1) * (shinelevel+1)) - 1) >> 13);
+ VertexColor[1] += ((((MatDiffuse[1]+1) * (LightColor[i][1]+1) * (difflevel+1)) - 1) >> 13);
+ VertexColor[1] += ((((MatAmbient[1]+1) * (LightColor[i][1]+1)) - 1) >> 5);
+
+ VertexColor[2] += ((((MatSpecular[2]+1) * (LightColor[i][2]+1) * (shinelevel+1)) - 1) >> 13);
+ VertexColor[2] += ((((MatDiffuse[2]+1) * (LightColor[i][2]+1) * (difflevel+1)) - 1) >> 13);
+ VertexColor[2] += ((((MatAmbient[2]+1) * (LightColor[i][2]+1)) - 1) >> 5);
+
+ if (VertexColor[0] > 31) VertexColor[0] = 31;
+ if (VertexColor[1] > 31) VertexColor[1] = 31;
+ if (VertexColor[2] > 31) VertexColor[2] = 31;
+
+ c++;
+ }
+
+ // checkme: cycle count
+ return c;
+}
+
void CmdFIFOWrite(CmdFIFOEntry& entry)
@@ -1033,6 +1107,8 @@ void ExecuteCommand()
}
memcpy(PosMatrix, PosMatrixStack[PosMatrixStackPointer], 16*4);
+ if (MatrixMode == 2)
+ memcpy(VecMatrix, PosMatrix, 16*4);
GXStat |= (1<<14);
ClipMatrixDirty = true;
}
@@ -1084,6 +1160,8 @@ void ExecuteCommand()
}
memcpy(PosMatrix, PosMatrixStack[addr], 16*4);
+ if (MatrixMode == 2)
+ memcpy(VecMatrix, PosMatrix, 16*4);
ClipMatrixDirty = true;
}
break;
@@ -1243,9 +1321,11 @@ void ExecuteCommand()
}
break;
- case 0x21:
- // TODO: more cycles if lights are enabled
- // TODO also texcoords if needed
+ case 0x21: // normal
+ Normal[0] = (s16)((ExecParams[0] & 0x000003FF) << 6) >> 6;
+ Normal[1] = (s16)((ExecParams[0] & 0x000FFC00) >> 4) >> 6;
+ Normal[2] = (s16)((ExecParams[0] & 0x3FF00000) >> 14) >> 6;
+ CycleCount += CalculateLighting();
break;
case 0x22: // texcoord
@@ -1309,6 +1389,66 @@ void ExecuteCommand()
TexPalette = ExecParams[0] & 0x1FFF;
break;
+ case 0x30: // diffuse/ambient material
+ MatDiffuse[0] = ExecParams[0] & 0x1F;
+ MatDiffuse[1] = (ExecParams[0] >> 5) & 0x1F;
+ MatDiffuse[2] = (ExecParams[0] >> 10) & 0x1F;
+ MatAmbient[0] = (ExecParams[0] >> 16) & 0x1F;
+ MatAmbient[1] = (ExecParams[0] >> 21) & 0x1F;
+ MatAmbient[2] = (ExecParams[0] >> 26) & 0x1F;
+ if (ExecParams[0] & 0x8000)
+ {
+ VertexColor[0] = MatDiffuse[0];
+ VertexColor[1] = MatDiffuse[1];
+ VertexColor[2] = MatDiffuse[2];
+ }
+ break;
+
+ case 0x31: // specular/emission material
+ MatSpecular[0] = ExecParams[0] & 0x1F;
+ MatSpecular[1] = (ExecParams[0] >> 5) & 0x1F;
+ MatSpecular[2] = (ExecParams[0] >> 10) & 0x1F;
+ MatEmission[0] = (ExecParams[0] >> 16) & 0x1F;
+ MatEmission[1] = (ExecParams[0] >> 21) & 0x1F;
+ MatEmission[2] = (ExecParams[0] >> 26) & 0x1F;
+ UseShininessTable = (ExecParams[0] & 0x8000) != 0;
+ break;
+
+ case 0x32: // light direction
+ {
+ u32 l = ExecParams[0] >> 30;
+ s16 dir[3];
+ dir[0] = (s16)((ExecParams[0] & 0x000003FF) << 6) >> 6;
+ dir[1] = (s16)((ExecParams[0] & 0x000FFC00) >> 4) >> 6;
+ dir[2] = (s16)((ExecParams[0] & 0x3FF00000) >> 14) >> 6;
+ LightDirection[l][0] = (dir[0]*VecMatrix[0] + dir[1]*VecMatrix[4] + dir[2]*VecMatrix[8]) >> 12;
+ LightDirection[l][1] = (dir[0]*VecMatrix[1] + dir[1]*VecMatrix[5] + dir[2]*VecMatrix[9]) >> 12;
+ LightDirection[l][2] = (dir[0]*VecMatrix[2] + dir[1]*VecMatrix[6] + dir[2]*VecMatrix[10]) >> 12;
+ }
+ break;
+
+ case 0x33: // light color
+ {
+ u32 l = ExecParams[0] >> 30;
+ LightColor[l][0] = ExecParams[0] & 0x1F;
+ LightColor[l][1] = (ExecParams[0] >> 5) & 0x1F;
+ LightColor[l][2] = (ExecParams[0] >> 10) & 0x1F;
+ }
+ break;
+
+ case 0x34: // shininess table
+ {
+ for (int i = 0; i < 128; i += 4)
+ {
+ u32 val = ExecParams[i >> 2];
+ ShininessTable[i + 0] = val & 0xFF;
+ ShininessTable[i + 1] = (val >> 8) & 0xFF;
+ ShininessTable[i + 2] = (val >> 16) & 0xFF;
+ ShininessTable[i + 3] = val >> 24;
+ }
+ }
+ break;
+
case 0x40: // begin polygons
PolygonMode = ExecParams[0] & 0x3;
VertexNum = 0;