Clean up most (99.99%) of the tab/space mismatches in the VideoSoftware project.

Got rid of trailing spaces that were unnecessary too.

Also update the license header for this project. We don't use SVN anymore.
This commit is contained in:
Lioncash 2013-04-13 23:54:02 -04:00
parent 48927c17d2
commit 7ab0cca645
51 changed files with 4633 additions and 4567 deletions

View File

@ -12,7 +12,7 @@
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// Official Git repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "VideoCommon.h"
@ -29,67 +29,67 @@
void InitBPMemory()
{
memset(&bpmem, 0, sizeof(bpmem));
bpmem.bpMask = 0xFFFFFF;
memset(&bpmem, 0, sizeof(bpmem));
bpmem.bpMask = 0xFFFFFF;
}
void SWLoadBPReg(u32 value)
{
//handle the mask register
//handle the mask register
int address = value >> 24;
int oldval = ((u32*)&bpmem)[address];
int newval = (oldval & ~bpmem.bpMask) | (value & bpmem.bpMask);
((u32*)&bpmem)[address] = newval;
((u32*)&bpmem)[address] = newval;
//reset the mask register
if (address != 0xFE)
bpmem.bpMask = 0xFFFFFF;
SWBPWritten(address, newval);
SWBPWritten(address, newval);
}
void SWBPWritten(int address, int newvalue)
{
switch (address)
switch (address)
{
case BPMEM_SCISSORTL:
case BPMEM_SCISSORBR:
case BPMEM_SCISSOROFFSET:
Rasterizer::SetScissor();
break;
case BPMEM_SCISSORTL:
case BPMEM_SCISSORBR:
case BPMEM_SCISSOROFFSET:
Rasterizer::SetScissor();
break;
case BPMEM_SETDRAWDONE: // This is called when the game is done drawing (eg: like in DX: Begin(); Draw(); End();)
switch (bpmem.drawdone & 0xFF)
{
case 0x02:
SWPixelEngine::SetFinish(); // may generate interrupt
DEBUG_LOG(VIDEO, "GXSetDrawDone SetPEFinish (value: 0x%02X)", (bpmem.drawdone & 0xFFFF));
break;
{
case 0x02:
SWPixelEngine::SetFinish(); // may generate interrupt
DEBUG_LOG(VIDEO, "GXSetDrawDone SetPEFinish (value: 0x%02X)", (bpmem.drawdone & 0xFFFF));
break;
default:
WARN_LOG(VIDEO, "GXSetDrawDone ??? (value 0x%02X)", (bpmem.drawdone & 0xFFFF));
break;
}
break;
default:
WARN_LOG(VIDEO, "GXSetDrawDone ??? (value 0x%02X)", (bpmem.drawdone & 0xFFFF));
break;
}
break;
case BPMEM_PE_TOKEN_ID: // Pixel Engine Token ID
DEBUG_LOG(VIDEO, "SetPEToken 0x%04x", (bpmem.petoken & 0xFFFF));
SWPixelEngine::SetToken(static_cast<u16>(bpmem.petokenint & 0xFFFF), false);
break;
case BPMEM_PE_TOKEN_INT_ID: // Pixel Engine Interrupt Token ID
DEBUG_LOG(VIDEO, "SetPEToken + INT 0x%04x", (bpmem.petokenint & 0xFFFF));
SWPixelEngine::SetToken(static_cast<u16>(bpmem.petokenint & 0xFFFF), true);
break;
case BPMEM_TRIGGER_EFB_COPY:
EfbCopy::CopyEfb();
break;
case BPMEM_CLEARBBOX1:
SWPixelEngine::pereg.boxRight = newvalue >> 10;
SWPixelEngine::pereg.boxLeft = newvalue & 0x3ff;
break;
case BPMEM_CLEARBBOX2:
SWPixelEngine::pereg.boxBottom = newvalue >> 10;
SWPixelEngine::pereg.boxTop = newvalue & 0x3ff;
break;
DEBUG_LOG(VIDEO, "SetPEToken 0x%04x", (bpmem.petoken & 0xFFFF));
SWPixelEngine::SetToken(static_cast<u16>(bpmem.petokenint & 0xFFFF), false);
break;
case BPMEM_PE_TOKEN_INT_ID: // Pixel Engine Interrupt Token ID
DEBUG_LOG(VIDEO, "SetPEToken + INT 0x%04x", (bpmem.petokenint & 0xFFFF));
SWPixelEngine::SetToken(static_cast<u16>(bpmem.petokenint & 0xFFFF), true);
break;
case BPMEM_TRIGGER_EFB_COPY:
EfbCopy::CopyEfb();
break;
case BPMEM_CLEARBBOX1:
SWPixelEngine::pereg.boxRight = newvalue >> 10;
SWPixelEngine::pereg.boxLeft = newvalue & 0x3ff;
break;
case BPMEM_CLEARBBOX2:
SWPixelEngine::pereg.boxBottom = newvalue >> 10;
SWPixelEngine::pereg.boxTop = newvalue & 0x3ff;
break;
case BPMEM_CLEAR_PIXEL_PERF:
// TODO: I didn't test if the value written to this register affects the amount of cleared registers
SWPixelEngine::pereg.perfZcompInputZcomplocLo = 0;
@ -105,16 +105,16 @@ void SWBPWritten(int address, int newvalue)
SWPixelEngine::pereg.perfEfbCopyClocksLo = 0;
SWPixelEngine::pereg.perfEfbCopyClocksHi = 0;
break;
case BPMEM_LOADTLUT0: // This one updates bpmem.tlutXferSrc, no need to do anything here.
case BPMEM_LOADTLUT0: // This one updates bpmem.tlutXferSrc, no need to do anything here.
break;
case BPMEM_LOADTLUT1: // Load a Texture Look Up Table
{
u32 tlutTMemAddr = (newvalue & 0x3FF) << 9;
u32 tlutXferCount = (newvalue & 0x1FFC00) >> 5;
{
u32 tlutTMemAddr = (newvalue & 0x3FF) << 9;
u32 tlutXferCount = (newvalue & 0x1FFC00) >> 5;
u8 *ptr = 0;
// TODO - figure out a cleaner way.
// TODO - figure out a cleaner way.
if (Core::g_CoreStartupParameter.bWii)
ptr = Memory::GetPointer(bpmem.tmem_config.tlut_src << 5);
else
@ -125,7 +125,7 @@ void SWBPWritten(int address, int newvalue)
else
PanicAlert("Invalid palette pointer %08x %08x %08x", bpmem.tmem_config.tlut_src, bpmem.tmem_config.tlut_src << 5, (bpmem.tmem_config.tlut_src & 0xFFFFF)<< 5);
break;
}
}
case BPMEM_PRELOAD_MODE:
if (newvalue != 0)
@ -166,36 +166,36 @@ void SWBPWritten(int address, int newvalue)
}
break;
case BPMEM_TEV_REGISTER_L: // Reg 1
case BPMEM_TEV_REGISTER_L: // Reg 1
case BPMEM_TEV_REGISTER_L+2: // Reg 2
case BPMEM_TEV_REGISTER_L+4: // Reg 3
case BPMEM_TEV_REGISTER_L+6: // Reg 4
{
int regNum = (address >> 1 ) & 0x3;
ColReg& reg = bpmem.tevregs[regNum].low;
bool konst = reg.type;
ColReg& reg = bpmem.tevregs[regNum].low;
bool konst = reg.type;
Rasterizer::SetTevReg(regNum, Tev::ALP_C, konst, reg.b); // A
Rasterizer::SetTevReg(regNum, Tev::RED_C, konst, reg.a); // R
Rasterizer::SetTevReg(regNum, Tev::RED_C, konst, reg.a); // R
break;
}
case BPMEM_TEV_REGISTER_H: // Reg 1
case BPMEM_TEV_REGISTER_H: // Reg 1
case BPMEM_TEV_REGISTER_H+2: // Reg 2
case BPMEM_TEV_REGISTER_H+4: // Reg 3
case BPMEM_TEV_REGISTER_H+6: // Reg 4
{
int regNum = (address >> 1 ) & 0x3;
ColReg& reg = bpmem.tevregs[regNum].high;
bool konst = reg.type;
ColReg& reg = bpmem.tevregs[regNum].high;
bool konst = reg.type;
Rasterizer::SetTevReg(regNum, Tev::GRN_C, konst, reg.b); // G
Rasterizer::SetTevReg(regNum, Tev::BLU_C, konst, reg.a); // B
Rasterizer::SetTevReg(regNum, Tev::GRN_C, konst, reg.b); // G
Rasterizer::SetTevReg(regNum, Tev::BLU_C, konst, reg.a); // B
break;
}
}
}
}

View File

@ -12,7 +12,7 @@
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// Official Git repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _BPMEMLOADER_H_

View File

@ -22,10 +22,10 @@
void SWLoadCPReg(u32 sub_cmd, u32 value)
{
switch (sub_cmd & 0xF0)
switch (sub_cmd & 0xF0)
{
case 0x30:
MatrixIndexA.Hex = value;
MatrixIndexA.Hex = value;
break;
case 0x40:
@ -60,7 +60,7 @@ void SWLoadCPReg(u32 sub_cmd, u32 value)
// Pointers to vertex arrays in GC RAM
case 0xA0:
arraybases[sub_cmd & 0xF] = value;
cached_arraybases[sub_cmd & 0xF] = Memory::GetPointer(value);
cached_arraybases[sub_cmd & 0xF] = Memory::GetPointer(value);
break;
case 0xB0:

View File

@ -12,7 +12,7 @@
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// Official Git repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _CPMEMLOADER_H_

View File

@ -12,7 +12,7 @@
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// Official Git repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
/*
@ -62,8 +62,8 @@ namespace Clipper
float m_ViewOffset[2];
OutputVertexData ClippedVertices[NUM_CLIPPED_VERTICES];
OutputVertexData *Vertices[NUM_INDICES];
OutputVertexData ClippedVertices[NUM_CLIPPED_VERTICES];
OutputVertexData *Vertices[NUM_INDICES];
void DoState(PointerWrap &p)
{
@ -72,94 +72,94 @@ namespace Clipper
ClippedVertices[i].DoState(p);
}
void Init()
{
for (int i = 0; i < NUM_CLIPPED_VERTICES; ++i)
Vertices[i+3] = &ClippedVertices[i];
}
void Init()
{
for (int i = 0; i < NUM_CLIPPED_VERTICES; ++i)
Vertices[i+3] = &ClippedVertices[i];
}
void SetViewOffset()
{
m_ViewOffset[0] = swxfregs.viewport.xOrig - 342;
m_ViewOffset[1] = swxfregs.viewport.yOrig - 342;
}
void SetViewOffset()
{
m_ViewOffset[0] = swxfregs.viewport.xOrig - 342;
m_ViewOffset[1] = swxfregs.viewport.yOrig - 342;
}
enum {
SKIP_FLAG = -1,
CLIP_POS_X_BIT = 0x01,
CLIP_NEG_X_BIT = 0x02,
CLIP_POS_Y_BIT = 0x04,
CLIP_NEG_Y_BIT = 0x08,
CLIP_POS_Z_BIT = 0x10,
CLIP_NEG_Z_BIT = 0x20
};
static inline int CalcClipMask(OutputVertexData *v)
{
int cmask = 0;
Vec4 pos = v->projectedPosition;
if (pos.w - pos.x < 0) cmask |= CLIP_POS_X_BIT;
if (pos.x + pos.w < 0) cmask |= CLIP_NEG_X_BIT;
if (pos.w - pos.y < 0) cmask |= CLIP_POS_Y_BIT;
if (pos.y + pos.w < 0) cmask |= CLIP_NEG_Y_BIT;
if (pos.w * pos.z > 0) cmask |= CLIP_POS_Z_BIT;
if (pos.z + pos.w < 0) cmask |= CLIP_NEG_Z_BIT;
return cmask;
}
enum {
SKIP_FLAG = -1,
CLIP_POS_X_BIT = 0x01,
CLIP_NEG_X_BIT = 0x02,
CLIP_POS_Y_BIT = 0x04,
CLIP_NEG_Y_BIT = 0x08,
CLIP_POS_Z_BIT = 0x10,
CLIP_NEG_Z_BIT = 0x20
};
static inline void AddInterpolatedVertex(float t, int out, int in, int& numVertices)
{
Vertices[numVertices]->Lerp(t, Vertices[out], Vertices[in]);
numVertices++;
}
static inline int CalcClipMask(OutputVertexData *v)
{
int cmask = 0;
Vec4 pos = v->projectedPosition;
if (pos.w - pos.x < 0) cmask |= CLIP_POS_X_BIT;
if (pos.x + pos.w < 0) cmask |= CLIP_NEG_X_BIT;
if (pos.w - pos.y < 0) cmask |= CLIP_POS_Y_BIT;
if (pos.y + pos.w < 0) cmask |= CLIP_NEG_Y_BIT;
if (pos.w * pos.z > 0) cmask |= CLIP_POS_Z_BIT;
if (pos.z + pos.w < 0) cmask |= CLIP_NEG_Z_BIT;
return cmask;
}
#define DIFFERENT_SIGNS(x,y) ((x <= 0 && y > 0) || (x > 0 && y <= 0))
static inline void AddInterpolatedVertex(float t, int out, int in, int& numVertices)
{
Vertices[numVertices]->Lerp(t, Vertices[out], Vertices[in]);
numVertices++;
}
#define CLIP_DOTPROD(I, A, B, C, D) \
(Vertices[I]->projectedPosition.x * A + Vertices[I]->projectedPosition.y * B + Vertices[I]->projectedPosition.z * C + Vertices[I]->projectedPosition.w * D)
#define DIFFERENT_SIGNS(x,y) ((x <= 0 && y > 0) || (x > 0 && y <= 0))
#define POLY_CLIP( PLANE_BIT, A, B, C, D ) \
{ \
if (mask & PLANE_BIT) { \
int idxPrev = inlist[0]; \
float dpPrev = CLIP_DOTPROD(idxPrev, A, B, C, D ); \
int outcount = 0; \
\
inlist[n] = inlist[0]; \
for (int j = 1; j <= n; j++) { \
int idx = inlist[j]; \
float dp = CLIP_DOTPROD(idx, A, B, C, D ); \
if (dpPrev >= 0) { \
outlist[outcount++] = idxPrev; \
} \
\
if (DIFFERENT_SIGNS(dp, dpPrev)) { \
if (dp < 0) { \
float t = dp / (dp - dpPrev); \
AddInterpolatedVertex(t, idx, idxPrev, numVertices); \
} else { \
float t = dpPrev / (dpPrev - dp); \
AddInterpolatedVertex(t, idxPrev, idx, numVertices); \
} \
outlist[outcount++] = numVertices - 1; \
} \
\
idxPrev = idx; \
dpPrev = dp; \
} \
\
if (outcount < 3) \
continue; \
\
{ \
int *tmp = inlist; \
inlist = outlist; \
outlist = tmp; \
n = outcount; \
} \
} \
}
#define CLIP_DOTPROD(I, A, B, C, D) \
(Vertices[I]->projectedPosition.x * A + Vertices[I]->projectedPosition.y * B + Vertices[I]->projectedPosition.z * C + Vertices[I]->projectedPosition.w * D)
#define POLY_CLIP( PLANE_BIT, A, B, C, D ) \
{ \
if (mask & PLANE_BIT) { \
int idxPrev = inlist[0]; \
float dpPrev = CLIP_DOTPROD(idxPrev, A, B, C, D ); \
int outcount = 0; \
\
inlist[n] = inlist[0]; \
for (int j = 1; j <= n; j++) { \
int idx = inlist[j]; \
float dp = CLIP_DOTPROD(idx, A, B, C, D ); \
if (dpPrev >= 0) { \
outlist[outcount++] = idxPrev; \
} \
\
if (DIFFERENT_SIGNS(dp, dpPrev)) { \
if (dp < 0) { \
float t = dp / (dp - dpPrev); \
AddInterpolatedVertex(t, idx, idxPrev, numVertices); \
} else { \
float t = dpPrev / (dpPrev - dp); \
AddInterpolatedVertex(t, idxPrev, idx, numVertices); \
} \
outlist[outcount++] = numVertices - 1; \
} \
\
idxPrev = idx; \
dpPrev = dp; \
} \
\
if (outcount < 3) \
continue; \
\
{ \
int *tmp = inlist; \
inlist = outlist; \
outlist = tmp; \
n = outcount; \
} \
} \
}
#define LINE_CLIP(PLANE_BIT, A, B, C, D ) \
{ \
@ -173,63 +173,63 @@ namespace Clipper
return; \
\
if (neg_dp1) { \
float t = dp1 / (dp1 - dp0); \
float t = dp1 / (dp1 - dp0); \
if (t > t1) t1 = t; \
} else if (neg_dp0) { \
float t = dp0 / (dp0 - dp1); \
float t = dp0 / (dp0 - dp1); \
if (t > t0) t0 = t; \
} \
} \
}
void ClipTriangle(int *indices, int &numIndices)
{
int mask = 0;
mask |= CalcClipMask(Vertices[0]);
mask |= CalcClipMask(Vertices[1]);
mask |= CalcClipMask(Vertices[2]);
void ClipTriangle(int *indices, int &numIndices)
{
int mask = 0;
if (mask != 0)
{
for(int i = 0; i < 3; i += 3)
{
int vlist[2][2*6+1];
int *inlist = vlist[0], *outlist = vlist[1];
int n = 3;
int numVertices = 3;
mask |= CalcClipMask(Vertices[0]);
mask |= CalcClipMask(Vertices[1]);
mask |= CalcClipMask(Vertices[2]);
inlist[0] = 0;
inlist[1] = 1;
inlist[2] = 2;
if (mask != 0)
{
for(int i = 0; i < 3; i += 3)
{
int vlist[2][2*6+1];
int *inlist = vlist[0], *outlist = vlist[1];
int n = 3;
int numVertices = 3;
// mark this triangle as unused in case it should be completely
// clipped
indices[0] = SKIP_FLAG;
indices[1] = SKIP_FLAG;
indices[2] = SKIP_FLAG;
inlist[0] = 0;
inlist[1] = 1;
inlist[2] = 2;
POLY_CLIP(CLIP_POS_X_BIT, -1, 0, 0, 1);
POLY_CLIP(CLIP_NEG_X_BIT, 1, 0, 0, 1);
POLY_CLIP(CLIP_POS_Y_BIT, 0, -1, 0, 1);
POLY_CLIP(CLIP_NEG_Y_BIT, 0, 1, 0, 1);
POLY_CLIP(CLIP_POS_Z_BIT, 0, 0, 0, 1);
POLY_CLIP(CLIP_NEG_Z_BIT, 0, 0, 1, 1);
// mark this triangle as unused in case it should be completely
// clipped
indices[0] = SKIP_FLAG;
indices[1] = SKIP_FLAG;
indices[2] = SKIP_FLAG;
INCSTAT(swstats.thisFrame.numTrianglesClipped);
POLY_CLIP(CLIP_POS_X_BIT, -1, 0, 0, 1);
POLY_CLIP(CLIP_NEG_X_BIT, 1, 0, 0, 1);
POLY_CLIP(CLIP_POS_Y_BIT, 0, -1, 0, 1);
POLY_CLIP(CLIP_NEG_Y_BIT, 0, 1, 0, 1);
POLY_CLIP(CLIP_POS_Z_BIT, 0, 0, 0, 1);
POLY_CLIP(CLIP_NEG_Z_BIT, 0, 0, 1, 1);
// transform the poly in inlist into triangles
indices[0] = inlist[0];
indices[1] = inlist[1];
indices[2] = inlist[2];
for (int j = 3; j < n; ++j) {
indices[numIndices++] = inlist[0];
indices[numIndices++] = inlist[j - 1];
indices[numIndices++] = inlist[j];
}
}
}
}
INCSTAT(swstats.thisFrame.numTrianglesClipped);
// transform the poly in inlist into triangles
indices[0] = inlist[0];
indices[1] = inlist[1];
indices[2] = inlist[2];
for (int j = 3; j < n; ++j) {
indices[numIndices++] = inlist[0];
indices[numIndices++] = inlist[j - 1];
indices[numIndices++] = inlist[j];
}
}
}
}
void ClipLine(int *indices)
{
@ -267,59 +267,61 @@ namespace Clipper
int numVertices = 2;
if (clip_mask[0]) {
if (clip_mask[0])
{
indices[0] = numVertices;
AddInterpolatedVertex(t0, 0, 1, numVertices);
}
if (clip_mask[1]) {
if (clip_mask[1])
{
indices[1] = numVertices;
AddInterpolatedVertex(t1, 1, 0, numVertices);
}
}
void ProcessTriangle(OutputVertexData *v0, OutputVertexData *v1, OutputVertexData *v2)
{
INCSTAT(swstats.thisFrame.numTrianglesIn)
void ProcessTriangle(OutputVertexData *v0, OutputVertexData *v1, OutputVertexData *v2)
{
INCSTAT(swstats.thisFrame.numTrianglesIn)
bool backface;
bool backface;
if(!CullTest(v0, v1, v2, backface))
return;
int indices[NUM_INDICES] = { 0, 1, 2, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG,
SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG,
SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG };
int numIndices = 3;
if(!CullTest(v0, v1, v2, backface))
return;
if (backface)
{
Vertices[0] = v0;
Vertices[1] = v2;
Vertices[2] = v1;
}
else
{
Vertices[0] = v0;
Vertices[1] = v1;
Vertices[2] = v2;
}
int indices[NUM_INDICES] = { 0, 1, 2, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG,
SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG,
SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG };
int numIndices = 3;
ClipTriangle(indices, numIndices);
if (backface)
{
Vertices[0] = v0;
Vertices[1] = v2;
Vertices[2] = v1;
}
else
{
Vertices[0] = v0;
Vertices[1] = v1;
Vertices[2] = v2;
}
for(int i = 0; i+3 <= numIndices; i+=3)
{
ClipTriangle(indices, numIndices);
for(int i = 0; i+3 <= numIndices; i+=3)
{
_assert_(i < NUM_INDICES);
if(indices[i] != SKIP_FLAG)
{
PerspectiveDivide(Vertices[indices[i]]);
PerspectiveDivide(Vertices[indices[i+1]]);
PerspectiveDivide(Vertices[indices[i+2]]);
{
PerspectiveDivide(Vertices[indices[i]]);
PerspectiveDivide(Vertices[indices[i+1]]);
PerspectiveDivide(Vertices[indices[i+2]]);
Rasterizer::DrawTriangleFrontFace(Vertices[indices[i]], Vertices[indices[i+1]], Vertices[indices[i+2]]);
}
}
}
Rasterizer::DrawTriangleFrontFace(Vertices[indices[i]], Vertices[indices[i+1]], Vertices[indices[i+2]]);
}
}
}
void CopyVertex(OutputVertexData *dst, OutputVertexData *src, float dx, float dy, unsigned int sOffset)
{
@ -343,7 +345,7 @@ namespace Clipper
int indices[4] = { 0, 1, SKIP_FLAG, SKIP_FLAG };
Vertices[0] = lineV0;
Vertices[1] = lineV1;
Vertices[1] = lineV1;
// point to a valid vertex to store to when clipping
Vertices[2] = &ClippedVertices[17];
@ -356,7 +358,7 @@ namespace Clipper
OutputVertexData *v1 = Vertices[indices[1]];
PerspectiveDivide(v0);
PerspectiveDivide(v1);
PerspectiveDivide(v1);
float dx = v1->screenPosition.x - v0->screenPosition.x;
float dy = v1->screenPosition.y - v0->screenPosition.y;
@ -393,57 +395,57 @@ namespace Clipper
Rasterizer::DrawTriangleFrontFace(&triangle[0], &triangle[1], &triangle[2]);
}
}
bool CullTest(OutputVertexData *v0, OutputVertexData *v1, OutputVertexData *v2, bool &backface)
{
int mask = CalcClipMask(v0);
mask &= CalcClipMask(v1);
mask &= CalcClipMask(v2);
if(mask)
{
INCSTAT(swstats.thisFrame.numTrianglesRejected)
return false;
}
bool CullTest(OutputVertexData *v0, OutputVertexData *v1, OutputVertexData *v2, bool &backface)
{
int mask = CalcClipMask(v0);
mask &= CalcClipMask(v1);
mask &= CalcClipMask(v2);
float x0 = v0->projectedPosition.x;
float x1 = v1->projectedPosition.x;
float x2 = v2->projectedPosition.x;
float y1 = v1->projectedPosition.y;
float y0 = v0->projectedPosition.y;
float y2 = v2->projectedPosition.y;
float w0 = v0->projectedPosition.w;
float w1 = v1->projectedPosition.w;
float w2 = v2->projectedPosition.w;
if(mask)
{
INCSTAT(swstats.thisFrame.numTrianglesRejected)
return false;
}
float normalZDir = (x0*w2 - x2*w0)*y1 + (x2*y0 - x0*y2)*w1 + (y2*w0 - y0*w2)*x1;
float x0 = v0->projectedPosition.x;
float x1 = v1->projectedPosition.x;
float x2 = v2->projectedPosition.x;
float y1 = v1->projectedPosition.y;
float y0 = v0->projectedPosition.y;
float y2 = v2->projectedPosition.y;
float w0 = v0->projectedPosition.w;
float w1 = v1->projectedPosition.w;
float w2 = v2->projectedPosition.w;
backface = normalZDir <= 0.0f;
float normalZDir = (x0*w2 - x2*w0)*y1 + (x2*y0 - x0*y2)*w1 + (y2*w0 - y0*w2)*x1;
if ((bpmem.genMode.cullmode & 1) && !backface) // cull frontfacing
{
INCSTAT(swstats.thisFrame.numTrianglesCulled)
return false;
}
backface = normalZDir <= 0.0f;
if ((bpmem.genMode.cullmode & 2) && backface) // cull backfacing
{
INCSTAT(swstats.thisFrame.numTrianglesCulled)
return false;
}
if ((bpmem.genMode.cullmode & 1) && !backface) // cull frontfacing
{
INCSTAT(swstats.thisFrame.numTrianglesCulled)
return false;
}
return true;
}
if ((bpmem.genMode.cullmode & 2) && backface) // cull backfacing
{
INCSTAT(swstats.thisFrame.numTrianglesCulled)
return false;
}
void PerspectiveDivide(OutputVertexData *vertex)
{
Vec4 &projected = vertex->projectedPosition;
Vec3 &screen = vertex->screenPosition;
return true;
}
void PerspectiveDivide(OutputVertexData *vertex)
{
Vec4 &projected = vertex->projectedPosition;
Vec3 &screen = vertex->screenPosition;
float wInverse = 1.0f/projected.w;
screen.x = projected.x * wInverse * swxfregs.viewport.wd + m_ViewOffset[0];
screen.y = projected.y * wInverse * swxfregs.viewport.ht + m_ViewOffset[1];
screen.z = projected.z * wInverse * swxfregs.viewport.zRange + swxfregs.viewport.farZ;
}
float wInverse = 1.0f/projected.w;
screen.x = projected.x * wInverse * swxfregs.viewport.wd + m_ViewOffset[0];
screen.y = projected.y * wInverse * swxfregs.viewport.ht + m_ViewOffset[1];
screen.z = projected.z * wInverse * swxfregs.viewport.zRange + swxfregs.viewport.farZ;
}
}

View File

@ -12,7 +12,7 @@
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// Official Git repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _CLIPPER_H_
@ -26,17 +26,17 @@
namespace Clipper
{
void Init();
void Init();
void SetViewOffset();
void SetViewOffset();
void ProcessTriangle(OutputVertexData *v0, OutputVertexData *v1, OutputVertexData *v2);
void ProcessTriangle(OutputVertexData *v0, OutputVertexData *v1, OutputVertexData *v2);
void ProcessLine(OutputVertexData *v0, OutputVertexData *v1);
bool CullTest(OutputVertexData *v0, OutputVertexData *v1, OutputVertexData *v2, bool &backface);
bool CullTest(OutputVertexData *v0, OutputVertexData *v1, OutputVertexData *v2, bool &backface);
void PerspectiveDivide(OutputVertexData *vertex);
void PerspectiveDivide(OutputVertexData *vertex);
void DoState(PointerWrap &p);
}

View File

@ -12,7 +12,7 @@
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// Official Git repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "Common.h"
@ -46,57 +46,57 @@ int BufferBase[NumObjectBuffers];
void Init()
{
for (int i = 0; i < NumObjectBuffers; i++)
{
memset(ObjectBuffer[i], 0, sizeof(ObjectBuffer[i]));
DrawnToBuffer[i] = false;
ObjectBufferName[i] = 0;
for (int i = 0; i < NumObjectBuffers; i++)
{
memset(ObjectBuffer[i], 0, sizeof(ObjectBuffer[i]));
DrawnToBuffer[i] = false;
ObjectBufferName[i] = 0;
BufferBase[i] = 0;
}
}
}
void SaveTexture(const char* filename, u32 texmap, s32 mip)
{
FourTexUnits& texUnit = bpmem.tex[(texmap >> 2) & 1];
u8 subTexmap = texmap & 3;
FourTexUnits& texUnit = bpmem.tex[(texmap >> 2) & 1];
u8 subTexmap = texmap & 3;
TexImage0& ti0 = texUnit.texImage0[subTexmap];
TexImage0& ti0 = texUnit.texImage0[subTexmap];
u32 width = ti0.width + 1;
u32 height = ti0.height + 1;
u8 *data = new u8[width * height * 4];
GetTextureBGRA(data, texmap, mip, width, height);
(void)SaveTGA(filename, width, height, data);
GetTextureBGRA(data, texmap, mip, width, height);
delete []data;
(void)SaveTGA(filename, width, height, data);
delete []data;
}
void GetTextureBGRA(u8 *dst, u32 texmap, s32 mip, u32 width, u32 height)
{
u8 sample[4];
u8 sample[4];
for (u32 y = 0; y < height; y++)
for (u32 y = 0; y < height; y++)
{
for (u32 x = 0; x < width; x++)
for (u32 x = 0; x < width; x++)
{
TextureSampler::SampleMip(x << 7, y << 7, mip, false, texmap, sample);
TextureSampler::SampleMip(x << 7, y << 7, mip, false, texmap, sample);
// RGBA to BGRA
*(dst++) = sample[2];
*(dst++) = sample[1];
*(dst++) = sample[0];
*(dst++) = sample[3];
}
*(dst++) = sample[2];
*(dst++) = sample[1];
*(dst++) = sample[0];
*(dst++) = sample[3];
}
}
}
s32 GetMaxTextureLod(u32 texmap)
{
FourTexUnits& texUnit = bpmem.tex[(texmap >> 2) & 1];
u8 subTexmap = texmap & 3;
u8 subTexmap = texmap & 3;
u8 maxLod = texUnit.texMode1[subTexmap].max_lod;
u8 mip = maxLod >> 4;
@ -110,9 +110,9 @@ s32 GetMaxTextureLod(u32 texmap)
void DumpActiveTextures()
{
for (unsigned int stageNum = 0; stageNum < bpmem.genMode.numindstages; stageNum++)
{
u32 texmap = bpmem.tevindref.getTexMap(stageNum);
for (unsigned int stageNum = 0; stageNum < bpmem.genMode.numindstages; stageNum++)
{
u32 texmap = bpmem.tevindref.getTexMap(stageNum);
s32 maxLod = GetMaxTextureLod(texmap);
for (s32 mip = 0; mip <= maxLod; ++mip)
@ -121,90 +121,96 @@ void DumpActiveTextures()
File::GetUserPath(D_DUMPTEXTURES_IDX).c_str(),
swstats.thisFrame.numDrawnObjects, stageNum, texmap, mip).c_str(), texmap, mip);
}
}
}
for (unsigned int stageNum = 0; stageNum <= bpmem.genMode.numtevstages; stageNum++)
{
int stageNum2 = stageNum >> 1;
int stageOdd = stageNum&1;
TwoTevStageOrders &order = bpmem.tevorders[stageNum2];
for (unsigned int stageNum = 0; stageNum <= bpmem.genMode.numtevstages; stageNum++)
{
int stageNum2 = stageNum >> 1;
int stageOdd = stageNum&1;
TwoTevStageOrders &order = bpmem.tevorders[stageNum2];
int texmap = order.getTexMap(stageOdd);
int texmap = order.getTexMap(stageOdd);
s32 maxLod = GetMaxTextureLod(texmap);
s32 maxLod = GetMaxTextureLod(texmap);
for (s32 mip = 0; mip <= maxLod; ++mip)
{
SaveTexture(StringFromFormat("%star%i_stage%i_map%i_mip%i.tga",
File::GetUserPath(D_DUMPTEXTURES_IDX).c_str(),
swstats.thisFrame.numDrawnObjects, stageNum, texmap, mip).c_str(), texmap, mip);
}
}
}
}
void DumpEfb(const char* filename)
{
u8 *data = new u8[EFB_WIDTH * EFB_HEIGHT * 4];
u8 *writePtr = data;
u8 sample[4];
u8 *data = new u8[EFB_WIDTH * EFB_HEIGHT * 4];
u8 *writePtr = data;
u8 sample[4];
for (int y = 0; y < EFB_HEIGHT; y++)
for (int x = 0; x < EFB_WIDTH; x++) {
EfbInterface::GetColor(x, y, sample);
// ABGR to BGRA
*(writePtr++) = sample[1];
*(writePtr++) = sample[2];
*(writePtr++) = sample[3];
*(writePtr++) = sample[0];
}
for (int y = 0; y < EFB_HEIGHT; y++)
{
for (int x = 0; x < EFB_WIDTH; x++)
{
EfbInterface::GetColor(x, y, sample);
// ABGR to BGRA
*(writePtr++) = sample[1];
*(writePtr++) = sample[2];
*(writePtr++) = sample[3];
*(writePtr++) = sample[0];
}
}
(void)SaveTGA(filename, EFB_WIDTH, EFB_HEIGHT, data);
(void)SaveTGA(filename, EFB_WIDTH, EFB_HEIGHT, data);
delete []data;
delete []data;
}
void DumpDepth(const char* filename)
{
u8 *data = new u8[EFB_WIDTH * EFB_HEIGHT * 4];
u8 *writePtr = data;
u8 *data = new u8[EFB_WIDTH * EFB_HEIGHT * 4];
u8 *writePtr = data;
for (int y = 0; y < EFB_HEIGHT; y++)
for (int x = 0; x < EFB_WIDTH; x++) {
u32 depth = EfbInterface::GetDepth(x, y);
// depth to bgra
*(writePtr++) = (depth >> 16) & 0xff;
*(writePtr++) = (depth >> 8) & 0xff;
*(writePtr++) = depth & 0xff;
*(writePtr++) = 255;
}
for (int y = 0; y < EFB_HEIGHT; y++)
{
for (int x = 0; x < EFB_WIDTH; x++)
{
u32 depth = EfbInterface::GetDepth(x, y);
// depth to bgra
*(writePtr++) = (depth >> 16) & 0xff;
*(writePtr++) = (depth >> 8) & 0xff;
*(writePtr++) = depth & 0xff;
*(writePtr++) = 255;
}
}
(void)SaveTGA(filename, EFB_WIDTH, EFB_HEIGHT, data);
(void)SaveTGA(filename, EFB_WIDTH, EFB_HEIGHT, data);
delete []data;
delete []data;
}
void DrawObjectBuffer(s16 x, s16 y, u8 *color, int bufferBase, int subBuffer, const char *name)
{
int buffer = bufferBase + subBuffer;
int buffer = bufferBase + subBuffer;
u32 offset = (x + y * EFB_WIDTH) * 4;
u8 *dst = (u8*)&ObjectBuffer[buffer][offset];
*(dst++) = color[2];
*(dst++) = color[1];
*(dst++) = color[0];
*(dst++) = color[3];
u8 *dst = (u8*)&ObjectBuffer[buffer][offset];
*(dst++) = color[2];
*(dst++) = color[1];
*(dst++) = color[0];
*(dst++) = color[3];
DrawnToBuffer[buffer] = true;
ObjectBufferName[buffer] = name;
DrawnToBuffer[buffer] = true;
ObjectBufferName[buffer] = name;
BufferBase[buffer] = bufferBase;
}
void DrawTempBuffer(u8 *color, int buffer)
{
u8 *dst = (u8*)&TempBuffer[buffer];
*(dst++) = color[2];
*(dst++) = color[1];
*(dst++) = color[0];
*(dst++) = color[3];
*(dst++) = color[2];
*(dst++) = color[1];
*(dst++) = color[0];
*(dst++) = color[3];
}
void CopyTempBuffer(s16 x, s16 y, int bufferBase, int subBuffer, const char *name)
@ -215,69 +221,69 @@ void CopyTempBuffer(s16 x, s16 y, int bufferBase, int subBuffer, const char *nam
ObjectBuffer[buffer][offset] = TempBuffer[buffer];
DrawnToBuffer[buffer] = true;
ObjectBufferName[buffer] = name;
ObjectBufferName[buffer] = name;
BufferBase[buffer] = bufferBase;
}
void OnObjectBegin()
{
if (!g_bSkipCurrentFrame)
{
if (g_SWVideoConfig.bDumpTextures && swstats.thisFrame.numDrawnObjects >= g_SWVideoConfig.drawStart && swstats.thisFrame.numDrawnObjects < g_SWVideoConfig.drawEnd)
DumpActiveTextures();
if (!g_bSkipCurrentFrame)
{
if (g_SWVideoConfig.bDumpTextures && swstats.thisFrame.numDrawnObjects >= g_SWVideoConfig.drawStart && swstats.thisFrame.numDrawnObjects < g_SWVideoConfig.drawEnd)
DumpActiveTextures();
if (g_SWVideoConfig.bHwRasterizer)
if (g_SWVideoConfig.bHwRasterizer)
{
HwRasterizer::BeginTriangles();
HwRasterizer::BeginTriangles();
drawingHwTriangles = true;
}
}
}
}
void OnObjectEnd()
{
if (!g_bSkipCurrentFrame)
{
if (g_SWVideoConfig.bDumpObjects && swstats.thisFrame.numDrawnObjects >= g_SWVideoConfig.drawStart && swstats.thisFrame.numDrawnObjects < g_SWVideoConfig.drawEnd)
if (!g_bSkipCurrentFrame)
{
if (g_SWVideoConfig.bDumpObjects && swstats.thisFrame.numDrawnObjects >= g_SWVideoConfig.drawStart && swstats.thisFrame.numDrawnObjects < g_SWVideoConfig.drawEnd)
DumpEfb(StringFromFormat("%sobject%i.tga",
File::GetUserPath(D_DUMPFRAMES_IDX).c_str(),
swstats.thisFrame.numDrawnObjects).c_str());
if (g_SWVideoConfig.bHwRasterizer || drawingHwTriangles)
if (g_SWVideoConfig.bHwRasterizer || drawingHwTriangles)
{
HwRasterizer::EndTriangles();
HwRasterizer::EndTriangles();
drawingHwTriangles = false;
}
for (int i = 0; i < NumObjectBuffers; i++)
{
if (DrawnToBuffer[i])
{
DrawnToBuffer[i] = false;
for (int i = 0; i < NumObjectBuffers; i++)
{
if (DrawnToBuffer[i])
{
DrawnToBuffer[i] = false;
(void)SaveTGA(StringFromFormat("%sobject%i_%s(%i).tga",
File::GetUserPath(D_DUMPFRAMES_IDX).c_str(),
swstats.thisFrame.numDrawnObjects, ObjectBufferName[i], i - BufferBase[i]).c_str(),
EFB_WIDTH, EFB_HEIGHT, ObjectBuffer[i]);
memset(ObjectBuffer[i], 0, sizeof(ObjectBuffer[i]));
}
}
}
}
swstats.thisFrame.numDrawnObjects++;
}
swstats.thisFrame.numDrawnObjects++;
}
}
void OnFrameEnd()
{
if (!g_bSkipCurrentFrame)
{
if (g_SWVideoConfig.bDumpFrames)
{
if (!g_bSkipCurrentFrame)
{
if (g_SWVideoConfig.bDumpFrames)
{
DumpEfb(StringFromFormat("%sframe%i_color.tga",
File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), swstats.frameCount).c_str());
DumpDepth(StringFromFormat("%sframe%i_depth.tga",
File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), swstats.frameCount).c_str());
}
}
}
}
}
}

View File

@ -12,7 +12,7 @@
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// Official Git repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _DEBUGUTIL_H
@ -20,18 +20,18 @@
namespace DebugUtil
{
void Init();
void Init();
void GetTextureBGRA(u8 *dst, u32 texmap, s32 mip, u32 width, u32 height);
void GetTextureBGRA(u8 *dst, u32 texmap, s32 mip, u32 width, u32 height);
void DumpActiveTextures();
void DumpActiveTextures();
void OnObjectBegin();
void OnObjectEnd();
void OnObjectBegin();
void OnObjectEnd();
void OnFrameEnd();
void OnFrameEnd();
void DrawObjectBuffer(s16 x, s16 y, u8 *color, int bufferBase, int subBuffer, const char *name);
void DrawObjectBuffer(s16 x, s16 y, u8 *color, int bufferBase, int subBuffer, const char *name);
void DrawTempBuffer(u8 *color, int buffer);
void CopyTempBuffer(s16 x, s16 y, int bufferBase, int subBuffer, const char *name);

View File

@ -12,7 +12,7 @@
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// Official Git repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "BPMemLoader.h"
@ -30,84 +30,83 @@
namespace EfbCopy
{
void CopyToXfb()
{
GLInterface->Update(); // just updates the render window position and the backbuffer size
void CopyToXfb()
{
GLInterface->Update(); // just updates the render window position and the backbuffer size
if (!g_SWVideoConfig.bHwRasterizer)
{
// copy to open gl for rendering
EfbInterface::UpdateColorTexture();
SWRenderer::DrawTexture(EfbInterface::efbColorTexture, EFB_WIDTH, EFB_HEIGHT);
}
{
// copy to open gl for rendering
EfbInterface::UpdateColorTexture();
SWRenderer::DrawTexture(EfbInterface::efbColorTexture, EFB_WIDTH, EFB_HEIGHT);
}
SWRenderer::SwapBuffer();
SWRenderer::SwapBuffer();
}
}
void CopyToRam()
{
if (!g_SWVideoConfig.bHwRasterizer)
void CopyToRam()
{
if (!g_SWVideoConfig.bHwRasterizer)
{
u8 *dest_ptr = Memory::GetPointer(bpmem.copyTexDest << 5);
TextureEncoder::Encode(dest_ptr);
}
}
}
void ClearEfb()
{
u32 clearColor = (bpmem.clearcolorAR & 0xff) << 24 | bpmem.clearcolorGB << 8 | (bpmem.clearcolorAR & 0xff00) >> 8;
void ClearEfb()
{
u32 clearColor = (bpmem.clearcolorAR & 0xff) << 24 | bpmem.clearcolorGB << 8 | (bpmem.clearcolorAR & 0xff00) >> 8;
int left = bpmem.copyTexSrcXY.x;
int top = bpmem.copyTexSrcXY.y;
int right = left + bpmem.copyTexSrcWH.x;
int bottom = top + bpmem.copyTexSrcWH.y;
int left = bpmem.copyTexSrcXY.x;
int top = bpmem.copyTexSrcXY.y;
int right = left + bpmem.copyTexSrcWH.x;
int bottom = top + bpmem.copyTexSrcWH.y;
for (u16 y = top; y <= bottom; y++)
{
for (u16 x = left; x <= right; x++)
{
EfbInterface::SetColor(x, y, (u8*)(&clearColor));
EfbInterface::SetDepth(x, y, bpmem.clearZValue);
}
}
}
for (u16 y = top; y <= bottom; y++)
{
for (u16 x = left; x <= right; x++)
{
EfbInterface::SetColor(x, y, (u8*)(&clearColor));
EfbInterface::SetDepth(x, y, bpmem.clearZValue);
}
}
}
void CopyEfb()
{
if (bpmem.triggerEFBCopy.copy_to_xfb)
DebugUtil::OnFrameEnd();
void CopyEfb()
{
if (bpmem.triggerEFBCopy.copy_to_xfb)
DebugUtil::OnFrameEnd();
if (!g_bSkipCurrentFrame)
{
if (bpmem.triggerEFBCopy.copy_to_xfb)
{
CopyToXfb();
Core::Callback_VideoCopiedToXFB(true);
if (!g_bSkipCurrentFrame)
{
if (bpmem.triggerEFBCopy.copy_to_xfb)
{
CopyToXfb();
Core::Callback_VideoCopiedToXFB(true);
swstats.frameCount++;
}
else
{
CopyToRam();
}
swstats.frameCount++;
}
else
{
CopyToRam();
}
if (bpmem.triggerEFBCopy.clear)
{
if (g_SWVideoConfig.bHwRasterizer)
HwRasterizer::Clear();
else
ClearEfb();
}
}
else
{
if (bpmem.triggerEFBCopy.copy_to_xfb)
{
// no frame rendered but tell that a frame has finished for frame skip counter
Core::Callback_VideoCopiedToXFB(false);
}
}
}
if (bpmem.triggerEFBCopy.clear)
{
if (g_SWVideoConfig.bHwRasterizer)
HwRasterizer::Clear();
else
ClearEfb();
}
}
else
{
if (bpmem.triggerEFBCopy.copy_to_xfb)
{
// no frame rendered but tell that a frame has finished for frame skip counter
Core::Callback_VideoCopiedToXFB(false);
}
}
}
}

View File

@ -12,7 +12,7 @@
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// Official Git repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _EFB_COPY_H_
@ -23,9 +23,9 @@
namespace EfbCopy
{
// Copy the EFB to RAM as a texture format or XFB
// Clear the EFB if needed
void CopyEfb();
// Copy the EFB to RAM as a texture format or XFB
// Clear the EFB if needed
void CopyEfb();
}

View File

@ -12,7 +12,7 @@
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// Official Git repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "Common.h"
@ -29,17 +29,17 @@ u8 efb[EFB_WIDTH*EFB_HEIGHT*6];
namespace EfbInterface
{
u8 efbColorTexture[EFB_WIDTH*EFB_HEIGHT*4];
u8 efbColorTexture[EFB_WIDTH*EFB_HEIGHT*4];
inline u32 GetColorOffset(u16 x, u16 y)
{
return (x + y * EFB_WIDTH) * 3;
}
inline u32 GetColorOffset(u16 x, u16 y)
{
return (x + y * EFB_WIDTH) * 3;
}
inline u32 GetDepthOffset(u16 x, u16 y)
{
return (x + y * EFB_WIDTH) * 3 + DEPTH_BUFFER_START;
}
inline u32 GetDepthOffset(u16 x, u16 y)
{
return (x + y * EFB_WIDTH) * 3 + DEPTH_BUFFER_START;
}
void DoState(PointerWrap &p)
{
@ -47,45 +47,45 @@ namespace EfbInterface
p.DoArray(efbColorTexture, EFB_WIDTH*EFB_HEIGHT*4);
}
void SetPixelAlphaOnly(u32 offset, u8 a)
{
switch (bpmem.zcontrol.pixel_format)
{
case PIXELFMT_RGB8_Z24:
case PIXELFMT_Z24:
case PIXELFMT_RGB565_Z16:
// do nothing
break;
case PIXELFMT_RGBA6_Z24:
{
void SetPixelAlphaOnly(u32 offset, u8 a)
{
switch (bpmem.zcontrol.pixel_format)
{
case PIXELFMT_RGB8_Z24:
case PIXELFMT_Z24:
case PIXELFMT_RGB565_Z16:
// do nothing
break;
case PIXELFMT_RGBA6_Z24:
{
u32 a32 = a;
u32 *dst = (u32*)&efb[offset];
u32 val = *dst & 0xffffffc0;
val |= (a32 >> 2) & 0x0000003f;
*dst = val;
}
break;
default:
ERROR_LOG(VIDEO, "Unsupported pixel format: %i", bpmem.zcontrol.pixel_format);
}
}
}
break;
default:
ERROR_LOG(VIDEO, "Unsupported pixel format: %i", bpmem.zcontrol.pixel_format);
}
}
void SetPixelColorOnly(u32 offset, u8 *rgb)
{
switch (bpmem.zcontrol.pixel_format)
{
case PIXELFMT_RGB8_Z24:
case PIXELFMT_Z24:
{
void SetPixelColorOnly(u32 offset, u8 *rgb)
{
switch (bpmem.zcontrol.pixel_format)
{
case PIXELFMT_RGB8_Z24:
case PIXELFMT_Z24:
{
u32 src = *(u32*)rgb;
u32 *dst = (u32*)&efb[offset];
u32 val = *dst & 0xff000000;
val |= src >> 8;
*dst = val;
}
break;
case PIXELFMT_RGBA6_Z24:
{
}
break;
case PIXELFMT_RGBA6_Z24:
{
u32 src = *(u32*)rgb;
u32 *dst = (u32*)&efb[offset];
u32 val = *dst & 0xff00003f;
@ -93,39 +93,39 @@ namespace EfbInterface
val |= (src >> 6) & 0x0003f000; // green
val |= (src >> 8) & 0x00fc0000; // red
*dst = val;
}
break;
case PIXELFMT_RGB565_Z16:
{
INFO_LOG(VIDEO, "PIXELFMT_RGB565_Z16 is not supported correctly yet");
u32 src = *(u32*)rgb;
}
break;
case PIXELFMT_RGB565_Z16:
{
INFO_LOG(VIDEO, "PIXELFMT_RGB565_Z16 is not supported correctly yet");
u32 src = *(u32*)rgb;
u32 *dst = (u32*)&efb[offset];
u32 val = *dst & 0xff000000;
val |= src >> 8;
*dst = val;
}
break;
default:
ERROR_LOG(VIDEO, "Unsupported pixel format: %i", bpmem.zcontrol.pixel_format);
}
}
}
break;
default:
ERROR_LOG(VIDEO, "Unsupported pixel format: %i", bpmem.zcontrol.pixel_format);
}
}
void SetPixelAlphaColor(u32 offset, u8 *color)
{
switch (bpmem.zcontrol.pixel_format)
{
case PIXELFMT_RGB8_Z24:
case PIXELFMT_Z24:
{
u32 src = *(u32*)color;
void SetPixelAlphaColor(u32 offset, u8 *color)
{
switch (bpmem.zcontrol.pixel_format)
{
case PIXELFMT_RGB8_Z24:
case PIXELFMT_Z24:
{
u32 src = *(u32*)color;
u32 *dst = (u32*)&efb[offset];
u32 val = *dst & 0xff000000;
val |= src >> 8;
*dst = val;
}
break;
case PIXELFMT_RGBA6_Z24:
{
}
break;
case PIXELFMT_RGBA6_Z24:
{
u32 src = *(u32*)color;
u32 *dst = (u32*)&efb[offset];
u32 val = *dst & 0xff000000;
@ -134,332 +134,341 @@ namespace EfbInterface
val |= (src >> 6) & 0x0003f000; // green
val |= (src >> 8) & 0x00fc0000; // red
*dst = val;
}
break;
case PIXELFMT_RGB565_Z16:
{
INFO_LOG(VIDEO, "PIXELFMT_RGB565_Z16 is not supported correctly yet");
}
break;
case PIXELFMT_RGB565_Z16:
{
INFO_LOG(VIDEO, "PIXELFMT_RGB565_Z16 is not supported correctly yet");
u32 src = *(u32*)color;
u32 *dst = (u32*)&efb[offset];
u32 val = *dst & 0xff000000;
val |= src >> 8;
*dst = val;
}
break;
default:
ERROR_LOG(VIDEO, "Unsupported pixel format: %i", bpmem.zcontrol.pixel_format);
}
}
}
break;
default:
ERROR_LOG(VIDEO, "Unsupported pixel format: %i", bpmem.zcontrol.pixel_format);
}
}
void GetPixelColor(u32 offset, u8 *color)
{
switch (bpmem.zcontrol.pixel_format)
{
case PIXELFMT_RGB8_Z24:
case PIXELFMT_Z24:
{
u32 src = *(u32*)&efb[offset];
void GetPixelColor(u32 offset, u8 *color)
{
switch (bpmem.zcontrol.pixel_format)
{
case PIXELFMT_RGB8_Z24:
case PIXELFMT_Z24:
{
u32 src = *(u32*)&efb[offset];
u32 *dst = (u32*)color;
u32 val = 0xff | ((src & 0x00ffffff) << 8);
*dst = val;
}
break;
case PIXELFMT_RGBA6_Z24:
{
}
break;
case PIXELFMT_RGBA6_Z24:
{
u32 src = *(u32*)&efb[offset];
color[ALP_C] = Convert6To8(src & 0x3f);
color[BLU_C] = Convert6To8((src >> 6) & 0x3f);
color[GRN_C] = Convert6To8((src >> 12) & 0x3f);
color[RED_C] = Convert6To8((src >> 18) & 0x3f);
}
break;
case PIXELFMT_RGB565_Z16:
{
INFO_LOG(VIDEO, "PIXELFMT_RGB565_Z16 is not supported correctly yet");
}
break;
case PIXELFMT_RGB565_Z16:
{
INFO_LOG(VIDEO, "PIXELFMT_RGB565_Z16 is not supported correctly yet");
u32 src = *(u32*)&efb[offset];
u32 *dst = (u32*)color;
u32 val = 0xff | ((src & 0x00ffffff) << 8);
*dst = val;
}
break;
default:
ERROR_LOG(VIDEO, "Unsupported pixel format: %i", bpmem.zcontrol.pixel_format);
}
}
}
break;
default:
ERROR_LOG(VIDEO, "Unsupported pixel format: %i", bpmem.zcontrol.pixel_format);
}
}
void SetPixelDepth(u32 offset, u32 depth)
{
switch (bpmem.zcontrol.pixel_format)
{
case PIXELFMT_RGB8_Z24:
case PIXELFMT_RGBA6_Z24:
case PIXELFMT_Z24:
{
u32 *dst = (u32*)&efb[offset];
void SetPixelDepth(u32 offset, u32 depth)
{
switch (bpmem.zcontrol.pixel_format)
{
case PIXELFMT_RGB8_Z24:
case PIXELFMT_RGBA6_Z24:
case PIXELFMT_Z24:
{
u32 *dst = (u32*)&efb[offset];
u32 val = *dst & 0xff000000;
val |= depth & 0x00ffffff;
*dst = val;
}
break;
case PIXELFMT_RGB565_Z16:
{
INFO_LOG(VIDEO, "PIXELFMT_RGB565_Z16 is not supported correctly yet");
}
break;
case PIXELFMT_RGB565_Z16:
{
INFO_LOG(VIDEO, "PIXELFMT_RGB565_Z16 is not supported correctly yet");
u32 *dst = (u32*)&efb[offset];
u32 val = *dst & 0xff000000;
val |= depth & 0x00ffffff;
*dst = val;
}
break;
default:
ERROR_LOG(VIDEO, "Unsupported pixel format: %i", bpmem.zcontrol.pixel_format);
}
}
}
break;
default:
ERROR_LOG(VIDEO, "Unsupported pixel format: %i", bpmem.zcontrol.pixel_format);
}
}
u32 GetPixelDepth(u32 offset)
{
u32 depth = 0;
u32 GetPixelDepth(u32 offset)
{
u32 depth = 0;
switch (bpmem.zcontrol.pixel_format)
{
case PIXELFMT_RGB8_Z24:
case PIXELFMT_RGBA6_Z24:
case PIXELFMT_Z24:
{
switch (bpmem.zcontrol.pixel_format)
{
case PIXELFMT_RGB8_Z24:
case PIXELFMT_RGBA6_Z24:
case PIXELFMT_Z24:
{
depth = (*(u32*)&efb[offset]) & 0x00ffffff;
}
break;
case PIXELFMT_RGB565_Z16:
{
INFO_LOG(VIDEO, "PIXELFMT_RGB565_Z16 is not supported correctly yet");
}
break;
case PIXELFMT_RGB565_Z16:
{
INFO_LOG(VIDEO, "PIXELFMT_RGB565_Z16 is not supported correctly yet");
depth = (*(u32*)&efb[offset]) & 0x00ffffff;
}
break;
default:
ERROR_LOG(VIDEO, "Unsupported pixel format: %i", bpmem.zcontrol.pixel_format);
}
}
break;
default:
ERROR_LOG(VIDEO, "Unsupported pixel format: %i", bpmem.zcontrol.pixel_format);
}
return depth;
}
return depth;
}
u32 GetSourceFactor(u8 *srcClr, u8 *dstClr, int mode)
{
switch (mode) {
case 0: // zero
return 0;
case 1: // one
return 0xffffffff;
case 2: // dstclr
return *(u32*)dstClr;
case 3: // invdstclr
return 0xffffffff - *(u32*)dstClr;
case 4: // srcalpha
{
u8 alpha = srcClr[ALP_C];
u32 factor = alpha << 24 | alpha << 16 | alpha << 8 | alpha;
return factor;
}
case 5: // invsrcalpha
{
u8 alpha = 0xff - srcClr[ALP_C];
u32 factor = alpha << 24 | alpha << 16 | alpha << 8 | alpha;
return factor;
}
case 6: // dstalpha
{
u8 alpha = dstClr[ALP_C];
u32 factor = alpha << 24 | alpha << 16 | alpha << 8 | alpha;
return factor;
}
case 7: // invdstalpha
{
u8 alpha = 0xff - dstClr[ALP_C];
u32 factor = alpha << 24 | alpha << 16 | alpha << 8 | alpha;
return factor;
}
}
u32 GetSourceFactor(u8 *srcClr, u8 *dstClr, int mode)
{
switch (mode) {
case 0: // zero
return 0;
case 1: // one
return 0xffffffff;
case 2: // dstclr
return *(u32*)dstClr;
case 3: // invdstclr
return 0xffffffff - *(u32*)dstClr;
case 4: // srcalpha
{
u8 alpha = srcClr[ALP_C];
u32 factor = alpha << 24 | alpha << 16 | alpha << 8 | alpha;
return factor;
}
case 5: // invsrcalpha
{
u8 alpha = 0xff - srcClr[ALP_C];
u32 factor = alpha << 24 | alpha << 16 | alpha << 8 | alpha;
return factor;
}
case 6: // dstalpha
{
u8 alpha = dstClr[ALP_C];
u32 factor = alpha << 24 | alpha << 16 | alpha << 8 | alpha;
return factor;
}
case 7: // invdstalpha
{
u8 alpha = 0xff - dstClr[ALP_C];
u32 factor = alpha << 24 | alpha << 16 | alpha << 8 | alpha;
return factor;
}
}
return 0;
}
return 0;
}
u32 GetDestinationFactor(u8 *srcClr, u8 *dstClr, int mode)
{
switch (mode) {
case 0: // zero
return 0;
case 1: // one
return 0xffffffff;
case 2: // srcclr
return *(u32*)srcClr;
case 3: // invsrcclr
return 0xffffffff - *(u32*)srcClr;
case 4: // srcalpha
{
u8 alpha = srcClr[ALP_C];
u32 factor = alpha << 24 | alpha << 16 | alpha << 8 | alpha;
return factor;
}
case 5: // invsrcalpha
{
u8 alpha = 0xff - srcClr[ALP_C];
u32 factor = alpha << 24 | alpha << 16 | alpha << 8 | alpha;
return factor;
}
case 6: // dstalpha
{
u8 alpha = dstClr[ALP_C] & 0xff;
u32 factor = alpha << 24 | alpha << 16 | alpha << 8 | alpha;
return factor;
}
case 7: // invdstalpha
{
u8 alpha = 0xff - dstClr[ALP_C];
u32 factor = alpha << 24 | alpha << 16 | alpha << 8 | alpha;
return factor;
}
}
u32 GetDestinationFactor(u8 *srcClr, u8 *dstClr, int mode)
{
switch (mode) {
case 0: // zero
return 0;
case 1: // one
return 0xffffffff;
case 2: // srcclr
return *(u32*)srcClr;
case 3: // invsrcclr
return 0xffffffff - *(u32*)srcClr;
case 4: // srcalpha
{
u8 alpha = srcClr[ALP_C];
u32 factor = alpha << 24 | alpha << 16 | alpha << 8 | alpha;
return factor;
}
case 5: // invsrcalpha
{
u8 alpha = 0xff - srcClr[ALP_C];
u32 factor = alpha << 24 | alpha << 16 | alpha << 8 | alpha;
return factor;
}
case 6: // dstalpha
{
u8 alpha = dstClr[ALP_C] & 0xff;
u32 factor = alpha << 24 | alpha << 16 | alpha << 8 | alpha;
return factor;
}
case 7: // invdstalpha
{
u8 alpha = 0xff - dstClr[ALP_C];
u32 factor = alpha << 24 | alpha << 16 | alpha << 8 | alpha;
return factor;
}
}
return 0;
}
return 0;
}
void BlendColor(u8 *srcClr, u8 *dstClr)
{
u32 srcFactor = GetSourceFactor(srcClr, dstClr, bpmem.blendmode.srcfactor);
u32 dstFactor = GetDestinationFactor(srcClr, dstClr, bpmem.blendmode.dstfactor);
void BlendColor(u8 *srcClr, u8 *dstClr)
{
u32 srcFactor = GetSourceFactor(srcClr, dstClr, bpmem.blendmode.srcfactor);
u32 dstFactor = GetDestinationFactor(srcClr, dstClr, bpmem.blendmode.dstfactor);
for (int i = 0; i < 4; i++)
{
// add MSB of factors to make their range 0 -> 256
u32 sf = (srcFactor & 0xff);
sf += sf >> 7;
u32 df = (dstFactor & 0xff);
df += df >> 7;
for (int i = 0; i < 4; i++)
{
// add MSB of factors to make their range 0 -> 256
u32 sf = (srcFactor & 0xff);
sf += sf >> 7;
u32 color = (srcClr[i] * sf + dstClr[i] * df) >> 8;
dstClr[i] = (color>255)?255:color;
u32 df = (dstFactor & 0xff);
df += df >> 7;
dstFactor >>= 8;
srcFactor >>= 8;
}
}
u32 color = (srcClr[i] * sf + dstClr[i] * df) >> 8;
dstClr[i] = (color>255)?255:color;
void LogicBlend(u32 srcClr, u32 &dstClr, int op)
{
switch (op) {
case 0: // clear
dstClr = 0;
break;
case 1: // and
dstClr = srcClr & dstClr;
break;
case 2: // revand
dstClr = srcClr & (~dstClr);
break;
case 3: // copy
dstClr = srcClr;
break;
case 4: // invand
dstClr = (~srcClr) & dstClr;
break;
case 5: // noop
dstFactor >>= 8;
srcFactor >>= 8;
}
}
void LogicBlend(u32 srcClr, u32 &dstClr, int op)
{
switch (op)
{
case 0: // clear
dstClr = 0;
break;
case 1: // and
dstClr = srcClr & dstClr;
break;
case 2: // revand
dstClr = srcClr & (~dstClr);
break;
case 3: // copy
dstClr = srcClr;
break;
case 4: // invand
dstClr = (~srcClr) & dstClr;
break;
case 5: // noop
// Do nothing
break;
case 6: // xor
dstClr = srcClr ^ dstClr;
break;
case 7: // or
dstClr = srcClr | dstClr;
break;
case 8: // nor
dstClr = ~(srcClr | dstClr);
break;
case 9: // equiv
dstClr = ~(srcClr ^ dstClr);
break;
case 10: // inv
dstClr = ~dstClr;
break;
case 11: // revor
dstClr = srcClr | (~dstClr);
break;
case 12: // invcopy
dstClr = ~srcClr;
break;
case 13: // invor
dstClr = (~srcClr) | dstClr;
break;
case 14: // nand
dstClr = ~(srcClr & dstClr);
break;
case 15: // set
dstClr = 0xffffffff;
break;
}
}
break;
case 6: // xor
dstClr = srcClr ^ dstClr;
break;
case 7: // or
dstClr = srcClr | dstClr;
break;
case 8: // nor
dstClr = ~(srcClr | dstClr);
break;
case 9: // equiv
dstClr = ~(srcClr ^ dstClr);
break;
case 10: // inv
dstClr = ~dstClr;
break;
case 11: // revor
dstClr = srcClr | (~dstClr);
break;
case 12: // invcopy
dstClr = ~srcClr;
break;
case 13: // invor
dstClr = (~srcClr) | dstClr;
break;
case 14: // nand
dstClr = ~(srcClr & dstClr);
break;
case 15: // set
dstClr = 0xffffffff;
break;
}
}
void SubtractBlend(u8 *srcClr, u8 *dstClr)
{
for (int i = 0; i < 4; i++)
{
int c = (int)dstClr[i] - (int)srcClr[i];
dstClr[i] = (c < 0)?0:c;
}
}
void SubtractBlend(u8 *srcClr, u8 *dstClr)
{
for (int i = 0; i < 4; i++)
{
int c = (int)dstClr[i] - (int)srcClr[i];
dstClr[i] = (c < 0)?0:c;
}
}
void BlendTev(u16 x, u16 y, u8 *color)
{
u32 dstClr;
u32 offset = GetColorOffset(x, y);
void BlendTev(u16 x, u16 y, u8 *color)
{
u32 dstClr;
u32 offset = GetColorOffset(x, y);
u8 *dstClrPtr = (u8*)&dstClr;
u8 *dstClrPtr = (u8*)&dstClr;
GetPixelColor(offset, dstClrPtr);
GetPixelColor(offset, dstClrPtr);
if (bpmem.blendmode.blendenable)
{
if (bpmem.blendmode.subtract)
SubtractBlend(color, dstClrPtr);
else
BlendColor(color, dstClrPtr);
}
else if (bpmem.blendmode.logicopenable)
LogicBlend(*((u32*)color), dstClr, bpmem.blendmode.logicmode);
else
dstClrPtr = color;
if (bpmem.blendmode.blendenable)
{
if (bpmem.blendmode.subtract)
SubtractBlend(color, dstClrPtr);
else
BlendColor(color, dstClrPtr);
}
else if (bpmem.blendmode.logicopenable)
{
LogicBlend(*((u32*)color), dstClr, bpmem.blendmode.logicmode);
}
else
{
dstClrPtr = color;
}
if (bpmem.dstalpha.enable)
dstClrPtr[ALP_C] = bpmem.dstalpha.alpha;
if (bpmem.dstalpha.enable)
dstClrPtr[ALP_C] = bpmem.dstalpha.alpha;
if (bpmem.blendmode.colorupdate)
{
if (bpmem.blendmode.alphaupdate)
SetPixelAlphaColor(offset, dstClrPtr);
else
SetPixelColorOnly(offset, dstClrPtr);
}
else if (bpmem.blendmode.alphaupdate)
SetPixelAlphaOnly(offset, dstClrPtr[ALP_C]);
{
if (bpmem.blendmode.alphaupdate)
SetPixelAlphaColor(offset, dstClrPtr);
else
SetPixelColorOnly(offset, dstClrPtr);
}
else if (bpmem.blendmode.alphaupdate)
{
SetPixelAlphaOnly(offset, dstClrPtr[ALP_C]);
}
// branchless bounding box update
SWPixelEngine::pereg.boxLeft = SWPixelEngine::pereg.boxLeft>x?x:SWPixelEngine::pereg.boxLeft;
SWPixelEngine::pereg.boxRight = SWPixelEngine::pereg.boxRight<x?x:SWPixelEngine::pereg.boxRight;
SWPixelEngine::pereg.boxTop = SWPixelEngine::pereg.boxTop>y?y:SWPixelEngine::pereg.boxTop;
SWPixelEngine::pereg.boxBottom = SWPixelEngine::pereg.boxBottom<y?y:SWPixelEngine::pereg.boxBottom;
}
// branchless bounding box update
SWPixelEngine::pereg.boxLeft = SWPixelEngine::pereg.boxLeft>x?x:SWPixelEngine::pereg.boxLeft;
SWPixelEngine::pereg.boxRight = SWPixelEngine::pereg.boxRight<x?x:SWPixelEngine::pereg.boxRight;
SWPixelEngine::pereg.boxTop = SWPixelEngine::pereg.boxTop>y?y:SWPixelEngine::pereg.boxTop;
SWPixelEngine::pereg.boxBottom = SWPixelEngine::pereg.boxBottom<y?y:SWPixelEngine::pereg.boxBottom;
}
void SetColor(u16 x, u16 y, u8 *color)
{
u32 offset = GetColorOffset(x, y);
if (bpmem.blendmode.colorupdate)
{
if (bpmem.blendmode.alphaupdate)
SetPixelAlphaColor(offset, color);
else
SetPixelColorOnly(offset, color);
}
else if (bpmem.blendmode.alphaupdate)
SetPixelAlphaOnly(offset, color[ALP_C]);
}
void SetColor(u16 x, u16 y, u8 *color)
{
u32 offset = GetColorOffset(x, y);
if (bpmem.blendmode.colorupdate)
{
if (bpmem.blendmode.alphaupdate)
SetPixelAlphaColor(offset, color);
else
SetPixelColorOnly(offset, color);
}
else if (bpmem.blendmode.alphaupdate)
{
SetPixelAlphaOnly(offset, color[ALP_C]);
}
}
void SetDepth(u16 x, u16 y, u32 depth)
{
@ -467,87 +476,87 @@ namespace EfbInterface
SetPixelDepth(GetDepthOffset(x, y), depth);
}
void GetColor(u16 x, u16 y, u8 *color)
{
u32 offset = GetColorOffset(x, y);
GetPixelColor(offset, color);
}
void GetColor(u16 x, u16 y, u8 *color)
{
u32 offset = GetColorOffset(x, y);
GetPixelColor(offset, color);
}
u32 GetDepth(u16 x, u16 y)
{
u32 offset = GetDepthOffset(x, y);
return GetPixelDepth(offset);
}
u32 GetDepth(u16 x, u16 y)
{
u32 offset = GetDepthOffset(x, y);
return GetPixelDepth(offset);
}
u8 *GetPixelPointer(u16 x, u16 y, bool depth)
{
if (depth)
return &efb[GetDepthOffset(x, y)];
return &efb[GetColorOffset(x, y)];
}
u8 *GetPixelPointer(u16 x, u16 y, bool depth)
{
if (depth)
return &efb[GetDepthOffset(x, y)];
return &efb[GetColorOffset(x, y)];
}
void UpdateColorTexture()
{
u32 color;
void UpdateColorTexture()
{
u32 color;
u8* colorPtr = (u8*)&color;
u32* texturePtr = (u32*)efbColorTexture;
u32 textureAddress = 0;
u32 efbOffset = 0;
for (u16 y = 0; y < EFB_HEIGHT; y++)
{
for (u16 x = 0; x < EFB_WIDTH; x++)
{
GetPixelColor(efbOffset, colorPtr);
efbOffset += 3;
u32 textureAddress = 0;
u32 efbOffset = 0;
for (u16 y = 0; y < EFB_HEIGHT; y++)
{
for (u16 x = 0; x < EFB_WIDTH; x++)
{
GetPixelColor(efbOffset, colorPtr);
efbOffset += 3;
texturePtr[textureAddress++] = Common::swap32(color); // ABGR->RGBA
}
}
}
}
}
}
bool ZCompare(u16 x, u16 y, u32 z)
{
u32 offset = GetDepthOffset(x, y);
u32 depth = GetPixelDepth(offset);
bool ZCompare(u16 x, u16 y, u32 z)
{
u32 offset = GetDepthOffset(x, y);
u32 depth = GetPixelDepth(offset);
bool pass;
bool pass;
switch (bpmem.zmode.func)
{
case COMPARE_NEVER:
pass = false;
break;
case COMPARE_LESS:
pass = z < depth;
break;
case COMPARE_EQUAL:
pass = z == depth;
break;
case COMPARE_LEQUAL:
pass = z <= depth;
break;
case COMPARE_GREATER:
pass = z > depth;
break;
case COMPARE_NEQUAL:
pass = z != depth;
break;
case COMPARE_GEQUAL:
pass = z >= depth;
break;
case COMPARE_ALWAYS:
pass = true;
break;
default:
pass = false;
ERROR_LOG(VIDEO, "Bad Z compare mode %i", bpmem.zmode.func);
}
switch (bpmem.zmode.func)
{
case COMPARE_NEVER:
pass = false;
break;
case COMPARE_LESS:
pass = z < depth;
break;
case COMPARE_EQUAL:
pass = z == depth;
break;
case COMPARE_LEQUAL:
pass = z <= depth;
break;
case COMPARE_GREATER:
pass = z > depth;
break;
case COMPARE_NEQUAL:
pass = z != depth;
break;
case COMPARE_GEQUAL:
pass = z >= depth;
break;
case COMPARE_ALWAYS:
pass = true;
break;
default:
pass = false;
ERROR_LOG(VIDEO, "Bad Z compare mode %i", bpmem.zmode.func);
}
if (pass && bpmem.zmode.updateenable)
{
SetPixelDepth(offset, z);
}
return pass;
}
if (pass && bpmem.zmode.updateenable)
{
SetPixelDepth(offset, z);
}
return pass;
}
}

View File

@ -12,7 +12,7 @@
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// Official Git repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _EFB_INTERFACE_H_
@ -22,32 +22,32 @@
namespace EfbInterface
{
const int DEPTH_BUFFER_START = EFB_WIDTH * EFB_HEIGHT * 3;
const int DEPTH_BUFFER_START = EFB_WIDTH * EFB_HEIGHT * 3;
enum { ALP_C, BLU_C, GRN_C, RED_C };
// color order is ABGR in order to emulate RGBA on little-endian hardware
// color order is ABGR in order to emulate RGBA on little-endian hardware
// does full blending of an incoming pixel
void BlendTev(u16 x, u16 y, u8 *color);
// does full blending of an incoming pixel
void BlendTev(u16 x, u16 y, u8 *color);
// compare z at location x,y
// writes it if it passes
// returns result of compare.
bool ZCompare(u16 x, u16 y, u32 z);
// compare z at location x,y
// writes it if it passes
// returns result of compare.
bool ZCompare(u16 x, u16 y, u32 z);
// sets the color and alpha
void SetColor(u16 x, u16 y, u8 *color);
void SetDepth(u16 x, u16 y, u32 depth);
// sets the color and alpha
void SetColor(u16 x, u16 y, u8 *color);
void SetDepth(u16 x, u16 y, u32 depth);
void GetColor(u16 x, u16 y, u8 *color);
u32 GetDepth(u16 x, u16 y);
void GetColor(u16 x, u16 y, u8 *color);
u32 GetDepth(u16 x, u16 y);
u8* GetPixelPointer(u16 x, u16 y, bool depth);
u8* GetPixelPointer(u16 x, u16 y, bool depth);
void UpdateColorTexture();
extern u8 efbColorTexture[EFB_WIDTH*EFB_HEIGHT*4]; // RGBA format
void UpdateColorTexture();
extern u8 efbColorTexture[EFB_WIDTH*EFB_HEIGHT*4]; // RGBA format
void DoState(PointerWrap &p);
}
#endif

View File

@ -12,7 +12,7 @@
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// Official Git repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "Common.h"
@ -369,10 +369,10 @@ namespace HwRasterizer
// extra checks cause textures to be reloaded much more
if (texUnit.texImage0[0].hex != texImage0.hex ||
//texUnit.texImage1[0].hex != texImage1.hex ||
//texUnit.texImage2[0].hex != texImage2.hex ||
texUnit.texImage3[0].hex != texImage3.hex ||
texUnit.texTlut[0].hex != texTlut.hex)
// texUnit.texImage1[0].hex != texImage1.hex ||
// texUnit.texImage2[0].hex != texImage2.hex ||
texUnit.texImage3[0].hex != texImage3.hex ||
texUnit.texTlut[0].hex != texTlut.hex)
{
Destroy();
Create();

View File

@ -12,7 +12,7 @@
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// Official Git repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _HW_RASTERIZER_H
@ -27,37 +27,37 @@ struct OutputVertexData;
namespace HwRasterizer
{
void Init();
void Init();
void Shutdown();
void Prepare();
void BeginTriangles();
void EndTriangles();
void BeginTriangles();
void EndTriangles();
void DrawTriangleFrontFace(OutputVertexData *v0, OutputVertexData *v1, OutputVertexData *v2);
void DrawTriangleFrontFace(OutputVertexData *v0, OutputVertexData *v1, OutputVertexData *v2);
void Clear();
void Clear();
struct TexCacheEntry
{
TexImage0 texImage0;
TexImage1 texImage1;
TexImage2 texImage2;
TexImage3 texImage3;
TexTLUT texTlut;
struct TexCacheEntry
{
TexImage0 texImage0;
TexImage1 texImage1;
TexImage2 texImage2;
TexImage3 texImage3;
TexTLUT texTlut;
GLuint texture;
GLuint texture;
TexCacheEntry();
TexCacheEntry();
void Create();
void Destroy();
void Update();
};
void Create();
void Destroy();
void Update();
};
typedef std::map<u32, TexCacheEntry> TextureCache;
static TextureCache textures;
typedef std::map<u32, TexCacheEntry> TextureCache;
static TextureCache textures;
}
#endif

View File

@ -12,7 +12,7 @@
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// Official Git repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _NATIVEVERTEXFORMAT_H
@ -39,13 +39,13 @@ struct Vec4
struct InputVertexData
{
u8 posMtx;
u8 texMtx[8];
u8 posMtx;
u8 texMtx[8];
Vec3 position;
Vec3 normal[3];
u8 color[2][4];
float texCoords[8][2];
Vec3 position;
Vec3 normal[3];
u8 color[2][4];
float texCoords[8][2];
};
struct OutputVertexData
@ -54,45 +54,45 @@ struct OutputVertexData
enum { RED_C, GRN_C, BLU_C, ALP_C };
Vec3 mvPosition;
Vec4 projectedPosition;
Vec3 screenPosition;
Vec3 normal[3];
u8 color[2][4];
Vec3 texCoords[8];
Vec4 projectedPosition;
Vec3 screenPosition;
Vec3 normal[3];
u8 color[2][4];
Vec3 texCoords[8];
void Lerp(float t, OutputVertexData *a, OutputVertexData *b)
{
#define LINTERP(T, OUT, IN) (OUT) + ((IN - OUT) * T)
void Lerp(float t, OutputVertexData *a, OutputVertexData *b)
{
#define LINTERP(T, OUT, IN) (OUT) + ((IN - OUT) * T)
#define LINTERP_INT(T, OUT, IN) (OUT) + (((IN - OUT) * T) >> 8)
#define LINTERP_INT(T, OUT, IN) (OUT) + (((IN - OUT) * T) >> 8)
mvPosition = LINTERP(t, a->mvPosition, b->mvPosition);
mvPosition = LINTERP(t, a->mvPosition, b->mvPosition);
projectedPosition.x = LINTERP(t, a->projectedPosition.x, b->projectedPosition.x);
projectedPosition.x = LINTERP(t, a->projectedPosition.x, b->projectedPosition.x);
projectedPosition.y = LINTERP(t, a->projectedPosition.y, b->projectedPosition.y);
projectedPosition.z = LINTERP(t, a->projectedPosition.z, b->projectedPosition.z);
projectedPosition.w = LINTERP(t, a->projectedPosition.w, b->projectedPosition.w);
for (int i = 0; i < 3; ++i)
{
normal[i] = LINTERP(t, a->normal[i], b->normal[i]);
}
for (int i = 0; i < 3; ++i)
{
normal[i] = LINTERP(t, a->normal[i], b->normal[i]);
}
u16 t_int = (u16)(t * 256);
for (int i = 0; i < 4; ++i)
{
color[0][i] = LINTERP_INT(t_int, a->color[0][i], b->color[0][i]);
color[1][i] = LINTERP_INT(t_int, a->color[1][i], b->color[1][i]);
}
u16 t_int = (u16)(t * 256);
for (int i = 0; i < 4; ++i)
{
color[0][i] = LINTERP_INT(t_int, a->color[0][i], b->color[0][i]);
color[1][i] = LINTERP_INT(t_int, a->color[1][i], b->color[1][i]);
}
for (int i = 0; i < 8; ++i)
{
texCoords[i] = LINTERP(t, a->texCoords[i], b->texCoords[i]);
}
for (int i = 0; i < 8; ++i)
{
texCoords[i] = LINTERP(t, a->texCoords[i], b->texCoords[i]);
}
#undef LINTERP
#undef LINTERP_INT
}
#undef LINTERP
#undef LINTERP_INT
}
void DoState(PointerWrap &p)
{
mvPosition.DoState(p);

View File

@ -12,7 +12,7 @@
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// Official Git repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "Common.h"
@ -61,258 +61,258 @@ void DoState(PointerWrap &p)
void DecodePrimitiveStream(u32 iBufferSize)
{
u32 vertexSize = vertexLoader.GetVertexSize();
u32 vertexSize = vertexLoader.GetVertexSize();
bool skipPrimitives = g_bSkipCurrentFrame ||
swstats.thisFrame.numDrawnObjects < g_SWVideoConfig.drawStart ||
swstats.thisFrame.numDrawnObjects >= g_SWVideoConfig.drawEnd;
if (skipPrimitives)
{
while (streamSize > 0 && iBufferSize >= vertexSize)
{
g_pVideoData += vertexSize;
iBufferSize -= vertexSize;
streamSize--;
}
}
else
{
while (streamSize > 0 && iBufferSize >= vertexSize)
{
vertexLoader.LoadVertex();
iBufferSize -= vertexSize;
streamSize--;
}
}
if (skipPrimitives)
{
while (streamSize > 0 && iBufferSize >= vertexSize)
{
g_pVideoData += vertexSize;
iBufferSize -= vertexSize;
streamSize--;
}
}
else
{
while (streamSize > 0 && iBufferSize >= vertexSize)
{
vertexLoader.LoadVertex();
iBufferSize -= vertexSize;
streamSize--;
}
}
if (streamSize == 0)
{
// return to normal command processing
ResetDecoding();
}
if (streamSize == 0)
{
// return to normal command processing
ResetDecoding();
}
}
void ReadXFData(u32 iBufferSize)
{
_assert_msg_(VIDEO, iBufferSize >= (u32)(streamSize * 4), "Underflow during standard opcode decoding");
_assert_msg_(VIDEO, iBufferSize >= (u32)(streamSize * 4), "Underflow during standard opcode decoding");
u32 pData[16];
for (int i = 0; i < streamSize; i++)
pData[i] = DataReadU32();
SWLoadXFReg(streamSize, streamAddress, pData);
u32 pData[16];
for (int i = 0; i < streamSize; i++)
pData[i] = DataReadU32();
SWLoadXFReg(streamSize, streamAddress, pData);
// return to normal command processing
ResetDecoding();
// return to normal command processing
ResetDecoding();
}
void ExecuteDisplayList(u32 addr, u32 count)
{
u8 *videoDataSave = g_pVideoData;
u8 *videoDataSave = g_pVideoData;
u8 *dlStart = Memory::GetPointer(addr);
u8 *dlStart = Memory::GetPointer(addr);
g_pVideoData = dlStart;
g_pVideoData = dlStart;
while (OpcodeDecoder::CommandRunnable(count))
{
OpcodeDecoder::Run(count);
while (OpcodeDecoder::CommandRunnable(count))
{
OpcodeDecoder::Run(count);
// if data was read by the opcode decoder then the video data pointer changed
u32 readCount = (u32)(g_pVideoData - dlStart);
dlStart = g_pVideoData;
// if data was read by the opcode decoder then the video data pointer changed
u32 readCount = (u32)(g_pVideoData - dlStart);
dlStart = g_pVideoData;
_assert_msg_(VIDEO, count >= readCount, "Display list underrun");
_assert_msg_(VIDEO, count >= readCount, "Display list underrun");
count -= readCount;
}
count -= readCount;
}
g_pVideoData = videoDataSave;
g_pVideoData = videoDataSave;
}
void DecodeStandard(u32 bufferSize)
{
_assert_msg_(VIDEO, CommandRunnable(bufferSize), "Underflow during standard opcode decoding");
_assert_msg_(VIDEO, CommandRunnable(bufferSize), "Underflow during standard opcode decoding");
int Cmd = DataReadU8();
int Cmd = DataReadU8();
if (Cmd == GX_NOP)
return;
// Causes a SIGBUS error on Android
// XXX: Investigate
if (Cmd == GX_NOP)
return;
// Causes a SIGBUS error on Android
// XXX: Investigate
#ifndef ANDROID
// check if switching in or out of an object
// only used for debuggging
if (inObjectStream && (Cmd & 0x87) != lastPrimCmd)
{
inObjectStream = false;
DebugUtil::OnObjectEnd();
}
if (Cmd & 0x80 && !inObjectStream)
{
inObjectStream = true;
lastPrimCmd = Cmd & 0x87;
DebugUtil::OnObjectBegin();
}
// check if switching in or out of an object
// only used for debuggging
if (inObjectStream && (Cmd & 0x87) != lastPrimCmd)
{
inObjectStream = false;
DebugUtil::OnObjectEnd();
}
if (Cmd & 0x80 && !inObjectStream)
{
inObjectStream = true;
lastPrimCmd = Cmd & 0x87;
DebugUtil::OnObjectBegin();
}
#endif
switch(Cmd)
{
case GX_NOP:
break;
switch(Cmd)
{
case GX_NOP:
break;
case GX_LOAD_CP_REG: //0x08
{
u32 SubCmd = DataReadU8();
u32 Value = DataReadU32();
SWLoadCPReg(SubCmd, Value);
}
break;
case GX_LOAD_CP_REG: //0x08
{
u32 SubCmd = DataReadU8();
u32 Value = DataReadU32();
SWLoadCPReg(SubCmd, Value);
}
break;
case GX_LOAD_XF_REG:
{
u32 Cmd2 = DataReadU32();
streamSize = ((Cmd2 >> 16) & 15) + 1;
streamAddress = Cmd2 & 0xFFFF;
currentFunction = ReadXFData;
minCommandSize = streamSize * 4;
readOpcode = false;
}
break;
case GX_LOAD_XF_REG:
{
u32 Cmd2 = DataReadU32();
streamSize = ((Cmd2 >> 16) & 15) + 1;
streamAddress = Cmd2 & 0xFFFF;
currentFunction = ReadXFData;
minCommandSize = streamSize * 4;
readOpcode = false;
}
break;
case GX_LOAD_INDX_A: //used for position matrices
SWLoadIndexedXF(DataReadU32(), 0xC);
break;
case GX_LOAD_INDX_B: //used for normal matrices
SWLoadIndexedXF(DataReadU32(), 0xD);
break;
case GX_LOAD_INDX_C: //used for postmatrices
SWLoadIndexedXF(DataReadU32(), 0xE);
break;
case GX_LOAD_INDX_D: //used for lights
SWLoadIndexedXF(DataReadU32(), 0xF);
break;
case GX_LOAD_INDX_A: //used for position matrices
SWLoadIndexedXF(DataReadU32(), 0xC);
break;
case GX_LOAD_INDX_B: //used for normal matrices
SWLoadIndexedXF(DataReadU32(), 0xD);
break;
case GX_LOAD_INDX_C: //used for postmatrices
SWLoadIndexedXF(DataReadU32(), 0xE);
break;
case GX_LOAD_INDX_D: //used for lights
SWLoadIndexedXF(DataReadU32(), 0xF);
break;
case GX_CMD_CALL_DL:
{
u32 dwAddr = DataReadU32();
u32 dwCount = DataReadU32();
ExecuteDisplayList(dwAddr, dwCount);
}
break;
case GX_CMD_CALL_DL:
{
u32 dwAddr = DataReadU32();
u32 dwCount = DataReadU32();
ExecuteDisplayList(dwAddr, dwCount);
}
break;
case 0x44:
// zelda 4 swords calls it and checks the metrics registers after that
break;
case 0x44:
// zelda 4 swords calls it and checks the metrics registers after that
break;
case GX_CMD_INVL_VC:// Invalidate (vertex cache?)
DEBUG_LOG(VIDEO, "Invalidate (vertex cache?)");
break;
case GX_CMD_INVL_VC:// Invalidate (vertex cache?)
DEBUG_LOG(VIDEO, "Invalidate (vertex cache?)");
break;
case GX_LOAD_BP_REG: //0x61
{
case GX_LOAD_BP_REG: //0x61
{
u32 cmd = DataReadU32();
SWLoadBPReg(cmd);
}
break;
SWLoadBPReg(cmd);
}
break;
// draw primitives
default:
if (Cmd & 0x80)
{
// draw primitives
default:
if (Cmd & 0x80)
{
u8 vatIndex = Cmd & GX_VAT_MASK;
u8 primitiveType = (Cmd & GX_PRIMITIVE_MASK) >> GX_PRIMITIVE_SHIFT;
vertexLoader.SetFormat(vatIndex, primitiveType);
// switch to primitive processing
streamSize = DataReadU16();
currentFunction = DecodePrimitiveStream;
minCommandSize = vertexLoader.GetVertexSize();
readOpcode = false;
u8 primitiveType = (Cmd & GX_PRIMITIVE_MASK) >> GX_PRIMITIVE_SHIFT;
vertexLoader.SetFormat(vatIndex, primitiveType);
INCSTAT(swstats.thisFrame.numPrimatives);
DEBUG_LOG(VIDEO, "Draw begin");
}
else
{
PanicAlert("GFX: Unknown Opcode (0x%x).\n", Cmd);
break;
}
break;
}
// switch to primitive processing
streamSize = DataReadU16();
currentFunction = DecodePrimitiveStream;
minCommandSize = vertexLoader.GetVertexSize();
readOpcode = false;
INCSTAT(swstats.thisFrame.numPrimatives);
DEBUG_LOG(VIDEO, "Draw begin");
}
else
{
PanicAlert("GFX: Unknown Opcode (0x%x).\n", Cmd);
break;
}
break;
}
}
void Init()
{
inObjectStream = false;
lastPrimCmd = 0;
ResetDecoding();
inObjectStream = false;
lastPrimCmd = 0;
ResetDecoding();
}
void ResetDecoding()
{
currentFunction = DecodeStandard;
minCommandSize = 1;
readOpcode = true;
currentFunction = DecodeStandard;
minCommandSize = 1;
readOpcode = true;
}
bool CommandRunnable(u32 iBufferSize)
{
if (iBufferSize < minCommandSize)
return false;
if (iBufferSize < minCommandSize)
return false;
if (readOpcode)
{
u8 Cmd = DataPeek8(0);
u32 minSize = 1;
if (readOpcode)
{
u8 Cmd = DataPeek8(0);
u32 minSize = 1;
switch(Cmd)
{
case GX_LOAD_CP_REG: //0x08
minSize = 6;
break;
switch(Cmd)
{
case GX_LOAD_CP_REG: //0x08
minSize = 6;
break;
case GX_LOAD_XF_REG:
minSize = 5;
break;
case GX_LOAD_XF_REG:
minSize = 5;
break;
case GX_LOAD_INDX_A: //used for position matrices
minSize = 5;
break;
case GX_LOAD_INDX_B: //used for normal matrices
minSize = 5;
break;
case GX_LOAD_INDX_C: //used for postmatrices
minSize = 5;
break;
case GX_LOAD_INDX_D: //used for lights
minSize = 5;
break;
case GX_LOAD_INDX_A: //used for position matrices
minSize = 5;
break;
case GX_LOAD_INDX_B: //used for normal matrices
minSize = 5;
break;
case GX_LOAD_INDX_C: //used for postmatrices
minSize = 5;
break;
case GX_LOAD_INDX_D: //used for lights
minSize = 5;
break;
case GX_CMD_CALL_DL:
minSize = 9;
break;
case GX_CMD_CALL_DL:
minSize = 9;
break;
case GX_LOAD_BP_REG: //0x61
minSize = 5;
break;
case GX_LOAD_BP_REG: //0x61
minSize = 5;
break;
// draw primitives
default:
if (Cmd & 0x80)
minSize = 3;
break;
}
// draw primitives
default:
if (Cmd & 0x80)
minSize = 3;
break;
}
return (iBufferSize >= minSize);
}
return true;
return (iBufferSize >= minSize);
}
return true;
}
void Run(u32 iBufferSize)
{
currentFunction(iBufferSize);
currentFunction(iBufferSize);
}
}

View File

@ -12,7 +12,7 @@
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// Official Git repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
@ -25,39 +25,39 @@
namespace OpcodeDecoder
{
#define GX_NOP 0x00
#define GX_NOP 0x00
#define GX_LOAD_BP_REG 0x61
#define GX_LOAD_CP_REG 0x08
#define GX_LOAD_XF_REG 0x10
#define GX_LOAD_INDX_A 0x20
#define GX_LOAD_INDX_B 0x28
#define GX_LOAD_INDX_C 0x30
#define GX_LOAD_INDX_D 0x38
#define GX_LOAD_BP_REG 0x61
#define GX_LOAD_CP_REG 0x08
#define GX_LOAD_XF_REG 0x10
#define GX_LOAD_INDX_A 0x20
#define GX_LOAD_INDX_B 0x28
#define GX_LOAD_INDX_C 0x30
#define GX_LOAD_INDX_D 0x38
#define GX_CMD_CALL_DL 0x40
#define GX_CMD_INVL_VC 0x48
#define GX_CMD_CALL_DL 0x40
#define GX_CMD_INVL_VC 0x48
#define GX_PRIMITIVE_MASK 0x78
#define GX_PRIMITIVE_SHIFT 3
#define GX_VAT_MASK 0x07
#define GX_PRIMITIVE_MASK 0x78
#define GX_PRIMITIVE_SHIFT 3
#define GX_VAT_MASK 0x07
//these are defined 1/8th of their real values and without their top bit
#define GX_DRAW_QUADS 0x0 //0x80
#define GX_DRAW_TRIANGLES 0x2 //0x90
#define GX_DRAW_TRIANGLE_STRIP 0x3 //0x98
#define GX_DRAW_TRIANGLE_FAN 0x4 //0xA0
#define GX_DRAW_LINES 0x5 //0xA8
#define GX_DRAW_LINE_STRIP 0x6 //0xB0
#define GX_DRAW_POINTS 0x7 //0xB8
//these are defined 1/8th of their real values and without their top bit
#define GX_DRAW_QUADS 0x0 //0x80
#define GX_DRAW_TRIANGLES 0x2 //0x90
#define GX_DRAW_TRIANGLE_STRIP 0x3 //0x98
#define GX_DRAW_TRIANGLE_FAN 0x4 //0xA0
#define GX_DRAW_LINES 0x5 //0xA8
#define GX_DRAW_LINE_STRIP 0x6 //0xB0
#define GX_DRAW_POINTS 0x7 //0xB8
void Init();
void Init();
void ResetDecoding();
void ResetDecoding();
bool CommandRunnable(u32 iBufferSize);
bool CommandRunnable(u32 iBufferSize);
void Run(u32 iBufferSize);
void Run(u32 iBufferSize);
void DoState(PointerWrap &p);
}

View File

@ -12,7 +12,7 @@
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// Official Git repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "../../Plugin_VideoOGL/Src/GLUtil.h"
@ -23,110 +23,112 @@
// globals
const GLubyte rasters[][13] = {
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36},
{0x00, 0x00, 0x00, 0x66, 0x66, 0xff, 0x66, 0x66, 0xff, 0x66, 0x66, 0x00, 0x00},
{0x00, 0x00, 0x18, 0x7e, 0xff, 0x1b, 0x1f, 0x7e, 0xf8, 0xd8, 0xff, 0x7e, 0x18},
{0x00, 0x00, 0x0e, 0x1b, 0xdb, 0x6e, 0x30, 0x18, 0x0c, 0x76, 0xdb, 0xd8, 0x70},
{0x00, 0x00, 0x7f, 0xc6, 0xcf, 0xd8, 0x70, 0x70, 0xd8, 0xcc, 0xcc, 0x6c, 0x38},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x1c, 0x0c, 0x0e},
{0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x18, 0x0c},
{0x00, 0x00, 0x30, 0x18, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x30},
{0x00, 0x00, 0x00, 0x00, 0x99, 0x5a, 0x3c, 0xff, 0x3c, 0x5a, 0x99, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0xff, 0xff, 0x18, 0x18, 0x18, 0x00, 0x00},
{0x00, 0x00, 0x30, 0x18, 0x1c, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x60, 0x60, 0x30, 0x30, 0x18, 0x18, 0x0c, 0x0c, 0x06, 0x06, 0x03, 0x03},
{0x00, 0x00, 0x3c, 0x66, 0xc3, 0xe3, 0xf3, 0xdb, 0xcf, 0xc7, 0xc3, 0x66, 0x3c},
{0x00, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78, 0x38, 0x18},
{0x00, 0x00, 0xff, 0xc0, 0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x03, 0xe7, 0x7e},
{0x00, 0x00, 0x7e, 0xe7, 0x03, 0x03, 0x07, 0x7e, 0x07, 0x03, 0x03, 0xe7, 0x7e},
{0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xff, 0xcc, 0x6c, 0x3c, 0x1c, 0x0c},
{0x00, 0x00, 0x7e, 0xe7, 0x03, 0x03, 0x07, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0, 0xff},
{0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xc7, 0xfe, 0xc0, 0xc0, 0xc0, 0xe7, 0x7e},
{0x00, 0x00, 0x30, 0x30, 0x30, 0x30, 0x18, 0x0c, 0x06, 0x03, 0x03, 0x03, 0xff},
{0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xe7, 0x7e, 0xe7, 0xc3, 0xc3, 0xe7, 0x7e},
{0x00, 0x00, 0x7e, 0xe7, 0x03, 0x03, 0x03, 0x7f, 0xe7, 0xc3, 0xc3, 0xe7, 0x7e},
{0x00, 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x30, 0x18, 0x1c, 0x1c, 0x00, 0x00, 0x1c, 0x1c, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06},
{0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x03, 0x06, 0x0c, 0x18, 0x30, 0x60},
{0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x18, 0x0c, 0x06, 0x03, 0xc3, 0xc3, 0x7e},
{0x00, 0x00, 0x3f, 0x60, 0xcf, 0xdb, 0xd3, 0xdd, 0xc3, 0x7e, 0x00, 0x00, 0x00},
{0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xff, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x18},
{0x00, 0x00, 0xfe, 0xc7, 0xc3, 0xc3, 0xc7, 0xfe, 0xc7, 0xc3, 0xc3, 0xc7, 0xfe},
{0x00, 0x00, 0x7e, 0xe7, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xe7, 0x7e},
{0x00, 0x00, 0xfc, 0xce, 0xc7, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc7, 0xce, 0xfc},
{0x00, 0x00, 0xff, 0xc0, 0xc0, 0xc0, 0xc0, 0xfc, 0xc0, 0xc0, 0xc0, 0xc0, 0xff},
{0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xfc, 0xc0, 0xc0, 0xc0, 0xff},
{0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xcf, 0xc0, 0xc0, 0xc0, 0xc0, 0xe7, 0x7e},
{0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xff, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3},
{0x00, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e},
{0x00, 0x00, 0x7c, 0xee, 0xc6, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06},
{0x00, 0x00, 0xc3, 0xc6, 0xcc, 0xd8, 0xf0, 0xe0, 0xf0, 0xd8, 0xcc, 0xc6, 0xc3},
{0x00, 0x00, 0xff, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0},
{0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xdb, 0xff, 0xff, 0xe7, 0xc3},
{0x00, 0x00, 0xc7, 0xc7, 0xcf, 0xcf, 0xdf, 0xdb, 0xfb, 0xf3, 0xf3, 0xe3, 0xe3},
{0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xe7, 0x7e},
{0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xfe, 0xc7, 0xc3, 0xc3, 0xc7, 0xfe},
{0x00, 0x00, 0x3f, 0x6e, 0xdf, 0xdb, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x3c},
{0x00, 0x00, 0xc3, 0xc6, 0xcc, 0xd8, 0xf0, 0xfe, 0xc7, 0xc3, 0xc3, 0xc7, 0xfe},
{0x00, 0x00, 0x7e, 0xe7, 0x03, 0x03, 0x07, 0x7e, 0xe0, 0xc0, 0xc0, 0xe7, 0x7e},
{0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff},
{0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3},
{0x00, 0x00, 0x18, 0x3c, 0x3c, 0x66, 0x66, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3},
{0x00, 0x00, 0xc3, 0xe7, 0xff, 0xff, 0xdb, 0xdb, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3},
{0x00, 0x00, 0xc3, 0x66, 0x66, 0x3c, 0x3c, 0x18, 0x3c, 0x3c, 0x66, 0x66, 0xc3},
{0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x3c, 0x66, 0x66, 0xc3},
{0x00, 0x00, 0xff, 0xc0, 0xc0, 0x60, 0x30, 0x7e, 0x0c, 0x06, 0x03, 0x03, 0xff},
{0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3c},
{0x00, 0x03, 0x03, 0x06, 0x06, 0x0c, 0x0c, 0x18, 0x18, 0x30, 0x30, 0x60, 0x60},
{0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18},
{0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x38, 0x30, 0x70},
{0x00, 0x00, 0x7f, 0xc3, 0xc3, 0x7f, 0x03, 0xc3, 0x7e, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0xfe, 0xc3, 0xc3, 0xc3, 0xc3, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0},
{0x00, 0x00, 0x7e, 0xc3, 0xc0, 0xc0, 0xc0, 0xc3, 0x7e, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x7f, 0xc3, 0xc3, 0xc3, 0xc3, 0x7f, 0x03, 0x03, 0x03, 0x03, 0x03},
{0x00, 0x00, 0x7f, 0xc0, 0xc0, 0xfe, 0xc3, 0xc3, 0x7e, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x33, 0x1e},
{0x7e, 0xc3, 0x03, 0x03, 0x7f, 0xc3, 0xc3, 0xc3, 0x7e, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0},
{0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x18, 0x00},
{0x38, 0x6c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00, 0x0c, 0x00},
{0x00, 0x00, 0xc6, 0xcc, 0xf8, 0xf0, 0xd8, 0xcc, 0xc6, 0xc0, 0xc0, 0xc0, 0xc0},
{0x00, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78},
{0x00, 0x00, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xfe, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xfc, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
{0xc0, 0xc0, 0xc0, 0xfe, 0xc3, 0xc3, 0xc3, 0xc3, 0xfe, 0x00, 0x00, 0x00, 0x00},
{0x03, 0x03, 0x03, 0x7f, 0xc3, 0xc3, 0xc3, 0xc3, 0x7f, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xe0, 0xfe, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0xfe, 0x03, 0x03, 0x7e, 0xc0, 0xc0, 0x7f, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x1c, 0x36, 0x30, 0x30, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x00},
{0x00, 0x00, 0x7e, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x18, 0x3c, 0x3c, 0x66, 0x66, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0xc3, 0xe7, 0xff, 0xdb, 0xc3, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0xc3, 0x00, 0x00, 0x00, 0x00},
{0xc0, 0x60, 0x60, 0x30, 0x18, 0x3c, 0x66, 0x66, 0xc3, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0xff, 0x60, 0x30, 0x18, 0x0c, 0x06, 0xff, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x0f, 0x18, 0x18, 0x18, 0x38, 0xf0, 0x38, 0x18, 0x18, 0x18, 0x0f},
{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
{0x00, 0x00, 0xf0, 0x18, 0x18, 0x18, 0x1c, 0x0f, 0x1c, 0x18, 0x18, 0x18, 0xf0},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x8f, 0xf1, 0x60, 0x00, 0x00, 0x00}
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36},
{0x00, 0x00, 0x00, 0x66, 0x66, 0xff, 0x66, 0x66, 0xff, 0x66, 0x66, 0x00, 0x00},
{0x00, 0x00, 0x18, 0x7e, 0xff, 0x1b, 0x1f, 0x7e, 0xf8, 0xd8, 0xff, 0x7e, 0x18},
{0x00, 0x00, 0x0e, 0x1b, 0xdb, 0x6e, 0x30, 0x18, 0x0c, 0x76, 0xdb, 0xd8, 0x70},
{0x00, 0x00, 0x7f, 0xc6, 0xcf, 0xd8, 0x70, 0x70, 0xd8, 0xcc, 0xcc, 0x6c, 0x38},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x1c, 0x0c, 0x0e},
{0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x18, 0x0c},
{0x00, 0x00, 0x30, 0x18, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x30},
{0x00, 0x00, 0x00, 0x00, 0x99, 0x5a, 0x3c, 0xff, 0x3c, 0x5a, 0x99, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0xff, 0xff, 0x18, 0x18, 0x18, 0x00, 0x00},
{0x00, 0x00, 0x30, 0x18, 0x1c, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x60, 0x60, 0x30, 0x30, 0x18, 0x18, 0x0c, 0x0c, 0x06, 0x06, 0x03, 0x03},
{0x00, 0x00, 0x3c, 0x66, 0xc3, 0xe3, 0xf3, 0xdb, 0xcf, 0xc7, 0xc3, 0x66, 0x3c},
{0x00, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78, 0x38, 0x18},
{0x00, 0x00, 0xff, 0xc0, 0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x03, 0xe7, 0x7e},
{0x00, 0x00, 0x7e, 0xe7, 0x03, 0x03, 0x07, 0x7e, 0x07, 0x03, 0x03, 0xe7, 0x7e},
{0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xff, 0xcc, 0x6c, 0x3c, 0x1c, 0x0c},
{0x00, 0x00, 0x7e, 0xe7, 0x03, 0x03, 0x07, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0, 0xff},
{0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xc7, 0xfe, 0xc0, 0xc0, 0xc0, 0xe7, 0x7e},
{0x00, 0x00, 0x30, 0x30, 0x30, 0x30, 0x18, 0x0c, 0x06, 0x03, 0x03, 0x03, 0xff},
{0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xe7, 0x7e, 0xe7, 0xc3, 0xc3, 0xe7, 0x7e},
{0x00, 0x00, 0x7e, 0xe7, 0x03, 0x03, 0x03, 0x7f, 0xe7, 0xc3, 0xc3, 0xe7, 0x7e},
{0x00, 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x30, 0x18, 0x1c, 0x1c, 0x00, 0x00, 0x1c, 0x1c, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06},
{0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x03, 0x06, 0x0c, 0x18, 0x30, 0x60},
{0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x18, 0x0c, 0x06, 0x03, 0xc3, 0xc3, 0x7e},
{0x00, 0x00, 0x3f, 0x60, 0xcf, 0xdb, 0xd3, 0xdd, 0xc3, 0x7e, 0x00, 0x00, 0x00},
{0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xff, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x18},
{0x00, 0x00, 0xfe, 0xc7, 0xc3, 0xc3, 0xc7, 0xfe, 0xc7, 0xc3, 0xc3, 0xc7, 0xfe},
{0x00, 0x00, 0x7e, 0xe7, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xe7, 0x7e},
{0x00, 0x00, 0xfc, 0xce, 0xc7, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc7, 0xce, 0xfc},
{0x00, 0x00, 0xff, 0xc0, 0xc0, 0xc0, 0xc0, 0xfc, 0xc0, 0xc0, 0xc0, 0xc0, 0xff},
{0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xfc, 0xc0, 0xc0, 0xc0, 0xff},
{0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xcf, 0xc0, 0xc0, 0xc0, 0xc0, 0xe7, 0x7e},
{0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xff, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3},
{0x00, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e},
{0x00, 0x00, 0x7c, 0xee, 0xc6, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06},
{0x00, 0x00, 0xc3, 0xc6, 0xcc, 0xd8, 0xf0, 0xe0, 0xf0, 0xd8, 0xcc, 0xc6, 0xc3},
{0x00, 0x00, 0xff, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0},
{0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xdb, 0xff, 0xff, 0xe7, 0xc3},
{0x00, 0x00, 0xc7, 0xc7, 0xcf, 0xcf, 0xdf, 0xdb, 0xfb, 0xf3, 0xf3, 0xe3, 0xe3},
{0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xe7, 0x7e},
{0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xfe, 0xc7, 0xc3, 0xc3, 0xc7, 0xfe},
{0x00, 0x00, 0x3f, 0x6e, 0xdf, 0xdb, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x3c},
{0x00, 0x00, 0xc3, 0xc6, 0xcc, 0xd8, 0xf0, 0xfe, 0xc7, 0xc3, 0xc3, 0xc7, 0xfe},
{0x00, 0x00, 0x7e, 0xe7, 0x03, 0x03, 0x07, 0x7e, 0xe0, 0xc0, 0xc0, 0xe7, 0x7e},
{0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff},
{0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3},
{0x00, 0x00, 0x18, 0x3c, 0x3c, 0x66, 0x66, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3},
{0x00, 0x00, 0xc3, 0xe7, 0xff, 0xff, 0xdb, 0xdb, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3},
{0x00, 0x00, 0xc3, 0x66, 0x66, 0x3c, 0x3c, 0x18, 0x3c, 0x3c, 0x66, 0x66, 0xc3},
{0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x3c, 0x66, 0x66, 0xc3},
{0x00, 0x00, 0xff, 0xc0, 0xc0, 0x60, 0x30, 0x7e, 0x0c, 0x06, 0x03, 0x03, 0xff},
{0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3c},
{0x00, 0x03, 0x03, 0x06, 0x06, 0x0c, 0x0c, 0x18, 0x18, 0x30, 0x30, 0x60, 0x60},
{0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18},
{0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x38, 0x30, 0x70},
{0x00, 0x00, 0x7f, 0xc3, 0xc3, 0x7f, 0x03, 0xc3, 0x7e, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0xfe, 0xc3, 0xc3, 0xc3, 0xc3, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0},
{0x00, 0x00, 0x7e, 0xc3, 0xc0, 0xc0, 0xc0, 0xc3, 0x7e, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x7f, 0xc3, 0xc3, 0xc3, 0xc3, 0x7f, 0x03, 0x03, 0x03, 0x03, 0x03},
{0x00, 0x00, 0x7f, 0xc0, 0xc0, 0xfe, 0xc3, 0xc3, 0x7e, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x33, 0x1e},
{0x7e, 0xc3, 0x03, 0x03, 0x7f, 0xc3, 0xc3, 0xc3, 0x7e, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0},
{0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x18, 0x00},
{0x38, 0x6c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00, 0x0c, 0x00},
{0x00, 0x00, 0xc6, 0xcc, 0xf8, 0xf0, 0xd8, 0xcc, 0xc6, 0xc0, 0xc0, 0xc0, 0xc0},
{0x00, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78},
{0x00, 0x00, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xfe, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xfc, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
{0xc0, 0xc0, 0xc0, 0xfe, 0xc3, 0xc3, 0xc3, 0xc3, 0xfe, 0x00, 0x00, 0x00, 0x00},
{0x03, 0x03, 0x03, 0x7f, 0xc3, 0xc3, 0xc3, 0xc3, 0x7f, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xe0, 0xfe, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0xfe, 0x03, 0x03, 0x7e, 0xc0, 0xc0, 0x7f, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x1c, 0x36, 0x30, 0x30, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x00},
{0x00, 0x00, 0x7e, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x18, 0x3c, 0x3c, 0x66, 0x66, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0xc3, 0xe7, 0xff, 0xdb, 0xc3, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0xc3, 0x00, 0x00, 0x00, 0x00},
{0xc0, 0x60, 0x60, 0x30, 0x18, 0x3c, 0x66, 0x66, 0xc3, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0xff, 0x60, 0x30, 0x18, 0x0c, 0x06, 0xff, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x0f, 0x18, 0x18, 0x18, 0x38, 0xf0, 0x38, 0x18, 0x18, 0x18, 0x0f},
{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
{0x00, 0x00, 0xf0, 0x18, 0x18, 0x18, 0x1c, 0x0f, 0x1c, 0x18, 0x18, 0x18, 0xf0},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x8f, 0xf1, 0x60, 0x00, 0x00, 0x00}
};
RasterFont::RasterFont()
{
// set GL modes
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
// create the raster font
fontOffset = glGenLists(128);
for (int i = 32; i < 127; i++) {
for (int i = 32; i < 127; i++)
{
glNewList(i + fontOffset, GL_COMPILE);
glBitmap(8, 13, 0.0f, 2.0f, 10.0f, 0.0f, rasters[i - 32]);
glEndList();
@ -153,7 +155,8 @@ void RasterFont::printString(const char *s, double x, double y, double z)
char *s2 = temp_buffer;
memcpy(s2, s, length);
s2[length] = 0;
for (int i = 0; i < length; i++) {
for (int i = 0; i < length; i++)
{
if (s2[i] < 32 || s2[i] > 126)
s2[i] = '!';
}
@ -209,7 +212,9 @@ void RasterFont::printMultilineText(const char *text, double start_x, double sta
*t++ = ' ';
}
else
{
*t++ = *text;
}
text++;
}

View File

@ -12,30 +12,31 @@
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// Official Git repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _RASTERFONT_H_
#define _RASTERFONT_H_
class RasterFont {
class RasterFont
{
public:
RasterFont();
~RasterFont(void);
static int debug;
// some useful constants
enum {char_width = 10};
enum {char_height = 15};
// and the happy helper functions
void printString(const char *s, double x, double y, double z=0.0);
void printCenteredString(const char *s, double y, int screen_width, double z=0.0);
RasterFont();
~RasterFont(void);
static int debug;
// some useful constants
enum {char_width = 10};
enum {char_height = 15};
// and the happy helper functions
void printString(const char *s, double x, double y, double z=0.0);
void printCenteredString(const char *s, double y, int screen_width, double z=0.0);
void printMultilineText(const char *text, double x, double y, double z, int bbWidth, int bbHeight);
private:
int fontOffset;
char *temp_buffer;
int fontOffset;
char *temp_buffer;
enum {TEMP_BUFFER_SIZE = 64 * 1024};
};

View File

@ -12,7 +12,7 @@
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// Official Git repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "Common.h"
@ -97,34 +97,34 @@ void Init()
inline int iround(float x)
{
int t;
int t;
#if defined(_WIN32) && !defined(_M_X64)
__asm
{
fld x
fistp t
}
__asm
{
fld x
fistp t
}
#else
t = (int)x;
if((x - t) >= 0.5)
return t + 1;
#endif
return t;
return t;
}
void SetScissor()
{
int xoff = bpmem.scissorOffset.x * 2 - 342;
int yoff = bpmem.scissorOffset.y * 2 - 342;
int xoff = bpmem.scissorOffset.x * 2 - 342;
int yoff = bpmem.scissorOffset.y * 2 - 342;
scissorLeft = bpmem.scissorTL.x - xoff - 342;
if (scissorLeft < 0) scissorLeft = 0;
scissorTop = bpmem.scissorTL.y - yoff - 342;
if (scissorTop < 0) scissorTop = 0;
scissorRight = bpmem.scissorBR.x - xoff - 341;
if (scissorRight > EFB_WIDTH) scissorRight = EFB_WIDTH;
@ -134,12 +134,12 @@ void SetScissor()
void SetTevReg(int reg, int comp, bool konst, s16 color)
{
tev.SetRegColor(reg, comp, konst, color);
tev.SetRegColor(reg, comp, konst, color);
}
inline void Draw(s32 x, s32 y, s32 xi, s32 yi)
{
INCSTAT(swstats.thisFrame.rasterizedPixels);
INCSTAT(swstats.thisFrame.rasterizedPixels);
float dx = vertexOffsetX + (float)(x - vertex0X);
float dy = vertexOffsetY + (float)(y - vertex0Y);
@ -200,14 +200,14 @@ inline void Draw(s32 x, s32 y, s32 xi, s32 yi)
tev.TextureLod[i] = rasterBlock.TextureLod[i];
tev.TextureLinear[i] = rasterBlock.TextureLinear[i];
}
tev.Draw();
tev.Draw();
}
void InitTriangle(float X1, float Y1, s32 xi, s32 yi)
{
vertex0X = xi;
vertex0Y = yi;
vertex0Y = yi;
// adjust a little less than 0.5
const float adjust = 0.495f;
@ -219,13 +219,13 @@ void InitTriangle(float X1, float Y1, s32 xi, s32 yi)
void InitSlope(Slope *slope, float f1, float f2, float f3, float DX31, float DX12, float DY12, float DY31)
{
float DF31 = f3 - f1;
float DF21 = f2 - f1;
float a = DF31 * -DY12 - DF21 * DY31;
float b = DX31 * DF21 + DX12 * DF31;
float c = -DX12 * DY31 - DX31 * -DY12;
slope->dfdx = -a / c;
slope->dfdy = -b / c;
slope->f0 = f1;
float DF21 = f2 - f1;
float a = DF31 * -DY12 - DF21 * DY31;
float b = DX31 * DF21 + DX12 * DF31;
float c = -DX12 * DY31 - DX31 * -DY12;
slope->dfdx = -a / c;
slope->dfdy = -b / c;
slope->f0 = f1;
}
inline void CalculateLOD(s32 &lod, bool &linear, u32 texmap, u32 texcoord)
@ -332,17 +332,17 @@ void BuildBlock(s32 blockX, s32 blockY)
void DrawTriangleFrontFace(OutputVertexData *v0, OutputVertexData *v1, OutputVertexData *v2)
{
INCSTAT(swstats.thisFrame.numTrianglesDrawn);
INCSTAT(swstats.thisFrame.numTrianglesDrawn);
if (g_SWVideoConfig.bHwRasterizer)
{
HwRasterizer::DrawTriangleFrontFace(v0, v1, v2);
return;
}
if (g_SWVideoConfig.bHwRasterizer)
{
HwRasterizer::DrawTriangleFrontFace(v0, v1, v2);
return;
}
// adapted from http://www.devmaster.net/forums/showthread.php?t=1884
// adapted from http://www.devmaster.net/forums/showthread.php?t=1884
// 28.4 fixed-pou32 coordinates. rounded to nearest and adjusted to match hardware output
// 28.4 fixed-pou32 coordinates. rounded to nearest and adjusted to match hardware output
// could also take floor and adjust -8
const s32 Y1 = iround(16.0f * v0->screenPosition[1]) - 9;
const s32 Y2 = iround(16.0f * v1->screenPosition[1]) - 9;
@ -352,161 +352,160 @@ void DrawTriangleFrontFace(OutputVertexData *v0, OutputVertexData *v1, OutputVer
const s32 X2 = iround(16.0f * v1->screenPosition[0]) - 9;
const s32 X3 = iround(16.0f * v2->screenPosition[0]) - 9;
// Deltas
const s32 DX12 = X1 - X2;
const s32 DX23 = X2 - X3;
const s32 DX31 = X3 - X1;
// Deltas
const s32 DX12 = X1 - X2;
const s32 DX23 = X2 - X3;
const s32 DX31 = X3 - X1;
const s32 DY12 = Y1 - Y2;
const s32 DY23 = Y2 - Y3;
const s32 DY31 = Y3 - Y1;
const s32 DY12 = Y1 - Y2;
const s32 DY23 = Y2 - Y3;
const s32 DY31 = Y3 - Y1;
// Fixed-pos32 deltas
const s32 FDX12 = DX12 << 4;
const s32 FDX23 = DX23 << 4;
const s32 FDX31 = DX31 << 4;
// Fixed-pos32 deltas
const s32 FDX12 = DX12 << 4;
const s32 FDX23 = DX23 << 4;
const s32 FDX31 = DX31 << 4;
const s32 FDY12 = DY12 << 4;
const s32 FDY23 = DY23 << 4;
const s32 FDY31 = DY31 << 4;
const s32 FDY12 = DY12 << 4;
const s32 FDY23 = DY23 << 4;
const s32 FDY31 = DY31 << 4;
// Bounding rectangle
s32 minx = (min(min(X1, X2), X3) + 0xF) >> 4;
s32 maxx = (max(max(X1, X2), X3) + 0xF) >> 4;
s32 miny = (min(min(Y1, Y2), Y3) + 0xF) >> 4;
s32 maxy = (max(max(Y1, Y2), Y3) + 0xF) >> 4;
// Bounding rectangle
s32 minx = (min(min(X1, X2), X3) + 0xF) >> 4;
s32 maxx = (max(max(X1, X2), X3) + 0xF) >> 4;
s32 miny = (min(min(Y1, Y2), Y3) + 0xF) >> 4;
s32 maxy = (max(max(Y1, Y2), Y3) + 0xF) >> 4;
// scissor
minx = max(minx, scissorLeft);
maxx = min(maxx, scissorRight);
miny = max(miny, scissorTop);
maxy = min(maxy, scissorBottom);
// scissor
minx = max(minx, scissorLeft);
maxx = min(maxx, scissorRight);
miny = max(miny, scissorTop);
maxy = min(maxy, scissorBottom);
if (minx >= maxx || miny >= maxy)
return;
if (minx >= maxx || miny >= maxy)
return;
// Setup slopes
float fltx1 = v0->screenPosition.x;
float flty1 = v0->screenPosition.y;
float fltdx31 = v2->screenPosition.x - fltx1;
float fltdx12 = fltx1 - v1->screenPosition.x;
float fltdy12 = flty1 - v1->screenPosition.y;
float fltdy31 = v2->screenPosition.y - flty1;
// Setup slopes
float fltx1 = v0->screenPosition.x;
float flty1 = v0->screenPosition.y;
float fltdx31 = v2->screenPosition.x - fltx1;
float fltdx12 = fltx1 - v1->screenPosition.x;
float fltdy12 = flty1 - v1->screenPosition.y;
float fltdy31 = v2->screenPosition.y - flty1;
InitTriangle(fltx1, flty1, (X1 + 0xF) >> 4, (Y1 + 0xF) >> 4);
float w[3] = { 1.0f / v0->projectedPosition.w, 1.0f / v1->projectedPosition.w, 1.0f / v2->projectedPosition.w };
InitSlope(&WSlope, w[0], w[1], w[2], fltdx31, fltdx12, fltdy12, fltdy31);
float w[3] = { 1.0f / v0->projectedPosition.w, 1.0f / v1->projectedPosition.w, 1.0f / v2->projectedPosition.w };
InitSlope(&WSlope, w[0], w[1], w[2], fltdx31, fltdx12, fltdy12, fltdy31);
if (!bpmem.genMode.zfreeze || !g_SWVideoConfig.bZFreeze)
InitSlope(&ZSlope, v0->screenPosition[2], v1->screenPosition[2], v2->screenPosition[2], fltdx31, fltdx12, fltdy12, fltdy31);
InitSlope(&ZSlope, v0->screenPosition[2], v1->screenPosition[2], v2->screenPosition[2], fltdx31, fltdx12, fltdy12, fltdy31);
for(unsigned int i = 0; i < bpmem.genMode.numcolchans; i++)
{
for(int comp = 0; comp < 4; comp++)
InitSlope(&ColorSlopes[i][comp], v0->color[i][comp], v1->color[i][comp], v2->color[i][comp], fltdx31, fltdx12, fltdy12, fltdy31);
}
for(unsigned int i = 0; i < bpmem.genMode.numcolchans; i++)
{
for(int comp = 0; comp < 4; comp++)
InitSlope(&ColorSlopes[i][comp], v0->color[i][comp], v1->color[i][comp], v2->color[i][comp], fltdx31, fltdx12, fltdy12, fltdy31);
}
for(unsigned int i = 0; i < bpmem.genMode.numtexgens; i++)
{
for(int comp = 0; comp < 3; comp++)
InitSlope(&TexSlopes[i][comp], v0->texCoords[i][comp] * w[0], v1->texCoords[i][comp] * w[1], v2->texCoords[i][comp] * w[2], fltdx31, fltdx12, fltdy12, fltdy31);
}
for(unsigned int i = 0; i < bpmem.genMode.numtexgens; i++)
{
for(int comp = 0; comp < 3; comp++)
InitSlope(&TexSlopes[i][comp], v0->texCoords[i][comp] * w[0], v1->texCoords[i][comp] * w[1], v2->texCoords[i][comp] * w[2], fltdx31, fltdx12, fltdy12, fltdy31);
}
// Start in corner of 8x8 block
minx &= ~(BLOCK_SIZE - 1);
miny &= ~(BLOCK_SIZE - 1);
// Half-edge constants
s32 C1 = DY12 * X1 - DX12 * Y1;
s32 C2 = DY23 * X2 - DX23 * Y2;
s32 C3 = DY31 * X3 - DX31 * Y3;
// Start in corner of 8x8 block
minx &= ~(BLOCK_SIZE - 1);
miny &= ~(BLOCK_SIZE - 1);
// Correct for fill convention
if(DY12 < 0 || (DY12 == 0 && DX12 > 0)) C1++;
if(DY23 < 0 || (DY23 == 0 && DX23 > 0)) C2++;
if(DY31 < 0 || (DY31 == 0 && DX31 > 0)) C3++;
// Half-edge constants
s32 C1 = DY12 * X1 - DX12 * Y1;
s32 C2 = DY23 * X2 - DX23 * Y2;
s32 C3 = DY31 * X3 - DX31 * Y3;
// Loop through blocks
for(s32 y = miny; y < maxy; y += BLOCK_SIZE)
{
for(s32 x = minx; x < maxx; x += BLOCK_SIZE)
{
// Corners of block
s32 x0 = x << 4;
s32 x1 = (x + BLOCK_SIZE - 1) << 4;
s32 y0 = y << 4;
s32 y1 = (y + BLOCK_SIZE - 1) << 4;
// Correct for fill convention
if(DY12 < 0 || (DY12 == 0 && DX12 > 0)) C1++;
if(DY23 < 0 || (DY23 == 0 && DX23 > 0)) C2++;
if(DY31 < 0 || (DY31 == 0 && DX31 > 0)) C3++;
// Evaluate half-space functions
bool a00 = C1 + DX12 * y0 - DY12 * x0 > 0;
bool a10 = C1 + DX12 * y0 - DY12 * x1 > 0;
bool a01 = C1 + DX12 * y1 - DY12 * x0 > 0;
bool a11 = C1 + DX12 * y1 - DY12 * x1 > 0;
int a = (a00 << 0) | (a10 << 1) | (a01 << 2) | (a11 << 3);
bool b00 = C2 + DX23 * y0 - DY23 * x0 > 0;
bool b10 = C2 + DX23 * y0 - DY23 * x1 > 0;
bool b01 = C2 + DX23 * y1 - DY23 * x0 > 0;
bool b11 = C2 + DX23 * y1 - DY23 * x1 > 0;
int b = (b00 << 0) | (b10 << 1) | (b01 << 2) | (b11 << 3);
bool c00 = C3 + DX31 * y0 - DY31 * x0 > 0;
bool c10 = C3 + DX31 * y0 - DY31 * x1 > 0;
bool c01 = C3 + DX31 * y1 - DY31 * x0 > 0;
bool c11 = C3 + DX31 * y1 - DY31 * x1 > 0;
int c = (c00 << 0) | (c10 << 1) | (c01 << 2) | (c11 << 3);
// Loop through blocks
for(s32 y = miny; y < maxy; y += BLOCK_SIZE)
{
for(s32 x = minx; x < maxx; x += BLOCK_SIZE)
{
// Corners of block
s32 x0 = x << 4;
s32 x1 = (x + BLOCK_SIZE - 1) << 4;
s32 y0 = y << 4;
s32 y1 = (y + BLOCK_SIZE - 1) << 4;
// Skip block when outside an edge
if(a == 0x0 || b == 0x0 || c == 0x0) continue;
// Evaluate half-space functions
bool a00 = C1 + DX12 * y0 - DY12 * x0 > 0;
bool a10 = C1 + DX12 * y0 - DY12 * x1 > 0;
bool a01 = C1 + DX12 * y1 - DY12 * x0 > 0;
bool a11 = C1 + DX12 * y1 - DY12 * x1 > 0;
int a = (a00 << 0) | (a10 << 1) | (a01 << 2) | (a11 << 3);
bool b00 = C2 + DX23 * y0 - DY23 * x0 > 0;
bool b10 = C2 + DX23 * y0 - DY23 * x1 > 0;
bool b01 = C2 + DX23 * y1 - DY23 * x0 > 0;
bool b11 = C2 + DX23 * y1 - DY23 * x1 > 0;
int b = (b00 << 0) | (b10 << 1) | (b01 << 2) | (b11 << 3);
bool c00 = C3 + DX31 * y0 - DY31 * x0 > 0;
bool c10 = C3 + DX31 * y0 - DY31 * x1 > 0;
bool c01 = C3 + DX31 * y1 - DY31 * x0 > 0;
bool c11 = C3 + DX31 * y1 - DY31 * x1 > 0;
int c = (c00 << 0) | (c10 << 1) | (c01 << 2) | (c11 << 3);
// Skip block when outside an edge
if(a == 0x0 || b == 0x0 || c == 0x0)
continue;
BuildBlock(x, y);
// Accept whole block when totally covered
if(a == 0xF && b == 0xF && c == 0xF)
{
for(s32 iy = 0; iy < BLOCK_SIZE; iy++)
{
for(s32 ix = 0; ix < BLOCK_SIZE; ix++)
{
Draw(x + ix, y + iy, ix, iy);
}
}
}
else // Partially covered block
{
s32 CY1 = C1 + DX12 * y0 - DY12 * x0;
s32 CY2 = C2 + DX23 * y0 - DY23 * x0;
s32 CY3 = C3 + DX31 * y0 - DY31 * x0;
// Accept whole block when totally covered
if(a == 0xF && b == 0xF && c == 0xF)
{
for(s32 iy = 0; iy < BLOCK_SIZE; iy++)
{
for(s32 ix = 0; ix < BLOCK_SIZE; ix++)
{
Draw(x + ix, y + iy, ix, iy);
}
}
}
else // Partially covered block
{
s32 CY1 = C1 + DX12 * y0 - DY12 * x0;
s32 CY2 = C2 + DX23 * y0 - DY23 * x0;
s32 CY3 = C3 + DX31 * y0 - DY31 * x0;
for(s32 iy = 0; iy < BLOCK_SIZE; iy++)
{
s32 CX1 = CY1;
s32 CX2 = CY2;
s32 CX3 = CY3;
for(s32 iy = 0; iy < BLOCK_SIZE; iy++)
{
s32 CX1 = CY1;
s32 CX2 = CY2;
s32 CX3 = CY3;
for(s32 ix = 0; ix < BLOCK_SIZE; ix++)
{
if(CX1 > 0 && CX2 > 0 && CX3 > 0)
{
Draw(x + ix, y + iy, ix, iy);
}
for(s32 ix = 0; ix < BLOCK_SIZE; ix++)
{
if(CX1 > 0 && CX2 > 0 && CX3 > 0)
{
Draw(x + ix, y + iy, ix, iy);
}
CX1 -= FDY12;
CX2 -= FDY23;
CX3 -= FDY31;
}
CY1 += FDX12;
CY2 += FDX23;
CY3 += FDX31;
}
}
}
}
CX1 -= FDY12;
CX2 -= FDY23;
CX3 -= FDY31;
}
CY1 += FDX12;
CY2 += FDX23;
CY3 += FDX31;
}
}
}
}
}
}

View File

@ -12,7 +12,7 @@
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// Official Git repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _RASTERIZER_H_
@ -23,19 +23,19 @@
namespace Rasterizer
{
void Init();
void Init();
void DrawTriangleFrontFace(OutputVertexData *v0, OutputVertexData *v1, OutputVertexData *v2);
void DrawTriangleFrontFace(OutputVertexData *v0, OutputVertexData *v1, OutputVertexData *v2);
void SetScissor();
void SetScissor();
void SetTevReg(int reg, int comp, bool konst, s16 color);
void SetTevReg(int reg, int comp, bool konst, s16 color);
struct Slope
{
float dfdx;
float dfdy;
float f0;
struct Slope
{
float dfdx;
float dfdy;
float f0;
float GetValue(float dx, float dy) { return f0 + (dfdx * dx) + (dfdy * dy); }
void DoState(PointerWrap &p)
@ -44,7 +44,7 @@ namespace Rasterizer
p.Do(dfdy);
p.Do(f0);
}
};
};
struct RasterBlockPixel
{
@ -62,7 +62,6 @@ namespace Rasterizer
};
void DoState(PointerWrap &p);
}
#endif

View File

@ -12,7 +12,7 @@
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// Official Git repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "Common.h"
@ -37,7 +37,7 @@ namespace SWCommandProcessor
enum
{
GATHER_PIPE_SIZE = 32,
INT_CAUSE_CP = 0x800
INT_CAUSE_CP = 0x800
};
// STATE_TO_SAVE
@ -83,17 +83,17 @@ void UpdateInterrupts_Wrapper(u64 userdata, int cyclesLate)
inline bool AtBreakpoint()
{
return cpreg.ctrl.BPEnable && (cpreg.readptr == cpreg.breakpt);
return cpreg.ctrl.BPEnable && (cpreg.readptr == cpreg.breakpt);
}
void Init()
{
cpreg.status.Hex = 0;
cpreg.status.Hex = 0;
cpreg.status.CommandIdle = 1;
cpreg.status.ReadIdle = 1;
cpreg.ctrl.Hex = 0;
cpreg.clear.Hex = 0;
cpreg.ctrl.Hex = 0;
cpreg.clear.Hex = 0;
cpreg.bboxleft = 0;
cpreg.bboxtop = 0;
@ -104,15 +104,15 @@ void Init()
et_UpdateInterrupts = CoreTiming::RegisterEvent("UpdateInterrupts", UpdateInterrupts_Wrapper);
// internal buffer position
readPos = 0;
writePos = 0;
// internal buffer position
readPos = 0;
writePos = 0;
interruptSet = false;
interruptWaiting = false;
interruptSet = false;
interruptWaiting = false;
g_pVideoData = 0;
g_bSkipCurrentFrame = false;
g_pVideoData = 0;
g_bSkipCurrentFrame = false;
}
void Shutdown()
@ -121,31 +121,32 @@ void Shutdown()
void RunGpu()
{
if (!SConfig::GetInstance().m_LocalCoreStartupParameter.bCPUThread)
{
// We are going to do FP math on the main thread so have to save the current state
FPURoundMode::SaveSIMDState();
FPURoundMode::LoadDefaultSIMDState();
// run the opcode decoder
do {
RunBuffer();
} while (cpreg.ctrl.GPReadEnable && !AtBreakpoint() && cpreg.readptr != cpreg.writeptr);
if (!SConfig::GetInstance().m_LocalCoreStartupParameter.bCPUThread)
{
// We are going to do FP math on the main thread so have to save the current state
FPURoundMode::SaveSIMDState();
FPURoundMode::LoadDefaultSIMDState();
FPURoundMode::LoadSIMDState();
}
// run the opcode decoder
do
{
RunBuffer();
} while (cpreg.ctrl.GPReadEnable && !AtBreakpoint() && cpreg.readptr != cpreg.writeptr);
FPURoundMode::LoadSIMDState();
}
}
void Read16(u16& _rReturnValue, const u32 _Address)
{
u32 regAddr = (_Address & 0xFFF) >> 1;
u32 regAddr = (_Address & 0xFFF) >> 1;
DEBUG_LOG(COMMANDPROCESSOR, "(r): 0x%08x : 0x%08x", _Address, ((u16*)&cpreg)[regAddr]);
if (regAddr < 0x20)
_rReturnValue = ((u16*)&cpreg)[regAddr];
else
_rReturnValue = 0;
DEBUG_LOG(COMMANDPROCESSOR, "(r): 0x%08x : 0x%08x", _Address, ((u16*)&cpreg)[regAddr]);
if (regAddr < 0x20)
_rReturnValue = ((u16*)&cpreg)[regAddr];
else
_rReturnValue = 0;
}
void Write16(const u16 _Value, const u32 _Address)
@ -162,14 +163,14 @@ void Write16(const u16 _Value, const u32 _Address)
case CTRL_REGISTER:
{
cpreg.ctrl.Hex = _Value;
cpreg.ctrl.Hex = _Value;
DEBUG_LOG(COMMANDPROCESSOR,"\t write to CTRL_REGISTER : %04x", _Value);
DEBUG_LOG(COMMANDPROCESSOR, "\t GPREAD %s | CPULINK %s | BP %s || BPIntEnable %s | OvF %s | UndF %s"
, cpreg.ctrl.GPReadEnable ? "ON" : "OFF"
, cpreg.ctrl.GPLinkEnable ? "ON" : "OFF"
, cpreg.ctrl.BPEnable ? "ON" : "OFF"
, cpreg.ctrl.BreakPointIntEnable ? "ON" : "OFF"
, cpreg.ctrl.GPReadEnable ? "ON" : "OFF"
, cpreg.ctrl.GPLinkEnable ? "ON" : "OFF"
, cpreg.ctrl.BPEnable ? "ON" : "OFF"
, cpreg.ctrl.BreakPointIntEnable ? "ON" : "OFF"
, cpreg.ctrl.FifoOverflowIntEnable ? "ON" : "OFF"
, cpreg.ctrl.FifoUnderflowIntEnable ? "ON" : "OFF"
);
@ -178,14 +179,14 @@ void Write16(const u16 _Value, const u32 _Address)
case CLEAR_REGISTER:
{
UCPClearReg tmpClear(_Value);
UCPClearReg tmpClear(_Value);
if (tmpClear.ClearFifoOverflow)
cpreg.status.OverflowHiWatermark = 0;
if (tmpClear.ClearFifoUnderflow)
cpreg.status.UnderflowLoWatermark = 0;
if (tmpClear.ClearFifoOverflow)
cpreg.status.OverflowHiWatermark = 0;
if (tmpClear.ClearFifoUnderflow)
cpreg.status.UnderflowLoWatermark = 0;
INFO_LOG(COMMANDPROCESSOR,"\t write to CLEAR_REGISTER : %04x",_Value);
INFO_LOG(COMMANDPROCESSOR,"\t write to CLEAR_REGISTER : %04x",_Value);
}
break;
@ -195,77 +196,77 @@ void Write16(const u16 _Value, const u32 _Address)
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_TOKEN_REGISTER : %04x", _Value);
break;
case FIFO_BASE_LO:
WriteLow ((u32 &)cpreg.fifobase, _Value & 0xFFE0);
case FIFO_BASE_LO:
WriteLow ((u32 &)cpreg.fifobase, _Value & 0xFFE0);
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_BASE_LO. FIFO base is : %08x", cpreg.fifobase);
break;
case FIFO_BASE_HI:
WriteHigh((u32 &)cpreg.fifobase, _Value);
case FIFO_BASE_HI:
WriteHigh((u32 &)cpreg.fifobase, _Value);
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_BASE_HI. FIFO base is : %08x", cpreg.fifobase);
break;
case FIFO_END_LO:
WriteLow ((u32 &)cpreg.fifoend, _Value & 0xFFE0);
case FIFO_END_LO:
WriteLow ((u32 &)cpreg.fifoend, _Value & 0xFFE0);
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_END_LO. FIFO end is : %08x", cpreg.fifoend);
break;
case FIFO_END_HI:
WriteHigh((u32 &)cpreg.fifoend, _Value);
WriteHigh((u32 &)cpreg.fifoend, _Value);
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_END_HI. FIFO end is : %08x", cpreg.fifoend);
break;
case FIFO_WRITE_POINTER_LO:
WriteLow ((u32 &)cpreg.writeptr, _Value & 0xFFE0);
WriteLow ((u32 &)cpreg.writeptr, _Value & 0xFFE0);
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_WRITE_POINTER_LO. write ptr is : %08x", cpreg.writeptr);
break;
case FIFO_WRITE_POINTER_HI:
WriteHigh ((u32 &)cpreg.writeptr, _Value);
WriteHigh ((u32 &)cpreg.writeptr, _Value);
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_WRITE_POINTER_HI. write ptr is : %08x", cpreg.writeptr);
break;
case FIFO_READ_POINTER_LO:
WriteLow ((u32 &)cpreg.readptr, _Value & 0xFFE0);
WriteLow ((u32 &)cpreg.readptr, _Value & 0xFFE0);
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_READ_POINTER_LO. read ptr is : %08x", cpreg.readptr);
break;
case FIFO_READ_POINTER_HI:
WriteHigh ((u32 &)cpreg.readptr, _Value);
WriteHigh ((u32 &)cpreg.readptr, _Value);
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_READ_POINTER_HI. read ptr is : %08x", cpreg.readptr);
break;
case FIFO_HI_WATERMARK_LO:
WriteLow ((u32 &)cpreg.hiwatermark, _Value);
case FIFO_HI_WATERMARK_LO:
WriteLow ((u32 &)cpreg.hiwatermark, _Value);
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_HI_WATERMARK_LO. hiwatermark is : %08x", cpreg.hiwatermark);
break;
case FIFO_HI_WATERMARK_HI:
WriteHigh ((u32 &)cpreg.hiwatermark, _Value);
WriteHigh ((u32 &)cpreg.hiwatermark, _Value);
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_HI_WATERMARK_HI. hiwatermark is : %08x", cpreg.hiwatermark);
break;
case FIFO_LO_WATERMARK_LO:
WriteLow ((u32 &)cpreg.lowatermark, _Value);
WriteLow ((u32 &)cpreg.lowatermark, _Value);
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_LO_WATERMARK_LO. lowatermark is : %08x", cpreg.lowatermark);
break;
case FIFO_LO_WATERMARK_HI:
WriteHigh ((u32 &)cpreg.lowatermark, _Value);
WriteHigh ((u32 &)cpreg.lowatermark, _Value);
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_LO_WATERMARK_HI. lowatermark is : %08x", cpreg.lowatermark);
break;
case FIFO_BP_LO:
WriteLow ((u32 &)cpreg.breakpt, _Value & 0xFFE0);
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_BP_LO. breakpt is : %08x", cpreg.breakpt);
case FIFO_BP_LO:
WriteLow ((u32 &)cpreg.breakpt, _Value & 0xFFE0);
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_BP_LO. breakpoint is : %08x", cpreg.breakpt);
break;
case FIFO_BP_HI:
WriteHigh ((u32 &)cpreg.breakpt, _Value);
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_BP_HI. breakpt is : %08x", cpreg.breakpt);
WriteHigh ((u32 &)cpreg.breakpt, _Value);
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_BP_HI. breakpoint is : %08x", cpreg.breakpt);
break;
case FIFO_RW_DISTANCE_LO:
WriteLow ((u32 &)cpreg.rwdistance, _Value & 0xFFE0);
case FIFO_RW_DISTANCE_LO:
WriteLow ((u32 &)cpreg.rwdistance, _Value & 0xFFE0);
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_RW_DISTANCE_LO. rwdistance is : %08x", cpreg.rwdistance);
break;
case FIFO_RW_DISTANCE_HI:
WriteHigh ((u32 &)cpreg.rwdistance, _Value);
WriteHigh ((u32 &)cpreg.rwdistance, _Value);
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_RW_DISTANCE_HI. rwdistance is : %08x", cpreg.rwdistance);
break;
}
}
RunGpu();
RunGpu();
}
void Read32(u32& _rReturnValue, const u32 _Address)
@ -282,35 +283,35 @@ void Write32(const u32 _Data, const u32 _Address)
void STACKALIGN GatherPipeBursted()
{
if (cpreg.ctrl.GPLinkEnable)
{
DEBUG_LOG(COMMANDPROCESSOR,"\t WGP burst. write thru : %08x", cpreg.writeptr);
{
DEBUG_LOG(COMMANDPROCESSOR,"\t WGP burst. write thru : %08x", cpreg.writeptr);
if (cpreg.writeptr == cpreg.fifoend)
cpreg.writeptr = cpreg.fifobase;
else
cpreg.writeptr += GATHER_PIPE_SIZE;
if (cpreg.writeptr == cpreg.fifoend)
cpreg.writeptr = cpreg.fifobase;
else
cpreg.writeptr += GATHER_PIPE_SIZE;
Common::AtomicAdd(cpreg.rwdistance, GATHER_PIPE_SIZE);
}
Common::AtomicAdd(cpreg.rwdistance, GATHER_PIPE_SIZE);
}
RunGpu();
RunGpu();
}
void UpdateInterrupts(u64 userdata)
{
if (userdata)
if (userdata)
{
interruptSet = true;
INFO_LOG(COMMANDPROCESSOR,"Interrupt set");
ProcessorInterface::SetInterrupt(INT_CAUSE_CP, true);
INFO_LOG(COMMANDPROCESSOR,"Interrupt set");
ProcessorInterface::SetInterrupt(INT_CAUSE_CP, true);
}
else
{
interruptSet = false;
interruptSet = false;
INFO_LOG(COMMANDPROCESSOR,"Interrupt cleared");
ProcessorInterface::SetInterrupt(INT_CAUSE_CP, false);
ProcessorInterface::SetInterrupt(INT_CAUSE_CP, false);
}
interruptWaiting = false;
interruptWaiting = false;
}
void UpdateInterruptsFromVideoBackend(u64 userdata)
@ -320,136 +321,138 @@ void UpdateInterruptsFromVideoBackend(u64 userdata)
void ReadFifo()
{
bool canRead = cpreg.readptr != cpreg.writeptr && writePos < (int)maxCommandBufferWrite;
bool atBreakpoint = AtBreakpoint();
bool canRead = cpreg.readptr != cpreg.writeptr && writePos < (int)maxCommandBufferWrite;
bool atBreakpoint = AtBreakpoint();
if (canRead && !atBreakpoint)
{
// read from fifo
u8 *ptr = Memory::GetPointer(cpreg.readptr);
int bytesRead = 0;
if (canRead && !atBreakpoint)
{
// read from fifo
u8 *ptr = Memory::GetPointer(cpreg.readptr);
int bytesRead = 0;
do
{
// copy to buffer
memcpy(&commandBuffer[writePos], ptr, GATHER_PIPE_SIZE);
writePos += GATHER_PIPE_SIZE;
bytesRead += GATHER_PIPE_SIZE;
do
{
// copy to buffer
memcpy(&commandBuffer[writePos], ptr, GATHER_PIPE_SIZE);
writePos += GATHER_PIPE_SIZE;
bytesRead += GATHER_PIPE_SIZE;
if (cpreg.readptr == cpreg.fifoend)
{
cpreg.readptr = cpreg.fifobase;
ptr = Memory::GetPointer(cpreg.readptr);
}
else
{
cpreg.readptr += GATHER_PIPE_SIZE;
ptr += GATHER_PIPE_SIZE;
}
if (cpreg.readptr == cpreg.fifoend)
{
cpreg.readptr = cpreg.fifobase;
ptr = Memory::GetPointer(cpreg.readptr);
}
else
{
cpreg.readptr += GATHER_PIPE_SIZE;
ptr += GATHER_PIPE_SIZE;
}
canRead = cpreg.readptr != cpreg.writeptr && writePos < (int)maxCommandBufferWrite;
atBreakpoint = AtBreakpoint();
} while (canRead && !atBreakpoint);
canRead = cpreg.readptr != cpreg.writeptr && writePos < (int)maxCommandBufferWrite;
atBreakpoint = AtBreakpoint();
} while (canRead && !atBreakpoint);
Common::AtomicAdd(cpreg.rwdistance, -bytesRead);
}
Common::AtomicAdd(cpreg.rwdistance, -bytesRead);
}
}
void SetStatus()
{
// overflow check
if (cpreg.rwdistance > cpreg.hiwatermark)
cpreg.status.OverflowHiWatermark = 1;
// overflow check
if (cpreg.rwdistance > cpreg.hiwatermark)
cpreg.status.OverflowHiWatermark = 1;
// underflow check
if (cpreg.rwdistance < cpreg.lowatermark)
cpreg.status.UnderflowLoWatermark = 1;
// underflow check
if (cpreg.rwdistance < cpreg.lowatermark)
cpreg.status.UnderflowLoWatermark = 1;
// breakpoint
if (cpreg.ctrl.BPEnable)
{
if (cpreg.breakpt == cpreg.readptr)
{
if (!cpreg.status.Breakpoint)
INFO_LOG(COMMANDPROCESSOR, "Hit breakpoint at %x", cpreg.readptr);
cpreg.status.Breakpoint = 1;
}
}
else
{
if (cpreg.status.Breakpoint)
INFO_LOG(COMMANDPROCESSOR, "Cleared breakpoint at %x", cpreg.readptr);
cpreg.status.Breakpoint = 0;
}
// breakpoint
if (cpreg.ctrl.BPEnable)
{
if (cpreg.breakpt == cpreg.readptr)
{
if (!cpreg.status.Breakpoint)
INFO_LOG(COMMANDPROCESSOR, "Hit breakpoint at %x", cpreg.readptr);
cpreg.status.Breakpoint = 1;
}
}
else
{
if (cpreg.status.Breakpoint)
INFO_LOG(COMMANDPROCESSOR, "Cleared breakpoint at %x", cpreg.readptr);
cpreg.status.Breakpoint = 0;
}
cpreg.status.ReadIdle = cpreg.readptr == cpreg.writeptr;
cpreg.status.ReadIdle = cpreg.readptr == cpreg.writeptr;
bool bpInt = cpreg.status.Breakpoint && cpreg.ctrl.BreakPointIntEnable;
bool ovfInt = cpreg.status.OverflowHiWatermark && cpreg.ctrl.FifoOverflowIntEnable;
bool undfInt = cpreg.status.UnderflowLoWatermark && cpreg.ctrl.FifoUnderflowIntEnable;
bool bpInt = cpreg.status.Breakpoint && cpreg.ctrl.BreakPointIntEnable;
bool ovfInt = cpreg.status.OverflowHiWatermark && cpreg.ctrl.FifoOverflowIntEnable;
bool undfInt = cpreg.status.UnderflowLoWatermark && cpreg.ctrl.FifoUnderflowIntEnable;
bool interrupt = bpInt || ovfInt || undfInt;
bool interrupt = bpInt || ovfInt || undfInt;
if (interrupt != interruptSet && !interruptWaiting)
{
u64 userdata = interrupt?1:0;
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bCPUThread)
{
interruptWaiting = true;
SWCommandProcessor::UpdateInterruptsFromVideoBackend(userdata);
}
else
SWCommandProcessor::UpdateInterrupts(userdata);
}
if (interrupt != interruptSet && !interruptWaiting)
{
u64 userdata = interrupt?1:0;
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bCPUThread)
{
interruptWaiting = true;
SWCommandProcessor::UpdateInterruptsFromVideoBackend(userdata);
}
else
{
SWCommandProcessor::UpdateInterrupts(userdata);
}
}
}
bool RunBuffer()
{
// fifo is read 32 bytes at a time
// read fifo data to internal buffer
if (cpreg.ctrl.GPReadEnable)
ReadFifo();
// fifo is read 32 bytes at a time
// read fifo data to internal buffer
if (cpreg.ctrl.GPReadEnable)
ReadFifo();
SetStatus();
_dbg_assert_(COMMANDPROCESSOR, writePos >= readPos);
g_pVideoData = &commandBuffer[readPos];
SetStatus();
u32 availableBytes = writePos - readPos;
_dbg_assert_(COMMANDPROCESSOR, writePos >= readPos);
while (OpcodeDecoder::CommandRunnable(availableBytes))
{
cpreg.status.CommandIdle = 0;
g_pVideoData = &commandBuffer[readPos];
OpcodeDecoder::Run(availableBytes);
u32 availableBytes = writePos - readPos;
// if data was read by the opcode decoder then the video data pointer changed
readPos = (u32)(g_pVideoData - &commandBuffer[0]);
_dbg_assert_(VIDEO, writePos >= readPos);
availableBytes = writePos - readPos;
}
while (OpcodeDecoder::CommandRunnable(availableBytes))
{
cpreg.status.CommandIdle = 0;
cpreg.status.CommandIdle = 1;
OpcodeDecoder::Run(availableBytes);
bool ranDecoder = false;
// move data remaing in command buffer
if (readPos > 0)
{
memmove(&commandBuffer[0], &commandBuffer[readPos], availableBytes);
writePos -= readPos;
readPos = 0;
// if data was read by the opcode decoder then the video data pointer changed
readPos = (u32)(g_pVideoData - &commandBuffer[0]);
_dbg_assert_(VIDEO, writePos >= readPos);
availableBytes = writePos - readPos;
}
ranDecoder = true;
}
cpreg.status.CommandIdle = 1;
return ranDecoder;
bool ranDecoder = false;
// move data remaing in command buffer
if (readPos > 0)
{
memmove(&commandBuffer[0], &commandBuffer[readPos], availableBytes);
writePos -= readPos;
readPos = 0;
ranDecoder = true;
}
return ranDecoder;
}
void SetRendering(bool enabled)
{
g_bSkipCurrentFrame = !enabled;
g_bSkipCurrentFrame = !enabled;
}
} // end of namespace SWCommandProcessor

View File

@ -12,12 +12,12 @@
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// Official Git repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _COMMANDPROCESSOR_H_
#define _COMMANDPROCESSOR_H_
#include "Common.h"
class PointerWrap;
@ -27,128 +27,128 @@ extern u8* g_pVideoData;
namespace SWCommandProcessor
{
// internal hardware addresses
enum
{
STATUS_REGISTER = 0x00,
CTRL_REGISTER = 0x02,
CLEAR_REGISTER = 0x04,
FIFO_TOKEN_REGISTER = 0x0E,
FIFO_BOUNDING_BOX_LEFT = 0x10,
FIFO_BOUNDING_BOX_RIGHT = 0x12,
FIFO_BOUNDING_BOX_TOP = 0x14,
FIFO_BOUNDING_BOX_BOTTOM = 0x16,
FIFO_BASE_LO = 0x20,
FIFO_BASE_HI = 0x22,
FIFO_END_LO = 0x24,
FIFO_END_HI = 0x26,
FIFO_HI_WATERMARK_LO = 0x28,
FIFO_HI_WATERMARK_HI = 0x2a,
FIFO_LO_WATERMARK_LO = 0x2c,
FIFO_LO_WATERMARK_HI = 0x2e,
FIFO_RW_DISTANCE_LO = 0x30,
FIFO_RW_DISTANCE_HI = 0x32,
FIFO_WRITE_POINTER_LO = 0x34,
FIFO_WRITE_POINTER_HI = 0x36,
FIFO_READ_POINTER_LO = 0x38,
FIFO_READ_POINTER_HI = 0x3A,
FIFO_BP_LO = 0x3C,
FIFO_BP_HI = 0x3E
};
// internal hardware addresses
enum
{
STATUS_REGISTER = 0x00,
CTRL_REGISTER = 0x02,
CLEAR_REGISTER = 0x04,
FIFO_TOKEN_REGISTER = 0x0E,
FIFO_BOUNDING_BOX_LEFT = 0x10,
FIFO_BOUNDING_BOX_RIGHT = 0x12,
FIFO_BOUNDING_BOX_TOP = 0x14,
FIFO_BOUNDING_BOX_BOTTOM = 0x16,
FIFO_BASE_LO = 0x20,
FIFO_BASE_HI = 0x22,
FIFO_END_LO = 0x24,
FIFO_END_HI = 0x26,
FIFO_HI_WATERMARK_LO = 0x28,
FIFO_HI_WATERMARK_HI = 0x2a,
FIFO_LO_WATERMARK_LO = 0x2c,
FIFO_LO_WATERMARK_HI = 0x2e,
FIFO_RW_DISTANCE_LO = 0x30,
FIFO_RW_DISTANCE_HI = 0x32,
FIFO_WRITE_POINTER_LO = 0x34,
FIFO_WRITE_POINTER_HI = 0x36,
FIFO_READ_POINTER_LO = 0x38,
FIFO_READ_POINTER_HI = 0x3A,
FIFO_BP_LO = 0x3C,
FIFO_BP_HI = 0x3E
};
// Fifo Status Register
union UCPStatusReg
{
struct
{
u16 OverflowHiWatermark : 1;
u16 UnderflowLoWatermark: 1;
u16 ReadIdle : 1; // done reading
u16 CommandIdle : 1; // done processing commands
u16 Breakpoint : 1;
u16 : 11;
};
u16 Hex;
UCPStatusReg() {Hex = 0; }
UCPStatusReg(u16 _hex) {Hex = _hex; }
};
// Fifo Status Register
union UCPStatusReg
{
struct
{
u16 OverflowHiWatermark : 1;
u16 UnderflowLoWatermark: 1;
u16 ReadIdle : 1; // done reading
u16 CommandIdle : 1; // done processing commands
u16 Breakpoint : 1;
u16 : 11;
};
u16 Hex;
UCPStatusReg() {Hex = 0; }
UCPStatusReg(u16 _hex) {Hex = _hex; }
};
// Fifo Control Register
union UCPCtrlReg
{
struct
{
u16 GPReadEnable : 1;
u16 BPEnable : 1;
u16 FifoOverflowIntEnable : 1;
u16 FifoUnderflowIntEnable : 1;
u16 GPLinkEnable : 1;
u16 BreakPointIntEnable : 1;
u16 : 10;
};
u16 Hex;
UCPCtrlReg() {Hex = 0; }
UCPCtrlReg(u16 _hex) {Hex = _hex; }
};
// Fifo Control Register
union UCPCtrlReg
{
struct
{
u16 GPReadEnable : 1;
u16 BPEnable : 1;
u16 FifoOverflowIntEnable : 1;
u16 FifoUnderflowIntEnable : 1;
u16 GPLinkEnable : 1;
u16 BreakPointIntEnable : 1;
u16 : 10;
};
u16 Hex;
UCPCtrlReg() {Hex = 0; }
UCPCtrlReg(u16 _hex) {Hex = _hex; }
};
// Fifo Control Register
union UCPClearReg
{
struct
{
u16 ClearFifoOverflow : 1;
u16 ClearFifoUnderflow : 1;
u16 ClearMetrices : 1;
u16 : 13;
};
u16 Hex;
UCPClearReg() {Hex = 0; }
UCPClearReg(u16 _hex) {Hex = _hex; }
};
// Fifo Control Register
union UCPClearReg
{
struct
{
u16 ClearFifoOverflow : 1;
u16 ClearFifoUnderflow : 1;
u16 ClearMetrices : 1;
u16 : 13;
};
u16 Hex;
UCPClearReg() {Hex = 0; }
UCPClearReg(u16 _hex) {Hex = _hex; }
};
struct CPReg
{
UCPStatusReg status; // 0x00
UCPCtrlReg ctrl; // 0x02
UCPClearReg clear; // 0x04
u32 unk0; // 0x06
u32 unk1; // 0x0a
u16 token; // 0x0e
u16 bboxleft; // 0x10
u16 bboxtop; // 0x12
u16 bboxright; // 0x14
u16 bboxbottom; // 0x16
u16 unk2; // 0x18
u32 fifobase; // 0x20
u32 fifoend; // 0x24
u32 hiwatermark; // 0x28
u32 lowatermark; // 0x2c
u32 rwdistance; // 0x30
u32 writeptr; // 0x34
u32 readptr; // 0x38
u32 breakpt; // 0x3c
};
struct CPReg
{
UCPStatusReg status; // 0x00
UCPCtrlReg ctrl; // 0x02
UCPClearReg clear; // 0x04
u32 unk0; // 0x06
u32 unk1; // 0x0a
u16 token; // 0x0e
u16 bboxleft; // 0x10
u16 bboxtop; // 0x12
u16 bboxright; // 0x14
u16 bboxbottom; // 0x16
u16 unk2; // 0x18
u32 fifobase; // 0x20
u32 fifoend; // 0x24
u32 hiwatermark; // 0x28
u32 lowatermark; // 0x2c
u32 rwdistance; // 0x30
u32 writeptr; // 0x34
u32 readptr; // 0x38
u32 breakpt; // 0x3c
};
extern CPReg cpreg;
extern CPReg cpreg;
// Init
void Init();
void Shutdown();
void DoState(PointerWrap &p);
// Init
void Init();
void Shutdown();
void DoState(PointerWrap &p);
bool RunBuffer();
void RunGpu();
bool RunBuffer();
void RunGpu();
// Read
void Read16(u16& _rReturnValue, const u32 _Address);
void Write16(const u16 _Data, const u32 _Address);
void Read32(u32& _rReturnValue, const u32 _Address);
void Write32(const u32 _Data, const u32 _Address);
// Read
void Read16(u16& _rReturnValue, const u32 _Address);
void Write16(const u16 _Data, const u32 _Address);
void Read32(u32& _rReturnValue, const u32 _Address);
void Write32(const u32 _Data, const u32 _Address);
// for CGPFIFO
void GatherPipeBursted();
void UpdateInterrupts(u64 userdata);
void UpdateInterruptsFromVideoBackend(u64 userdata);
// for CGPFIFO
void GatherPipeBursted();
void UpdateInterrupts(u64 userdata);
void UpdateInterruptsFromVideoBackend(u64 userdata);
void SetRendering(bool enabled);

View File

@ -12,7 +12,7 @@
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// Official Git repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
@ -35,8 +35,8 @@ namespace SWPixelEngine
enum
{
INT_CAUSE_PE_TOKEN = 0x200, // GP Token
INT_CAUSE_PE_FINISH = 0x400, // GP Finished
INT_CAUSE_PE_TOKEN = 0x200, // GP Token
INT_CAUSE_PE_FINISH = 0x400, // GP Finished
};
// STATE_TO_SAVE
@ -50,7 +50,7 @@ static int et_SetFinishOnMainThread;
void DoState(PointerWrap &p)
{
p.DoPOD(pereg);
p.DoPOD(pereg);
p.Do(g_bSignalTokenInterrupt);
p.Do(g_bSignalFinishInterrupt);
p.Do(et_SetTokenOnMainThread);
@ -64,10 +64,10 @@ void SetFinish_OnMainThread(u64 userdata, int cyclesLate);
void Init()
{
memset(&pereg, 0, sizeof(pereg));
memset(&pereg, 0, sizeof(pereg));
et_SetTokenOnMainThread = false;
g_bSignalFinishInterrupt = false;
et_SetTokenOnMainThread = false;
g_bSignalFinishInterrupt = false;
et_SetTokenOnMainThread = CoreTiming::RegisterEvent("SetToken", SetToken_OnMainThread);
et_SetFinishOnMainThread = CoreTiming::RegisterEvent("SetFinish", SetFinish_OnMainThread);
@ -77,10 +77,10 @@ void Read16(u16& _uReturnValue, const u32 _iAddress)
{
DEBUG_LOG(PIXELENGINE, "(r16): 0x%08x", _iAddress);
u16 address = _iAddress & 0xFFF;
u16 address = _iAddress & 0xFFF;
if (address <= 0x2e)
_uReturnValue = ((u16*)&pereg)[address >> 1];
if (address <= 0x2e)
_uReturnValue = ((u16*)&pereg)[address >> 1];
}
void Write32(const u32 _iValue, const u32 _iAddress)
@ -92,7 +92,7 @@ void Write16(const u16 _iValue, const u32 _iAddress)
{
u16 address = _iAddress & 0xFFF;
switch (address)
switch (address)
{
case PE_CTRL_REGISTER:
{
@ -101,7 +101,7 @@ void Write16(const u16 _iValue, const u32 _iAddress)
if (tmpCtrl.PEToken) g_bSignalTokenInterrupt = false;
if (tmpCtrl.PEFinish) g_bSignalFinishInterrupt = false;
pereg.ctrl.PETokenEnable = tmpCtrl.PETokenEnable;
pereg.ctrl.PETokenEnable = tmpCtrl.PETokenEnable;
pereg.ctrl.PEFinishEnable = tmpCtrl.PEFinishEnable;
pereg.ctrl.PEToken = 0; // this flag is write only
pereg.ctrl.PEFinish = 0; // this flag is write only
@ -112,7 +112,7 @@ void Write16(const u16 _iValue, const u32 _iAddress)
break;
default:
if (address <= 0x2e)
((u16*)&pereg)[address >> 1] = _iValue;
((u16*)&pereg)[address >> 1] = _iValue;
break;
}
}
@ -125,13 +125,13 @@ bool AllowIdleSkipping()
void UpdateInterrupts()
{
// check if there is a token-interrupt
if (g_bSignalTokenInterrupt & pereg.ctrl.PETokenEnable)
ProcessorInterface::SetInterrupt(INT_CAUSE_PE_TOKEN, true);
if (g_bSignalTokenInterrupt & pereg.ctrl.PETokenEnable)
ProcessorInterface::SetInterrupt(INT_CAUSE_PE_TOKEN, true);
else
ProcessorInterface::SetInterrupt(INT_CAUSE_PE_TOKEN, false);
// check if there is a finish-interrupt
if (g_bSignalFinishInterrupt & pereg.ctrl.PEFinishEnable)
if (g_bSignalFinishInterrupt & pereg.ctrl.PEFinishEnable)
ProcessorInterface::SetInterrupt(INT_CAUSE_PE_FINISH, true);
else
ProcessorInterface::SetInterrupt(INT_CAUSE_PE_FINISH, false);
@ -142,7 +142,7 @@ void UpdateInterrupts()
void SetToken_OnMainThread(u64 userdata, int cyclesLate)
{
g_bSignalTokenInterrupt = true;
INFO_LOG(PIXELENGINE, "VIDEO Backend raises INT_CAUSE_PE_TOKEN (btw, token: %04x)", pereg.token);
INFO_LOG(PIXELENGINE, "VIDEO Backend raises INT_CAUSE_PE_TOKEN (btw, token: %04x)", pereg.token);
UpdateInterrupts();
}
@ -157,7 +157,7 @@ void SetFinish_OnMainThread(u64 userdata, int cyclesLate)
void SetToken(const u16 _token, const int _bSetTokenAcknowledge)
{
pereg.token = _token;
if (_bSetTokenAcknowledge) // set token INT
if (_bSetTokenAcknowledge) // set token INT
{
CoreTiming::ScheduleEvent_Threadsafe(0, et_SetTokenOnMainThread,
_token | (_bSetTokenAcknowledge << 16));

View File

@ -12,7 +12,7 @@
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// Official Git repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _PIXELENGINE_H
#define _PIXELENGINE_H
@ -24,20 +24,20 @@ class PointerWrap;
namespace SWPixelEngine
{
// internal hardware addresses
enum
{
PE_ZCONF = 0x000, // Z Config
PE_ALPHACONF = 0x002, // Alpha Config
PE_DSTALPHACONF = 0x004, // Destination Alpha Config
PE_ALPHAMODE = 0x006, // Alpha Mode Config
PE_ALPHAREAD = 0x008, // Alpha Read
PE_CTRL_REGISTER = 0x00a, // Control
PE_TOKEN_REG = 0x00e, // Token
PE_BBOX_LEFT = 0x010, // Flip Left
PE_BBOX_RIGHT = 0x012, // Flip Right
PE_BBOX_TOP = 0x014, // Flip Top
PE_BBOX_BOTTOM = 0x016, // Flip Bottom
// internal hardware addresses
enum
{
PE_ZCONF = 0x000, // Z Config
PE_ALPHACONF = 0x002, // Alpha Config
PE_DSTALPHACONF = 0x004, // Destination Alpha Config
PE_ALPHAMODE = 0x006, // Alpha Mode Config
PE_ALPHAREAD = 0x008, // Alpha Read
PE_CTRL_REGISTER = 0x00a, // Control
PE_TOKEN_REG = 0x00e, // Token
PE_BBOX_LEFT = 0x010, // Flip Left
PE_BBOX_RIGHT = 0x012, // Flip Right
PE_BBOX_TOP = 0x014, // Flip Top
PE_BBOX_BOTTOM = 0x016, // Flip Bottom
// NOTE: Order not verified
// These indicate the number of quads that are being used as input/output for each particular stage
@ -53,98 +53,98 @@ namespace SWPixelEngine
PE_PERF_BLEND_INPUT_H = 0x2a,
PE_PERF_EFB_COPY_CLOCKS_L = 0x2c,
PE_PERF_EFB_COPY_CLOCKS_H = 0x2e,
};
};
union UPEZConfReg
{
u16 Hex;
struct
{
u16 ZCompEnable : 1; // Z Comparator Enable
u16 Function : 3;
u16 ZUpdEnable : 1;
u16 : 11;
};
};
union UPEZConfReg
{
u16 Hex;
struct
{
u16 ZCompEnable : 1; // Z Comparator Enable
u16 Function : 3;
u16 ZUpdEnable : 1;
u16 : 11;
};
};
union UPEAlphaConfReg
{
u16 Hex;
struct
{
u16 BMMath : 1; // GX_BM_BLEND || GX_BM_SUBSTRACT
u16 BMLogic : 1; // GX_BM_LOGIC
u16 Dither : 1;
u16 ColorUpdEnable : 1;
u16 AlphaUpdEnable : 1;
u16 DstFactor : 3;
u16 SrcFactor : 3;
u16 Substract : 1; // Additive mode by default
u16 BlendOperator : 4;
};
};
union UPEAlphaConfReg
{
u16 Hex;
struct
{
u16 BMMath : 1; // GX_BM_BLEND || GX_BM_SUBSTRACT
u16 BMLogic : 1; // GX_BM_LOGIC
u16 Dither : 1;
u16 ColorUpdEnable : 1;
u16 AlphaUpdEnable : 1;
u16 DstFactor : 3;
u16 SrcFactor : 3;
u16 Substract : 1; // Additive mode by default
u16 BlendOperator : 4;
};
};
union UPEDstAlphaConfReg
{
u16 Hex;
struct
{
u16 DstAlpha : 8;
u16 Enable : 1;
u16 : 7;
};
};
union UPEDstAlphaConfReg
{
u16 Hex;
struct
{
u16 DstAlpha : 8;
u16 Enable : 1;
u16 : 7;
};
};
union UPEAlphaModeConfReg
{
u16 Hex;
struct
{
u16 Threshold : 8;
u16 CompareMode : 8;
};
};
union UPEAlphaModeConfReg
{
u16 Hex;
struct
{
u16 Threshold : 8;
u16 CompareMode : 8;
};
};
union UPEAlphaReadReg
{
u16 Hex;
struct
{
u16 ReadMode : 3;
u16 : 13;
};
};
union UPEAlphaReadReg
{
u16 Hex;
struct
{
u16 ReadMode : 3;
u16 : 13;
};
};
union UPECtrlReg
{
struct
{
u16 PETokenEnable : 1;
u16 PEFinishEnable : 1;
u16 PEToken : 1; // write only
u16 PEFinish : 1; // write only
u16 : 12;
};
u16 Hex;
UPECtrlReg() {Hex = 0; }
UPECtrlReg(u16 _hex) {Hex = _hex; }
};
union UPECtrlReg
{
struct
{
u16 PETokenEnable : 1;
u16 PEFinishEnable : 1;
u16 PEToken : 1; // write only
u16 PEFinish : 1; // write only
u16 : 12;
};
u16 Hex;
UPECtrlReg() {Hex = 0; }
UPECtrlReg(u16 _hex) {Hex = _hex; }
};
struct PEReg
{
UPEZConfReg zconf;
UPEAlphaConfReg alphaConf;
UPEDstAlphaConfReg dstAlpha;
UPEAlphaModeConfReg alphaMode;
UPEAlphaReadReg alphaRead;
UPECtrlReg ctrl;
u16 unk0;
u16 token;
struct PEReg
{
UPEZConfReg zconf;
UPEAlphaConfReg alphaConf;
UPEDstAlphaConfReg dstAlpha;
UPEAlphaModeConfReg alphaMode;
UPEAlphaReadReg alphaRead;
UPECtrlReg ctrl;
u16 unk0;
u16 token;
u16 boxLeft;
u16 boxRight;
u16 boxTop;
u16 boxBottom;
u16 boxLeft;
u16 boxRight;
u16 boxTop;
u16 boxBottom;
u16 perfZcompInputZcomplocLo;
u16 perfZcompInputZcomplocHi;
@ -206,24 +206,24 @@ namespace SWPixelEngine
if (++perfBlendInputLo == 0)
perfBlendInputHi++;
}
};
};
extern PEReg pereg;
extern PEReg pereg;
void Init();
void DoState(PointerWrap &p);
void Init();
void DoState(PointerWrap &p);
// Read
void Read16(u16& _uReturnValue, const u32 _iAddress);
// Read
void Read16(u16& _uReturnValue, const u32 _iAddress);
// Write
void Write16(const u16 _iValue, const u32 _iAddress);
void Write32(const u32 _iValue, const u32 _iAddress);
// Write
void Write16(const u16 _iValue, const u32 _iAddress);
void Write32(const u32 _iValue, const u32 _iAddress);
// gfx backend support
void SetToken(const u16 _token, const int _bSetTokenAcknowledge);
void SetFinish(void);
bool AllowIdleSkipping();
// gfx backend support
void SetToken(const u16 _token, const int _bSetTokenAcknowledge);
void SetFinish(void);
bool AllowIdleSkipping();
} // end of namespace SWPixelEngine

View File

@ -12,7 +12,7 @@
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// Official Git repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "Common.h"
@ -118,20 +118,20 @@ void SWRenderer::DrawDebugText()
if (g_SWVideoConfig.bShowStats)
{
p+=sprintf(p,"Objects: %i\n",swstats.thisFrame.numDrawnObjects);
p+=sprintf(p,"Primitives: %i\n",swstats.thisFrame.numPrimatives);
p+=sprintf(p,"Vertices Loaded: %i\n",swstats.thisFrame.numVerticesLoaded);
p+=sprintf(p,"Objects: %i\n",swstats.thisFrame.numDrawnObjects);
p+=sprintf(p,"Primitives: %i\n",swstats.thisFrame.numPrimatives);
p+=sprintf(p,"Vertices Loaded: %i\n",swstats.thisFrame.numVerticesLoaded);
p+=sprintf(p,"Triangles Input: %i\n",swstats.thisFrame.numTrianglesIn);
p+=sprintf(p,"Triangles Rejected: %i\n",swstats.thisFrame.numTrianglesRejected);
p+=sprintf(p,"Triangles Culled: %i\n",swstats.thisFrame.numTrianglesCulled);
p+=sprintf(p,"Triangles Clipped: %i\n",swstats.thisFrame.numTrianglesClipped);
p+=sprintf(p,"Triangles Drawn: %i\n",swstats.thisFrame.numTrianglesDrawn);
p+=sprintf(p,"Triangles Input: %i\n",swstats.thisFrame.numTrianglesIn);
p+=sprintf(p,"Triangles Rejected: %i\n",swstats.thisFrame.numTrianglesRejected);
p+=sprintf(p,"Triangles Culled: %i\n",swstats.thisFrame.numTrianglesCulled);
p+=sprintf(p,"Triangles Clipped: %i\n",swstats.thisFrame.numTrianglesClipped);
p+=sprintf(p,"Triangles Drawn: %i\n",swstats.thisFrame.numTrianglesDrawn);
p+=sprintf(p,"Rasterized Pix: %i\n",swstats.thisFrame.rasterizedPixels);
p+=sprintf(p,"TEV Pix In: %i\n",swstats.thisFrame.tevPixelsIn);
p+=sprintf(p,"TEV Pix Out: %i\n",swstats.thisFrame.tevPixelsOut);
}
p+=sprintf(p,"Rasterized Pix: %i\n",swstats.thisFrame.rasterizedPixels);
p+=sprintf(p,"TEV Pix In: %i\n",swstats.thisFrame.tevPixelsIn);
p+=sprintf(p,"TEV Pix Out: %i\n",swstats.thisFrame.tevPixelsOut);
}
// Render a shadow, and then the text.
SWRenderer::RenderText(debugtext_buffer, 21, 21, 0xDD000000);
@ -171,9 +171,9 @@ void SWRenderer::DrawTexture(u8 *texture, int width, int height)
glVertexAttribPointer(attr_tex, 2, GL_FLOAT, GL_FALSE, 0, texverts);
glEnableVertexAttribArray(attr_pos);
glEnableVertexAttribArray(attr_tex);
glUniform1i(uni_tex, 0);
glActiveTexture(GL_TEXTURE0);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
glUniform1i(uni_tex, 0);
glActiveTexture(GL_TEXTURE0);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
glDisableVertexAttribArray(attr_pos);
glDisableVertexAttribArray(attr_tex);
@ -191,7 +191,7 @@ void SWRenderer::SwapBuffer()
glFlush();
GLInterface->Swap();
swstats.ResetFrame();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

View File

@ -12,7 +12,7 @@
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// Official Git repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _RENDERER_H_
@ -22,16 +22,16 @@
namespace SWRenderer
{
void Init();
void Prepare();
void Shutdown();
void Init();
void Prepare();
void Shutdown();
void RenderText(const char* pstr, int left, int top, u32 color);
void DrawDebugText();
void RenderText(const char* pstr, int left, int top, u32 color);
void DrawDebugText();
void DrawTexture(u8 *texture, int width, int height);
void DrawTexture(u8 *texture, int width, int height);
void SwapBuffer();
void SwapBuffer();
}
#endif

View File

@ -12,7 +12,7 @@
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// Official Git repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "SWStatistics.h"
@ -29,7 +29,7 @@ void Xchg(T& a, T&b)
SWStatistics::SWStatistics()
{
frameCount = 0;
frameCount = 0;
}
void SWStatistics::ResetFrame()

View File

@ -12,7 +12,7 @@
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// Official Git repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "CommonTypes.h"
@ -23,29 +23,29 @@
struct SWStatistics
{
struct ThisFrame
{
u32 numDrawnObjects;
u32 numPrimatives;
u32 numVerticesLoaded;
u32 numVerticesOut;
struct ThisFrame
{
u32 numDrawnObjects;
u32 numPrimatives;
u32 numVerticesLoaded;
u32 numVerticesOut;
u32 numTrianglesIn;
u32 numTrianglesRejected;
u32 numTrianglesCulled;
u32 numTrianglesClipped;
u32 numTrianglesDrawn;
u32 numTrianglesIn;
u32 numTrianglesRejected;
u32 numTrianglesCulled;
u32 numTrianglesClipped;
u32 numTrianglesDrawn;
u32 rasterizedPixels;
u32 tevPixelsIn;
u32 tevPixelsOut;
};
u32 rasterizedPixels;
u32 tevPixelsIn;
u32 tevPixelsOut;
};
u32 frameCount;
SWStatistics();
u32 frameCount;
SWStatistics();
ThisFrame thisFrame;
void ResetFrame();
ThisFrame thisFrame;
void ResetFrame();
};
extern SWStatistics swstats;

View File

@ -12,7 +12,7 @@
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// Official Git repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "Common.h"
@ -41,72 +41,74 @@ extern float tcScale[8];
SWVertexLoader::SWVertexLoader() :
m_VertexSize(0),
m_NumAttributeLoaders(0)
m_VertexSize(0),
m_NumAttributeLoaders(0)
{
VertexLoader_Normal::Init();
VertexLoader_Position::Init();
VertexLoader_TextCoord::Init();
VertexLoader_Normal::Init();
VertexLoader_Position::Init();
VertexLoader_TextCoord::Init();
m_SetupUnit = new SetupUnit;
m_SetupUnit = new SetupUnit;
}
SWVertexLoader::~SWVertexLoader()
{
delete m_SetupUnit;
m_SetupUnit = NULL;
delete m_SetupUnit;
m_SetupUnit = NULL;
}
void SWVertexLoader::SetFormat(u8 attributeIndex, u8 primitiveType)
{
m_CurrentVat = &g_VtxAttr[attributeIndex];
m_CurrentVat = &g_VtxAttr[attributeIndex];
posScale = 1.0f / float(1 << m_CurrentVat->g0.PosFrac);
tcScale[0] = 1.0f / float(1 << m_CurrentVat->g0.Tex0Frac);
tcScale[1] = 1.0f / float(1 << m_CurrentVat->g1.Tex1Frac);
tcScale[2] = 1.0f / float(1 << m_CurrentVat->g1.Tex2Frac);
tcScale[3] = 1.0f / float(1 << m_CurrentVat->g1.Tex3Frac);
tcScale[4] = 1.0f / float(1 << m_CurrentVat->g2.Tex4Frac);
tcScale[5] = 1.0f / float(1 << m_CurrentVat->g2.Tex5Frac);
tcScale[6] = 1.0f / float(1 << m_CurrentVat->g2.Tex6Frac);
tcScale[7] = 1.0f / float(1 << m_CurrentVat->g2.Tex7Frac);
posScale = 1.0f / float(1 << m_CurrentVat->g0.PosFrac);
tcScale[0] = 1.0f / float(1 << m_CurrentVat->g0.Tex0Frac);
tcScale[1] = 1.0f / float(1 << m_CurrentVat->g1.Tex1Frac);
tcScale[2] = 1.0f / float(1 << m_CurrentVat->g1.Tex2Frac);
tcScale[3] = 1.0f / float(1 << m_CurrentVat->g1.Tex3Frac);
tcScale[4] = 1.0f / float(1 << m_CurrentVat->g2.Tex4Frac);
tcScale[5] = 1.0f / float(1 << m_CurrentVat->g2.Tex5Frac);
tcScale[6] = 1.0f / float(1 << m_CurrentVat->g2.Tex6Frac);
tcScale[7] = 1.0f / float(1 << m_CurrentVat->g2.Tex7Frac);
//TexMtx
const u32 tmDesc[8] = {
g_VtxDesc.Tex0MatIdx, g_VtxDesc.Tex1MatIdx, g_VtxDesc.Tex2MatIdx, g_VtxDesc.Tex3MatIdx,
//TexMtx
const u32 tmDesc[8] = {
g_VtxDesc.Tex0MatIdx, g_VtxDesc.Tex1MatIdx, g_VtxDesc.Tex2MatIdx, g_VtxDesc.Tex3MatIdx,
g_VtxDesc.Tex4MatIdx, g_VtxDesc.Tex5MatIdx, g_VtxDesc.Tex6MatIdx, g_VtxDesc.Tex7MatIdx
};
// Colors
// Colors
const u32 colDesc[2] = {g_VtxDesc.Color0, g_VtxDesc.Color1};
colElements[0] = m_CurrentVat->g0.Color0Elements;
colElements[1] = m_CurrentVat->g0.Color1Elements;
const u32 colComp[2] = {m_CurrentVat->g0.Color0Comp, m_CurrentVat->g0.Color1Comp};
colElements[0] = m_CurrentVat->g0.Color0Elements;
colElements[1] = m_CurrentVat->g0.Color1Elements;
const u32 colComp[2] = {m_CurrentVat->g0.Color0Comp, m_CurrentVat->g0.Color1Comp};
// TextureCoord
const u32 tcDesc[8] = {
g_VtxDesc.Tex0Coord, g_VtxDesc.Tex1Coord, g_VtxDesc.Tex2Coord, g_VtxDesc.Tex3Coord,
g_VtxDesc.Tex4Coord, g_VtxDesc.Tex5Coord, g_VtxDesc.Tex6Coord, (const u32)((g_VtxDesc.Hex >> 31) & 3)
};
const u32 tcElements[8] = {
m_CurrentVat->g0.Tex0CoordElements, m_CurrentVat->g1.Tex1CoordElements, m_CurrentVat->g1.Tex2CoordElements,
m_CurrentVat->g1.Tex3CoordElements, m_CurrentVat->g1.Tex4CoordElements, m_CurrentVat->g2.Tex5CoordElements,
m_CurrentVat->g2.Tex6CoordElements, m_CurrentVat->g2.Tex7CoordElements
};
const u32 tcElements[8] = {
m_CurrentVat->g0.Tex0CoordElements, m_CurrentVat->g1.Tex1CoordElements, m_CurrentVat->g1.Tex2CoordElements,
m_CurrentVat->g1.Tex3CoordElements, m_CurrentVat->g1.Tex4CoordElements, m_CurrentVat->g2.Tex5CoordElements,
m_CurrentVat->g2.Tex6CoordElements, m_CurrentVat->g2.Tex7CoordElements
};
const u32 tcFormat[8] = {
m_CurrentVat->g0.Tex0CoordFormat, m_CurrentVat->g1.Tex1CoordFormat, m_CurrentVat->g1.Tex2CoordFormat,
m_CurrentVat->g1.Tex3CoordFormat, m_CurrentVat->g1.Tex4CoordFormat, m_CurrentVat->g2.Tex5CoordFormat,
m_CurrentVat->g2.Tex6CoordFormat, m_CurrentVat->g2.Tex7CoordFormat
};
const u32 tcFormat[8] = {
m_CurrentVat->g0.Tex0CoordFormat, m_CurrentVat->g1.Tex1CoordFormat, m_CurrentVat->g1.Tex2CoordFormat,
m_CurrentVat->g1.Tex3CoordFormat, m_CurrentVat->g1.Tex4CoordFormat, m_CurrentVat->g2.Tex5CoordFormat,
m_CurrentVat->g2.Tex6CoordFormat, m_CurrentVat->g2.Tex7CoordFormat
};
m_VertexSize = 0;
m_VertexSize = 0;
// Reset pipeline
m_positionLoader = NULL;
m_normalLoader = NULL;
m_NumAttributeLoaders = 0;
m_normalLoader = NULL;
m_NumAttributeLoaders = 0;
// Reset vertex
// matrix index from xf regs or cp memory?
// Reset vertex
// matrix index from xf regs or cp memory?
if (swxfregs.MatrixIndexA.PosNormalMtxIdx != MatrixIndexA.PosNormalMtxIdx ||
swxfregs.MatrixIndexA.Tex0MtxIdx != MatrixIndexA.Tex0MtxIdx ||
swxfregs.MatrixIndexA.Tex1MtxIdx != MatrixIndexA.Tex1MtxIdx ||
@ -126,39 +128,41 @@ void SWVertexLoader::SetFormat(u8 attributeIndex, u8 primitiveType)
}
#if(1)
m_Vertex.posMtx = swxfregs.MatrixIndexA.PosNormalMtxIdx;
m_Vertex.texMtx[0] = swxfregs.MatrixIndexA.Tex0MtxIdx;
m_Vertex.texMtx[1] = swxfregs.MatrixIndexA.Tex1MtxIdx;
m_Vertex.texMtx[2] = swxfregs.MatrixIndexA.Tex2MtxIdx;
m_Vertex.texMtx[3] = swxfregs.MatrixIndexA.Tex3MtxIdx;
m_Vertex.texMtx[4] = swxfregs.MatrixIndexB.Tex4MtxIdx;
m_Vertex.texMtx[5] = swxfregs.MatrixIndexB.Tex5MtxIdx;
m_Vertex.texMtx[6] = swxfregs.MatrixIndexB.Tex6MtxIdx;
m_Vertex.texMtx[7] = swxfregs.MatrixIndexB.Tex7MtxIdx;
m_Vertex.posMtx = swxfregs.MatrixIndexA.PosNormalMtxIdx;
m_Vertex.texMtx[0] = swxfregs.MatrixIndexA.Tex0MtxIdx;
m_Vertex.texMtx[1] = swxfregs.MatrixIndexA.Tex1MtxIdx;
m_Vertex.texMtx[2] = swxfregs.MatrixIndexA.Tex2MtxIdx;
m_Vertex.texMtx[3] = swxfregs.MatrixIndexA.Tex3MtxIdx;
m_Vertex.texMtx[4] = swxfregs.MatrixIndexB.Tex4MtxIdx;
m_Vertex.texMtx[5] = swxfregs.MatrixIndexB.Tex5MtxIdx;
m_Vertex.texMtx[6] = swxfregs.MatrixIndexB.Tex6MtxIdx;
m_Vertex.texMtx[7] = swxfregs.MatrixIndexB.Tex7MtxIdx;
#else
m_Vertex.posMtx = MatrixIndexA.PosNormalMtxIdx;
m_Vertex.texMtx[0] = MatrixIndexA.Tex0MtxIdx;
m_Vertex.texMtx[1] = MatrixIndexA.Tex1MtxIdx;
m_Vertex.texMtx[2] = MatrixIndexA.Tex2MtxIdx;
m_Vertex.texMtx[3] = MatrixIndexA.Tex3MtxIdx;
m_Vertex.texMtx[4] = MatrixIndexB.Tex4MtxIdx;
m_Vertex.texMtx[5] = MatrixIndexB.Tex5MtxIdx;
m_Vertex.texMtx[6] = MatrixIndexB.Tex6MtxIdx;
m_Vertex.texMtx[7] = MatrixIndexB.Tex7MtxIdx;
m_Vertex.posMtx = MatrixIndexA.PosNormalMtxIdx;
m_Vertex.texMtx[0] = MatrixIndexA.Tex0MtxIdx;
m_Vertex.texMtx[1] = MatrixIndexA.Tex1MtxIdx;
m_Vertex.texMtx[2] = MatrixIndexA.Tex2MtxIdx;
m_Vertex.texMtx[3] = MatrixIndexA.Tex3MtxIdx;
m_Vertex.texMtx[4] = MatrixIndexB.Tex4MtxIdx;
m_Vertex.texMtx[5] = MatrixIndexB.Tex5MtxIdx;
m_Vertex.texMtx[6] = MatrixIndexB.Tex6MtxIdx;
m_Vertex.texMtx[7] = MatrixIndexB.Tex7MtxIdx;
#endif
if (g_VtxDesc.PosMatIdx != NOT_PRESENT) {
AddAttributeLoader(LoadPosMtx);
m_VertexSize++;
}
if (g_VtxDesc.PosMatIdx != NOT_PRESENT)
{
AddAttributeLoader(LoadPosMtx);
m_VertexSize++;
}
for (int i = 0; i < 8; ++i) {
if (tmDesc[i] != NOT_PRESENT)
{
AddAttributeLoader(LoadTexMtx, i);
m_VertexSize++;
}
}
for (int i = 0; i < 8; ++i)
{
if (tmDesc[i] != NOT_PRESENT)
{
AddAttributeLoader(LoadTexMtx, i);
m_VertexSize++;
}
}
// Write vertex position loader
m_positionLoader = VertexLoader_Position::GetFunction(g_VtxDesc.Position, m_CurrentVat->g0.PosFormat, m_CurrentVat->g0.PosElements);
@ -178,14 +182,15 @@ void SWVertexLoader::SetFormat(u8 attributeIndex, u8 primitiveType)
{
ERROR_LOG(VIDEO, "VertexLoader_Normal::GetFunction returned zero!");
}
AddAttributeLoader(LoadNormal);
}
AddAttributeLoader(LoadNormal);
}
for (int i = 0; i < 2; i++) {
for (int i = 0; i < 2; i++)
{
switch (colDesc[i])
{
case NOT_PRESENT:
m_colorLoader[i] = NULL;
m_colorLoader[i] = NULL;
break;
case DIRECT:
switch (colComp[i])
@ -198,7 +203,7 @@ void SWVertexLoader::SetFormat(u8 attributeIndex, u8 primitiveType)
case FORMAT_32B_8888: m_VertexSize += 4; m_colorLoader[i] = (Color_ReadDirect_32b_8888); break;
default: _assert_(0); break;
}
AddAttributeLoader(LoadColor, i);
AddAttributeLoader(LoadColor, i);
break;
case INDEX8:
m_VertexSize += 1;
@ -212,7 +217,7 @@ void SWVertexLoader::SetFormat(u8 attributeIndex, u8 primitiveType)
case FORMAT_32B_8888: m_colorLoader[i] = (Color_ReadIndex8_32b_8888); break;
default: _assert_(0); break;
}
AddAttributeLoader(LoadColor, i);
AddAttributeLoader(LoadColor, i);
break;
case INDEX16:
m_VertexSize += 2;
@ -226,13 +231,14 @@ void SWVertexLoader::SetFormat(u8 attributeIndex, u8 primitiveType)
case FORMAT_32B_8888: m_colorLoader[i] = (Color_ReadIndex16_32b_8888); break;
default: _assert_(0); break;
}
AddAttributeLoader(LoadColor, i);
AddAttributeLoader(LoadColor, i);
break;
}
}
// Texture matrix indices (remove if corresponding texture coordinate isn't enabled)
for (int i = 0; i < 8; i++) {
for (int i = 0; i < 8; i++)
{
const int desc = tcDesc[i];
const int format = tcFormat[i];
const int elements = tcElements[i];
@ -244,7 +250,7 @@ void SWVertexLoader::SetFormat(u8 attributeIndex, u8 primitiveType)
m_VertexSize += VertexLoader_TextCoord::GetSize(desc, format, elements);
if (m_texCoordLoader[i])
AddAttributeLoader(LoadTexCoord, i);
}
}
// special case if only pos and tex coord 0 and tex coord input is AB11
m_TexGenSpecialCase =
@ -252,80 +258,79 @@ void SWVertexLoader::SetFormat(u8 attributeIndex, u8 primitiveType)
(g_VtxDesc.Tex0Coord != NOT_PRESENT) &&
(swxfregs.texMtxInfo[0].projection == XF_TEXPROJ_ST);
m_SetupUnit->Init(primitiveType);
m_SetupUnit->Init(primitiveType);
}
void SWVertexLoader::LoadVertex()
{
for (int i = 0; i < m_NumAttributeLoaders; i++)
m_AttributeLoaders[i].loader(this, &m_Vertex, m_AttributeLoaders[i].index);
for (int i = 0; i < m_NumAttributeLoaders; i++)
m_AttributeLoaders[i].loader(this, &m_Vertex, m_AttributeLoaders[i].index);
OutputVertexData* outVertex = m_SetupUnit->GetVertex();
OutputVertexData* outVertex = m_SetupUnit->GetVertex();
// transform input data
TransformUnit::TransformPosition(&m_Vertex, outVertex);
// transform input data
TransformUnit::TransformPosition(&m_Vertex, outVertex);
if (g_VtxDesc.Normal != NOT_PRESENT)
{
TransformUnit::TransformNormal(&m_Vertex, m_CurrentVat->g0.NormalElements, outVertex);
}
if (g_VtxDesc.Normal != NOT_PRESENT)
{
TransformUnit::TransformNormal(&m_Vertex, m_CurrentVat->g0.NormalElements, outVertex);
}
TransformUnit::TransformColor(&m_Vertex, outVertex);
TransformUnit::TransformColor(&m_Vertex, outVertex);
TransformUnit::TransformTexCoord(&m_Vertex, outVertex, m_TexGenSpecialCase);
TransformUnit::TransformTexCoord(&m_Vertex, outVertex, m_TexGenSpecialCase);
m_SetupUnit->SetupVertex();
m_SetupUnit->SetupVertex();
INCSTAT(swstats.thisFrame.numVerticesLoaded)
INCSTAT(swstats.thisFrame.numVerticesLoaded)
}
void SWVertexLoader::AddAttributeLoader(AttributeLoader loader, u8 index)
{
_assert_msg_(VIDEO, m_NumAttributeLoaders < 21, "Too many attribute loaders");
m_AttributeLoaders[m_NumAttributeLoaders].loader = loader;
m_AttributeLoaders[m_NumAttributeLoaders++].index = index;
_assert_msg_(VIDEO, m_NumAttributeLoaders < 21, "Too many attribute loaders");
m_AttributeLoaders[m_NumAttributeLoaders].loader = loader;
m_AttributeLoaders[m_NumAttributeLoaders++].index = index;
}
void SWVertexLoader::LoadPosMtx(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 unused)
{
vertex->posMtx = DataReadU8() & 0x3f;
vertex->posMtx = DataReadU8() & 0x3f;
}
void SWVertexLoader::LoadTexMtx(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 index)
{
vertex->texMtx[index] = DataReadU8() & 0x3f;
}
vertex->texMtx[index] = DataReadU8() & 0x3f;
}
void SWVertexLoader::LoadPosition(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 unused)
{
VertexManager::s_pCurBufferPointer = (u8*)&vertex->position;
vertexLoader->m_positionLoader();
VertexManager::s_pCurBufferPointer = (u8*)&vertex->position;
vertexLoader->m_positionLoader();
}
void SWVertexLoader::LoadNormal(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 unused)
{
VertexManager::s_pCurBufferPointer = (u8*)&vertex->normal;
vertexLoader->m_normalLoader();
vertexLoader->m_normalLoader();
}
void SWVertexLoader::LoadColor(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 index)
{
u32 color;
VertexManager::s_pCurBufferPointer = (u8*)&color;
colIndex = index;
vertexLoader->m_colorLoader[index]();
u32 color;
VertexManager::s_pCurBufferPointer = (u8*)&color;
colIndex = index;
vertexLoader->m_colorLoader[index]();
// rgba -> abgr
*(u32*)vertex->color[index] = Common::swap32(color);
// rgba -> abgr
*(u32*)vertex->color[index] = Common::swap32(color);
}
void SWVertexLoader::LoadTexCoord(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 index)
{
VertexManager::s_pCurBufferPointer = (u8*)&vertex->texCoords[index];
tcIndex = index;
vertexLoader->m_texCoordLoader[index]();
VertexManager::s_pCurBufferPointer = (u8*)&vertex->texCoords[index];
tcIndex = index;
vertexLoader->m_texCoordLoader[index]();
}
void SWVertexLoader::DoState(PointerWrap &p)
@ -339,4 +344,4 @@ void SWVertexLoader::DoState(PointerWrap &p)
p.Do(m_NumAttributeLoaders);
m_SetupUnit->DoState(p);
p.Do(m_TexGenSpecialCase);
}
}

View File

@ -12,7 +12,7 @@
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// Official Git repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _VERTEXLOADER_H_
@ -28,48 +28,48 @@ class SetupUnit;
class SWVertexLoader
{
u32 m_VertexSize;
u32 m_VertexSize;
VAT* m_CurrentVat;
TPipelineFunction m_positionLoader;
TPipelineFunction m_normalLoader;
TPipelineFunction m_colorLoader[2];
TPipelineFunction m_texCoordLoader[8];
VAT* m_CurrentVat;
InputVertexData m_Vertex;
TPipelineFunction m_positionLoader;
TPipelineFunction m_normalLoader;
TPipelineFunction m_colorLoader[2];
TPipelineFunction m_texCoordLoader[8];
typedef void (*AttributeLoader)(SWVertexLoader*, InputVertexData*, u8);
struct AttrLoaderCall
{
AttributeLoader loader;
u8 index;
};
AttrLoaderCall m_AttributeLoaders[1+8+1+1+2+8];
int m_NumAttributeLoaders;
void AddAttributeLoader(AttributeLoader loader, u8 index=0);
InputVertexData m_Vertex;
// attribute loader functions
static void LoadPosMtx(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 unused);
static void LoadTexMtx(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 index);
static void LoadPosition(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 unused);
static void LoadNormal(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 unused);
static void LoadColor(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 index);
static void LoadTexCoord(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 index);
typedef void (*AttributeLoader)(SWVertexLoader*, InputVertexData*, u8);
struct AttrLoaderCall
{
AttributeLoader loader;
u8 index;
};
AttrLoaderCall m_AttributeLoaders[1+8+1+1+2+8];
int m_NumAttributeLoaders;
void AddAttributeLoader(AttributeLoader loader, u8 index=0);
SetupUnit *m_SetupUnit;
// attribute loader functions
static void LoadPosMtx(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 unused);
static void LoadTexMtx(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 index);
static void LoadPosition(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 unused);
static void LoadNormal(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 unused);
static void LoadColor(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 index);
static void LoadTexCoord(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 index);
SetupUnit *m_SetupUnit;
bool m_TexGenSpecialCase;
public:
SWVertexLoader();
~SWVertexLoader();
SWVertexLoader();
~SWVertexLoader();
void SetFormat(u8 attributeIndex, u8 primitiveType);
void SetFormat(u8 attributeIndex, u8 primitiveType);
u32 GetVertexSize() { return m_VertexSize; }
u32 GetVertexSize() { return m_VertexSize; }
void LoadVertex();
void LoadVertex();
void DoState(PointerWrap &p);
};

View File

@ -12,7 +12,7 @@
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// Official Git repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "FileUtil.h"

View File

@ -12,7 +12,7 @@
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// Official Git repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _VIDEOSOFTWARE_CONFIG_H_
@ -25,14 +25,14 @@
// NEVER inherit from this class.
struct SWVideoConfig : NonCopyable
{
SWVideoConfig();
void Load(const char* ini_file);
void Save(const char* ini_file);
SWVideoConfig();
void Load(const char* ini_file);
void Save(const char* ini_file);
// General
bool bFullscreen;
bool bHideCursor;
bool renderToMainframe;
// General
bool bFullscreen;
bool bHideCursor;
bool renderToMainframe;
bool bHwRasterizer;
@ -40,18 +40,18 @@ struct SWVideoConfig : NonCopyable
bool bZComploc;
bool bZFreeze;
bool bShowStats;
bool bShowStats;
bool bDumpTextures;
bool bDumpObjects;
bool bDumpFrames;
bool bDumpTextures;
bool bDumpObjects;
bool bDumpFrames;
// Debug only
bool bDumpTevStages;
bool bDumpTevStages;
bool bDumpTevTextureFetches;
u32 drawStart;
u32 drawEnd;
u32 drawStart;
u32 drawEnd;
};
extern SWVideoConfig g_SWVideoConfig;

View File

@ -12,7 +12,7 @@
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// Official Git repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
@ -213,30 +213,32 @@ u32 VideoSoftware::Video_AccessEFB(EFBAccessType type, u32 x, u32 y, u32 InputDa
{
u32 value = 0;
switch (type)
{
case PEEK_Z:
{
value = EfbInterface::GetDepth(x, y);
break;
}
case POKE_Z:
break;
case PEEK_COLOR:
{
u32 color = 0;
EfbInterface::GetColor(x, y, (u8*)&color);
switch (type)
{
case PEEK_Z:
{
value = EfbInterface::GetDepth(x, y);
break;
}
// rgba to argb
value = (color >> 8) | (color & 0xff) << 24;
break;
}
case POKE_COLOR:
break;
}
case POKE_Z:
break;
return value;
case PEEK_COLOR:
{
u32 color = 0;
EfbInterface::GetColor(x, y, (u8*)&color);
// rgba to argb
value = (color >> 8) | (color & 0xff) << 24;
break;
}
case POKE_COLOR:
break;
}
return value;
}
u32 VideoSoftware::Video_GetQueryResult(PerfQueryType type)
@ -256,7 +258,7 @@ bool VideoSoftware::Video_Screenshot(const char *_szFilename)
void VideoSoftware::Video_EnterLoop()
{
std::lock_guard<std::mutex> lk(m_csSWVidOccupied);
fifoStateRun = true;
fifoStateRun = true;
while (fifoStateRun)
{
@ -279,7 +281,7 @@ void VideoSoftware::Video_EnterLoop()
void VideoSoftware::Video_ExitLoop()
{
fifoStateRun = false;
fifoStateRun = false;
}
// TODO : could use the OSD class in video common, we would need to implement the Renderer class

View File

@ -12,7 +12,7 @@
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// Official Git repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "SetupUnit.h"
@ -27,7 +27,7 @@ void SetupUnit::Init(u8 primitiveType)
{
m_PrimType = primitiveType;
m_VertexCounter = 0;
m_VertexCounter = 0;
m_VertPointer[0] = &m_Vertices[0];
m_VertPointer[1] = &m_Vertices[1];
m_VertPointer[2] = &m_Vertices[2];
@ -36,130 +36,130 @@ void SetupUnit::Init(u8 primitiveType)
void SetupUnit::SetupVertex()
{
switch(m_PrimType)
{
case GX_DRAW_QUADS:
SetupQuad();
break;
case GX_DRAW_TRIANGLES:
SetupTriangle();
break;
case GX_DRAW_TRIANGLE_STRIP:
SetupTriStrip();
break;
case GX_DRAW_TRIANGLE_FAN:
SetupTriFan();
break;
case GX_DRAW_LINES:
SetupLine();
break;
case GX_DRAW_LINE_STRIP:
SetupLineStrip();
break;
case GX_DRAW_POINTS:
SetupPoint();
break;
}
switch(m_PrimType)
{
case GX_DRAW_QUADS:
SetupQuad();
break;
case GX_DRAW_TRIANGLES:
SetupTriangle();
break;
case GX_DRAW_TRIANGLE_STRIP:
SetupTriStrip();
break;
case GX_DRAW_TRIANGLE_FAN:
SetupTriFan();
break;
case GX_DRAW_LINES:
SetupLine();
break;
case GX_DRAW_LINE_STRIP:
SetupLineStrip();
break;
case GX_DRAW_POINTS:
SetupPoint();
break;
}
}
void SetupUnit::SetupQuad()
{
if (m_VertexCounter < 2)
{
m_VertexCounter++;
m_VertWritePointer = m_VertPointer[m_VertexCounter];
return;
}
void SetupUnit::SetupQuad()
{
if (m_VertexCounter < 2)
{
m_VertexCounter++;
m_VertWritePointer = m_VertPointer[m_VertexCounter];
return;
}
Clipper::ProcessTriangle(m_VertPointer[0], m_VertPointer[1], m_VertPointer[2]);
Clipper::ProcessTriangle(m_VertPointer[0], m_VertPointer[1], m_VertPointer[2]);
m_VertexCounter++;
m_VertexCounter &= 3;
m_VertWritePointer = &m_Vertices[m_VertexCounter & 1];
OutputVertexData* temp = m_VertPointer[1];
m_VertPointer[1] = m_VertPointer[2];
m_VertPointer[2] = temp;
}
m_VertexCounter++;
m_VertexCounter &= 3;
m_VertWritePointer = &m_Vertices[m_VertexCounter & 1];
OutputVertexData* temp = m_VertPointer[1];
m_VertPointer[1] = m_VertPointer[2];
m_VertPointer[2] = temp;
}
void SetupUnit::SetupTriangle()
{
if (m_VertexCounter < 2)
{
m_VertexCounter++;
m_VertWritePointer = m_VertPointer[m_VertexCounter];
return;
}
if (m_VertexCounter < 2)
{
m_VertexCounter++;
m_VertWritePointer = m_VertPointer[m_VertexCounter];
return;
}
Clipper::ProcessTriangle(m_VertPointer[0], m_VertPointer[1], m_VertPointer[2]);
Clipper::ProcessTriangle(m_VertPointer[0], m_VertPointer[1], m_VertPointer[2]);
m_VertexCounter = 0;
m_VertWritePointer = m_VertPointer[0];
m_VertexCounter = 0;
m_VertWritePointer = m_VertPointer[0];
}
void SetupUnit::SetupTriStrip()
{
if (m_VertexCounter < 2)
{
m_VertexCounter++;
m_VertWritePointer = m_VertPointer[m_VertexCounter];
return;
}
if (m_VertexCounter < 2)
{
m_VertexCounter++;
m_VertWritePointer = m_VertPointer[m_VertexCounter];
return;
}
Clipper::ProcessTriangle(m_VertPointer[0], m_VertPointer[1], m_VertPointer[2]);
Clipper::ProcessTriangle(m_VertPointer[0], m_VertPointer[1], m_VertPointer[2]);
m_VertexCounter++;
m_VertPointer[2 - (m_VertexCounter & 1)] = m_VertPointer[0];
m_VertWritePointer = m_VertPointer[0];
m_VertexCounter++;
m_VertPointer[2 - (m_VertexCounter & 1)] = m_VertPointer[0];
m_VertWritePointer = m_VertPointer[0];
m_VertPointer[0] = &m_Vertices[(m_VertexCounter + 1) % 3];
m_VertPointer[0] = &m_Vertices[(m_VertexCounter + 1) % 3];
}
void SetupUnit::SetupTriFan()
{
if (m_VertexCounter < 2)
{
m_VertexCounter++;
m_VertWritePointer = m_VertPointer[m_VertexCounter];
return;
}
if (m_VertexCounter < 2)
{
m_VertexCounter++;
m_VertWritePointer = m_VertPointer[m_VertexCounter];
return;
}
Clipper::ProcessTriangle(m_VertPointer[0], m_VertPointer[1], m_VertPointer[2]);
Clipper::ProcessTriangle(m_VertPointer[0], m_VertPointer[1], m_VertPointer[2]);
m_VertexCounter++;
m_VertPointer[1] = m_VertPointer[2];
m_VertPointer[2] = &m_Vertices[2 - (m_VertexCounter & 1)];
m_VertexCounter++;
m_VertPointer[1] = m_VertPointer[2];
m_VertPointer[2] = &m_Vertices[2 - (m_VertexCounter & 1)];
m_VertWritePointer = m_VertPointer[2];
m_VertWritePointer = m_VertPointer[2];
}
void SetupUnit::SetupLine()
{
if (m_VertexCounter < 1)
{
m_VertexCounter++;
m_VertWritePointer = m_VertPointer[m_VertexCounter];
return;
}
{
m_VertexCounter++;
m_VertWritePointer = m_VertPointer[m_VertexCounter];
return;
}
Clipper::ProcessLine(m_VertPointer[0], m_VertPointer[1]);
Clipper::ProcessLine(m_VertPointer[0], m_VertPointer[1]);
m_VertexCounter = 0;
m_VertWritePointer = m_VertPointer[0];
m_VertexCounter = 0;
m_VertWritePointer = m_VertPointer[0];
}
void SetupUnit::SetupLineStrip()
{
if (m_VertexCounter < 1)
{
m_VertexCounter++;
{
m_VertexCounter++;
m_VertWritePointer = m_VertPointer[m_VertexCounter];
return;
}
return;
}
m_VertexCounter++;
Clipper::ProcessLine(m_VertPointer[0], m_VertPointer[1]);
Clipper::ProcessLine(m_VertPointer[0], m_VertPointer[1]);
m_VertWritePointer = m_VertPointer[0];

View File

@ -12,7 +12,7 @@
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// Official Git repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
@ -25,27 +25,27 @@
class SetupUnit
{
u8 m_PrimType;
int m_VertexCounter;
u8 m_PrimType;
int m_VertexCounter;
OutputVertexData m_Vertices[3];
OutputVertexData *m_VertPointer[3];
OutputVertexData *m_VertWritePointer;
void SetupQuad();
void SetupTriangle();
void SetupTriStrip();
void SetupTriFan();
void SetupLine();
void SetupLineStrip();
void SetupPoint();
OutputVertexData m_Vertices[3];
OutputVertexData *m_VertPointer[3];
OutputVertexData *m_VertWritePointer;
void SetupQuad();
void SetupTriangle();
void SetupTriStrip();
void SetupTriFan();
void SetupLine();
void SetupLineStrip();
void SetupPoint();
public:
void Init(u8 primitiveType);
void Init(u8 primitiveType);
OutputVertexData* GetVertex() { return m_VertWritePointer; }
OutputVertexData* GetVertex() { return m_VertWritePointer; }
void SetupVertex();
void SetupVertex();
void DoState(PointerWrap &p);
};

File diff suppressed because it is too large Load Diff

View File

@ -12,7 +12,7 @@
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// Official Git repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _TEV_H_
@ -23,12 +23,13 @@
class Tev
{
struct InputRegType {
unsigned a : 8;
unsigned b : 8;
unsigned c : 8;
signed d : 11;
};
struct InputRegType
{
unsigned a : 8;
unsigned b : 8;
unsigned c : 8;
signed d : 11;
};
struct TextureCoordinateType
{
@ -36,26 +37,26 @@ class Tev
signed t : 24;
};
// color order: ABGR
s16 Reg[4][4];
s16 KonstantColors[4][4];
s16 TexColor[4];
s16 RasColor[4];
s16 StageKonst[4];
s16 Zero16[4];
// color order: ABGR
s16 Reg[4][4];
s16 KonstantColors[4][4];
s16 TexColor[4];
s16 RasColor[4];
s16 StageKonst[4];
s16 Zero16[4];
s16 FixedConstants[9];
u8 AlphaBump;
u8 IndirectTex[4][4];
u8 IndirectTex[4][4];
TextureCoordinateType TexCoord;
s16 *m_ColorInputLUT[16][3];
s16 *m_AlphaInputLUT[8]; // values must point to ABGR color
s16 *m_KonstLUT[32][4];
u8 *m_RasColorLUT[8];
s16 m_BiasLUT[4];
u8 m_ScaleLShiftLUT[4];
u8 m_ScaleRShiftLUT[4];
s16 *m_ColorInputLUT[16][3];
s16 *m_AlphaInputLUT[8]; // values must point to ABGR color
s16 *m_KonstLUT[32][4];
u8 *m_RasColorLUT[8];
s16 m_BiasLUT[4];
u8 m_ScaleLShiftLUT[4];
u8 m_ScaleRShiftLUT[4];
// enumeration for color input LUT
enum
@ -72,29 +73,29 @@ class Tev
INDIRECT = 32
};
void SetRasColor(int colorChan, int swaptable);
void SetRasColor(int colorChan, int swaptable);
void DrawColorRegular(TevStageCombiner::ColorCombiner &cc);
void DrawColorCompare(TevStageCombiner::ColorCombiner &cc);
void DrawAlphaRegular(TevStageCombiner::AlphaCombiner &ac);
void DrawAlphaCompare(TevStageCombiner::AlphaCombiner &ac);
void DrawColorRegular(TevStageCombiner::ColorCombiner &cc);
void DrawColorCompare(TevStageCombiner::ColorCombiner &cc);
void DrawAlphaRegular(TevStageCombiner::AlphaCombiner &ac);
void DrawAlphaCompare(TevStageCombiner::AlphaCombiner &ac);
void Indirect(unsigned int stageNum, s32 s, s32 t);
void Indirect(unsigned int stageNum, s32 s, s32 t);
public:
s32 Position[3];
u8 Color[2][4]; // must be RGBA for correct swap table ordering
TextureCoordinateType Uv[8];
s32 IndirectLod[4];
u8 Color[2][4]; // must be RGBA for correct swap table ordering
TextureCoordinateType Uv[8];
s32 IndirectLod[4];
bool IndirectLinear[4];
s32 TextureLod[16];
bool TextureLinear[16];
void Init();
void Init();
void Draw();
void Draw();
void SetRegColor(int reg, int comp, bool konst, s16 color);
void SetRegColor(int reg, int comp, bool konst, s16 color);
enum { ALP_C, BLU_C, GRN_C, RED_C };

File diff suppressed because it is too large Load Diff

View File

@ -12,7 +12,7 @@
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// Official Git repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
@ -23,7 +23,7 @@
namespace TextureEncoder
{
void Encode(u8 *dest_ptr);
void Encode(u8 *dest_ptr);
}
#endif

View File

@ -11,7 +11,7 @@
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// Official Git repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
@ -30,51 +30,51 @@ namespace TextureSampler
inline void WrapCoord(int &coord, int wrapMode, int imageSize)
{
switch (wrapMode)
{
case 0: // clamp
coord = (coord>imageSize)?imageSize:(coord<0)?0:coord;
break;
case 1: // wrap
coord = coord % (imageSize + 1);
coord = (coord<0)?imageSize+coord:coord;
break;
case 2: // mirror
{
int sizePlus1 = imageSize + 1;
int div = coord / sizePlus1;
coord = coord - (div * sizePlus1);
coord = (coord<0)?-coord:coord;
coord = (div&1)?imageSize - coord:coord;
}
break;
}
switch (wrapMode)
{
case 0: // clamp
coord = (coord>imageSize)?imageSize:(coord<0)?0:coord;
break;
case 1: // wrap
coord = coord % (imageSize + 1);
coord = (coord<0)?imageSize+coord:coord;
break;
case 2: // mirror
{
int sizePlus1 = imageSize + 1;
int div = coord / sizePlus1;
coord = coord - (div * sizePlus1);
coord = (coord<0)?-coord:coord;
coord = (div&1)?imageSize - coord:coord;
}
break;
}
}
inline void SetTexel(u8 *inTexel, u32 *outTexel, u32 fract)
{
outTexel[0] = inTexel[0] * fract;
outTexel[1] = inTexel[1] * fract;
outTexel[2] = inTexel[2] * fract;
outTexel[3] = inTexel[3] * fract;
outTexel[0] = inTexel[0] * fract;
outTexel[1] = inTexel[1] * fract;
outTexel[2] = inTexel[2] * fract;
outTexel[3] = inTexel[3] * fract;
}
inline void AddTexel(u8 *inTexel, u32 *outTexel, u32 fract)
{
outTexel[0] += inTexel[0] * fract;
outTexel[1] += inTexel[1] * fract;
outTexel[2] += inTexel[2] * fract;
outTexel[3] += inTexel[3] * fract;
outTexel[0] += inTexel[0] * fract;
outTexel[1] += inTexel[1] * fract;
outTexel[2] += inTexel[2] * fract;
outTexel[3] += inTexel[3] * fract;
}
void Sample(s32 s, s32 t, s32 lod, bool linear, u8 texmap, u8 *sample)
{
int baseMip = 0;
int baseMip = 0;
bool mipLinear = false;
#if (ALLOW_MIPMAP)
FourTexUnits& texUnit = bpmem.tex[(texmap >> 2) & 1];
TexMode0& tm0 = texUnit.texMode0[texmap & 3];
TexMode0& tm0 = texUnit.texMode0[texmap & 3];
s32 lodFract = lod & 0xf;
@ -91,7 +91,7 @@ void Sample(s32 s, s32 t, s32 lod, bool linear, u8 texmap, u8 *sample)
if (mipLinear)
{
u8 sampledTex[4];
u32 texel[4];
u32 texel[4];
SampleMip(s, t, baseMip, linear, texmap, sampledTex);
SetTexel(sampledTex, texel, (16 - lodFract));
@ -100,25 +100,25 @@ void Sample(s32 s, s32 t, s32 lod, bool linear, u8 texmap, u8 *sample)
AddTexel(sampledTex, texel, lodFract);
sample[0] = (u8)(texel[0] >> 4);
sample[1] = (u8)(texel[1] >> 4);
sample[2] = (u8)(texel[2] >> 4);
sample[3] = (u8)(texel[3] >> 4);
sample[1] = (u8)(texel[1] >> 4);
sample[2] = (u8)(texel[2] >> 4);
sample[3] = (u8)(texel[3] >> 4);
}
else
#endif
{
SampleMip(s, t, baseMip, linear, texmap, sample);
}
}
}
void SampleMip(s32 s, s32 t, s32 mip, bool linear, u8 texmap, u8 *sample)
{
FourTexUnits& texUnit = bpmem.tex[(texmap >> 2) & 1];
u8 subTexmap = texmap & 3;
u8 subTexmap = texmap & 3;
TexMode0& tm0 = texUnit.texMode0[subTexmap];
TexImage0& ti0 = texUnit.texImage0[subTexmap];
TexTLUT& texTlut = texUnit.texTlut[subTexmap];
TexMode0& tm0 = texUnit.texMode0[subTexmap];
TexImage0& ti0 = texUnit.texImage0[subTexmap];
TexTLUT& texTlut = texUnit.texTlut[subTexmap];
u8 *imageSrc, *imageSrcOdd = NULL;
if (texUnit.texImage1[subTexmap].image_type)
@ -129,7 +129,7 @@ void SampleMip(s32 s, s32 t, s32 mip, bool linear, u8 texmap, u8 *sample)
}
else
{
u32 imageBase = texUnit.texImage3[subTexmap].image_base << 5;
u32 imageBase = texUnit.texImage3[subTexmap].image_base << 5;
imageSrc = Memory::GetPointer(imageBase);
}
@ -167,8 +167,8 @@ void SampleMip(s32 s, s32 t, s32 mip, bool linear, u8 texmap, u8 *sample)
}
}
if (linear)
{
if (linear)
{
// offset linear sampling
s -= 64;
t -= 64;
@ -179,18 +179,18 @@ void SampleMip(s32 s, s32 t, s32 mip, bool linear, u8 texmap, u8 *sample)
// linear sampling
int imageSPlus1 = imageS + 1;
int fractS = s & 0x7f;
int imageTPlus1 = imageT + 1;
int fractT = t & 0x7f;
int fractS = s & 0x7f;
u8 sampledTex[4];
u32 texel[4];
int imageTPlus1 = imageT + 1;
int fractT = t & 0x7f;
WrapCoord(imageS, tm0.wrap_s, imageWidth);
WrapCoord(imageT, tm0.wrap_t, imageHeight);
WrapCoord(imageSPlus1, tm0.wrap_s, imageWidth);
WrapCoord(imageTPlus1, tm0.wrap_t, imageHeight);
u8 sampledTex[4];
u32 texel[4];
WrapCoord(imageS, tm0.wrap_s, imageWidth);
WrapCoord(imageT, tm0.wrap_t, imageHeight);
WrapCoord(imageSPlus1, tm0.wrap_s, imageWidth);
WrapCoord(imageTPlus1, tm0.wrap_t, imageHeight);
if (!(ti0.format == GX_TF_RGBA8 && texUnit.texImage1[subTexmap].image_type))
{
@ -221,26 +221,26 @@ void SampleMip(s32 s, s32 t, s32 mip, bool linear, u8 texmap, u8 *sample)
AddTexel(sampledTex, texel, (fractS) * (fractT));
}
sample[0] = (u8)(texel[0] >> 14);
sample[1] = (u8)(texel[1] >> 14);
sample[2] = (u8)(texel[2] >> 14);
sample[3] = (u8)(texel[3] >> 14);
}
else
{
sample[0] = (u8)(texel[0] >> 14);
sample[1] = (u8)(texel[1] >> 14);
sample[2] = (u8)(texel[2] >> 14);
sample[3] = (u8)(texel[3] >> 14);
}
else
{
// integer part of sample location
int imageS = s >> 7;
int imageT = t >> 7;
// nearest neighbor sampling
// nearest neighbor sampling
WrapCoord(imageS, tm0.wrap_s, imageWidth);
WrapCoord(imageT, tm0.wrap_t, imageHeight);
WrapCoord(imageT, tm0.wrap_t, imageHeight);
if (!(ti0.format == GX_TF_RGBA8 && texUnit.texImage1[subTexmap].image_type))
TexDecoder_DecodeTexel(sample, imageSrc, imageS, imageT, imageWidth, ti0.format, tlutAddress, texTlut.tlut_format);
TexDecoder_DecodeTexel(sample, imageSrc, imageS, imageT, imageWidth, ti0.format, tlutAddress, texTlut.tlut_format);
else
TexDecoder_DecodeTexelRGBA8FromTmem(sample, imageSrc, imageSrcOdd, imageS, imageT, imageWidth);
}
TexDecoder_DecodeTexelRGBA8FromTmem(sample, imageSrc, imageSrcOdd, imageS, imageT, imageWidth);
}
}
}

View File

@ -12,7 +12,7 @@
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// Official Git repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _TEXTURESAMPLER_H_

View File

@ -12,7 +12,7 @@
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// Official Git repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "Common.h"
@ -33,114 +33,114 @@ namespace TransformUnit
void MultiplyVec2Mat24(const Vec3 &vec, const float *mat, Vec3 &result)
{
result.x = mat[0] * vec.x + mat[1] * vec.y + mat[2] + mat[3];
result.y = mat[4] * vec.x + mat[5] * vec.y + mat[6] + mat[7];
result.x = mat[0] * vec.x + mat[1] * vec.y + mat[2] + mat[3];
result.y = mat[4] * vec.x + mat[5] * vec.y + mat[6] + mat[7];
result.z = 1.0f;
}
void MultiplyVec2Mat34(const Vec3 &vec, const float *mat, Vec3 &result)
{
result.x = mat[0] * vec.x + mat[1] * vec.y + mat[2] + mat[3];
result.y = mat[4] * vec.x + mat[5] * vec.y + mat[6] + mat[7];
result.z = mat[8] * vec.x + mat[9] * vec.y + mat[10] + mat[11];
result.x = mat[0] * vec.x + mat[1] * vec.y + mat[2] + mat[3];
result.y = mat[4] * vec.x + mat[5] * vec.y + mat[6] + mat[7];
result.z = mat[8] * vec.x + mat[9] * vec.y + mat[10] + mat[11];
}
void MultiplyVec3Mat33(const Vec3 &vec, const float *mat, Vec3 &result)
{
result.x = mat[0] * vec.x + mat[1] * vec.y + mat[2] * vec.z;
result.y = mat[3] * vec.x + mat[4] * vec.y + mat[5] * vec.z;
result.z = mat[6] * vec.x + mat[7] * vec.y + mat[8] * vec.z;
result.x = mat[0] * vec.x + mat[1] * vec.y + mat[2] * vec.z;
result.y = mat[3] * vec.x + mat[4] * vec.y + mat[5] * vec.z;
result.z = mat[6] * vec.x + mat[7] * vec.y + mat[8] * vec.z;
}
void MultiplyVec3Mat24(const Vec3 &vec, const float *mat, Vec3 &result)
{
result.x = mat[0] * vec.x + mat[1] * vec.y + mat[2] * vec.z + mat[3];
result.y = mat[4] * vec.x + mat[5] * vec.y + mat[6] * vec.z + mat[7];
result.z = 1.0f;
result.x = mat[0] * vec.x + mat[1] * vec.y + mat[2] * vec.z + mat[3];
result.y = mat[4] * vec.x + mat[5] * vec.y + mat[6] * vec.z + mat[7];
result.z = 1.0f;
}
void MultiplyVec3Mat34(const Vec3 &vec, const float *mat, Vec3 &result)
{
result.x = mat[0] * vec.x + mat[1] * vec.y + mat[2] * vec.z + mat[3];
result.y = mat[4] * vec.x + mat[5] * vec.y + mat[6] * vec.z + mat[7];
result.z = mat[8] * vec.x + mat[9] * vec.y + mat[10] * vec.z + mat[11];
result.x = mat[0] * vec.x + mat[1] * vec.y + mat[2] * vec.z + mat[3];
result.y = mat[4] * vec.x + mat[5] * vec.y + mat[6] * vec.z + mat[7];
result.z = mat[8] * vec.x + mat[9] * vec.y + mat[10] * vec.z + mat[11];
}
void MultipleVec3Perspective(const Vec3 &vec, const float *proj, Vec4 &result)
{
result.x = proj[0] * vec.x + proj[1] * vec.z;
result.y = proj[2] * vec.y + proj[3] * vec.z;
//result.z = (proj[4] * vec.z + proj[5]);
result.z = (proj[4] * vec.z + proj[5]) * (1.0f - (float)1e-7);
result.w = -vec.z;
result.x = proj[0] * vec.x + proj[1] * vec.z;
result.y = proj[2] * vec.y + proj[3] * vec.z;
//result.z = (proj[4] * vec.z + proj[5]);
result.z = (proj[4] * vec.z + proj[5]) * (1.0f - (float)1e-7);
result.w = -vec.z;
}
void MultipleVec3Ortho(const Vec3 &vec, const float *proj, Vec4 &result)
{
result.x = proj[0] * vec.x + proj[1];
result.y = proj[2] * vec.y + proj[3];
result.z = proj[4] * vec.z + proj[5];
result.w = 1;
result.x = proj[0] * vec.x + proj[1];
result.y = proj[2] * vec.y + proj[3];
result.z = proj[4] * vec.z + proj[5];
result.w = 1;
}
void TransformPosition(const InputVertexData *src, OutputVertexData *dst)
{
const float* mat = (const float*)&swxfregs.posMatrices[src->posMtx * 4];
MultiplyVec3Mat34(src->position, mat, dst->mvPosition);
const float* mat = (const float*)&swxfregs.posMatrices[src->posMtx * 4];
MultiplyVec3Mat34(src->position, mat, dst->mvPosition);
if (swxfregs.projection.type == GX_PERSPECTIVE)
{
MultipleVec3Perspective(dst->mvPosition, swxfregs.projection.rawProjection, dst->projectedPosition);
}
else
{
MultipleVec3Ortho(dst->mvPosition, swxfregs.projection.rawProjection, dst->projectedPosition);
}
if (swxfregs.projection.type == GX_PERSPECTIVE)
{
MultipleVec3Perspective(dst->mvPosition, swxfregs.projection.rawProjection, dst->projectedPosition);
}
else
{
MultipleVec3Ortho(dst->mvPosition, swxfregs.projection.rawProjection, dst->projectedPosition);
}
}
void TransformNormal(const InputVertexData *src, bool nbt, OutputVertexData *dst)
{
const float* mat = (const float*)&swxfregs.normalMatrices[(src->posMtx & 31) * 3];
const float* mat = (const float*)&swxfregs.normalMatrices[(src->posMtx & 31) * 3];
if (nbt)
{
MultiplyVec3Mat33(src->normal[0], mat, dst->normal[0]);
MultiplyVec3Mat33(src->normal[1], mat, dst->normal[1]);
MultiplyVec3Mat33(src->normal[2], mat, dst->normal[2]);
dst->normal[0].normalize();
}
else
{
MultiplyVec3Mat33(src->normal[0], mat, dst->normal[0]);
dst->normal[0].normalize();
}
if (nbt)
{
MultiplyVec3Mat33(src->normal[0], mat, dst->normal[0]);
MultiplyVec3Mat33(src->normal[1], mat, dst->normal[1]);
MultiplyVec3Mat33(src->normal[2], mat, dst->normal[2]);
dst->normal[0].normalize();
}
else
{
MultiplyVec3Mat33(src->normal[0], mat, dst->normal[0]);
dst->normal[0].normalize();
}
}
void TransformTexCoordRegular(const TexMtxInfo &texinfo, int coordNum, bool specialCase, const InputVertexData *srcVertex, OutputVertexData *dstVertex)
{
const Vec3 *src;
switch (texinfo.sourcerow)
{
case XF_SRCGEOM_INROW:
src = &srcVertex->position;
break;
case XF_SRCNORMAL_INROW:
src = &srcVertex->normal[0];
break;
case XF_SRCBINORMAL_T_INROW:
src = &srcVertex->normal[1];
break;
case XF_SRCBINORMAL_B_INROW:
src = &srcVertex->normal[2];
break;
default:
_assert_(texinfo.sourcerow >= XF_SRCTEX0_INROW && texinfo.sourcerow <= XF_SRCTEX7_INROW);
src = (Vec3*)srcVertex->texCoords[texinfo.sourcerow - XF_SRCTEX0_INROW];
break;
}
const Vec3 *src;
switch (texinfo.sourcerow)
{
case XF_SRCGEOM_INROW:
src = &srcVertex->position;
break;
case XF_SRCNORMAL_INROW:
src = &srcVertex->normal[0];
break;
case XF_SRCBINORMAL_T_INROW:
src = &srcVertex->normal[1];
break;
case XF_SRCBINORMAL_B_INROW:
src = &srcVertex->normal[2];
break;
default:
_assert_(texinfo.sourcerow >= XF_SRCTEX0_INROW && texinfo.sourcerow <= XF_SRCTEX7_INROW);
src = (Vec3*)srcVertex->texCoords[texinfo.sourcerow - XF_SRCTEX0_INROW];
break;
}
const float *mat = (const float*)&swxfregs.posMatrices[srcVertex->texMtx[coordNum] * 4];
Vec3 *dst = &dstVertex->texCoords[coordNum];
const float *mat = (const float*)&swxfregs.posMatrices[srcVertex->texMtx[coordNum] * 4];
Vec3 *dst = &dstVertex->texCoords[coordNum];
if (texinfo.projection == XF_TEXPROJ_ST)
{
@ -159,12 +159,12 @@ void TransformTexCoordRegular(const TexMtxInfo &texinfo, int coordNum, bool spec
MultiplyVec3Mat34(*src, mat, *dst);
}
if (swxfregs.dualTexTrans)
{
Vec3 tempCoord;
if (swxfregs.dualTexTrans)
{
Vec3 tempCoord;
// normalize
const PostMtxInfo &postInfo = swxfregs.postMtxInfo[coordNum];
// normalize
const PostMtxInfo &postInfo = swxfregs.postMtxInfo[coordNum];
const float *postMat = (const float*)&swxfregs.postMatrices[postInfo.index * 4];
if (specialCase)
@ -180,7 +180,7 @@ void TransformTexCoordRegular(const TexMtxInfo &texinfo, int coordNum, bool spec
dst->z = 1.0f;
}
else
{
{
if (postInfo.normalize)
tempCoord = dst->normalized();
else
@ -188,320 +188,336 @@ void TransformTexCoordRegular(const TexMtxInfo &texinfo, int coordNum, bool spec
MultiplyVec3Mat34(tempCoord, postMat, *dst);
}
}
}
}
struct LightPointer
{
u32 reserved[3];
u8 color[4];
Vec3 cosatt;
Vec3 distatt;
Vec3 pos;
Vec3 dir;
u32 reserved[3];
u8 color[4];
Vec3 cosatt;
Vec3 distatt;
Vec3 pos;
Vec3 dir;
};
inline void AddIntegerColor(const u8 *src, Vec3 &dst)
{
dst.x += src[1];
dst.y += src[2];
dst.z += src[3];
dst.x += src[1];
dst.y += src[2];
dst.z += src[3];
}
inline void AddScaledIntegerColor(const u8 *src, float scale, Vec3 &dst)
{
dst.x += src[1] * scale;
dst.y += src[2] * scale;
dst.z += src[3] * scale;
dst.x += src[1] * scale;
dst.y += src[2] * scale;
dst.z += src[3] * scale;
}
inline float Clamp(float val, float a, float b)
{
return val<a?a:val>b?b:val;
return val<a?a:val>b?b:val;
}
inline float SafeDivide(float n, float d)
{
return (d==0)?(n>0?1:0):n/d;
return (d==0) ? (n>0?1:0) : n/d;
}
void LightColor(const Vec3 &pos, const Vec3 &normal, u8 lightNum, const LitChannel &chan, Vec3 &lightCol)
{
const LightPointer *light = (const LightPointer*)&swxfregs.lights[0x10*lightNum];
const LightPointer *light = (const LightPointer*)&swxfregs.lights[0x10*lightNum];
if (!(chan.attnfunc & 1)) {
// atten disabled
switch (chan.diffusefunc) {
case LIGHTDIF_NONE:
AddIntegerColor(light->color, lightCol);
break;
case LIGHTDIF_SIGN:
{
Vec3 ldir = (light->pos - pos).normalized();
float diffuse = ldir * normal;
AddScaledIntegerColor(light->color, diffuse, lightCol);
}
break;
case LIGHTDIF_CLAMP:
{
Vec3 ldir = (light->pos - pos).normalized();
float diffuse = max(0.0f, ldir * normal);
AddScaledIntegerColor(light->color, diffuse, lightCol);
}
break;
default: _assert_(0);
}
}
else { // spec and spot
// not sure about divide by zero checks
Vec3 ldir = light->pos - pos;
float attn;
if (!(chan.attnfunc & 1))
{
// atten disabled
switch (chan.diffusefunc)
{
case LIGHTDIF_NONE:
AddIntegerColor(light->color, lightCol);
break;
case LIGHTDIF_SIGN:
{
Vec3 ldir = (light->pos - pos).normalized();
float diffuse = ldir * normal;
AddScaledIntegerColor(light->color, diffuse, lightCol);
}
break;
case LIGHTDIF_CLAMP:
{
Vec3 ldir = (light->pos - pos).normalized();
float diffuse = max(0.0f, ldir * normal);
AddScaledIntegerColor(light->color, diffuse, lightCol);
}
break;
default: _assert_(0);
}
}
else // spec and spot
{
// not sure about divide by zero checks
Vec3 ldir = light->pos - pos;
float attn;
if (chan.attnfunc == 3) { // spot
float dist2 = ldir.length2();
float dist = sqrtf(dist2);
ldir = ldir / dist;
attn = max(0.0f, ldir * light->dir);
if (chan.attnfunc == 3) // spot
{
float dist2 = ldir.length2();
float dist = sqrtf(dist2);
ldir = ldir / dist;
attn = max(0.0f, ldir * light->dir);
float cosAtt = light->cosatt.x + (light->cosatt.y * attn) + (light->cosatt.z * attn * attn);
float distAtt = light->distatt.x + (light->distatt.y * dist) + (light->distatt.z * dist2);
attn = SafeDivide(max(0.0f, cosAtt), distAtt);
}
else if (chan.attnfunc == 1) { // specular
// donko - what is going on here? 655.36 is a guess but seems about right.
attn = (light->pos * normal) > -655.36 ? max(0.0f, (light->dir * normal)) : 0;
ldir.set(1.0f, attn, attn * attn);
float cosAtt = light->cosatt.x + (light->cosatt.y * attn) + (light->cosatt.z * attn * attn);
float distAtt = light->distatt.x + (light->distatt.y * dist) + (light->distatt.z * dist2);
attn = SafeDivide(max(0.0f, cosAtt), distAtt);
}
else if (chan.attnfunc == 1) // specular
{
// donko - what is going on here? 655.36 is a guess but seems about right.
attn = (light->pos * normal) > -655.36 ? max(0.0f, (light->dir * normal)) : 0;
ldir.set(1.0f, attn, attn * attn);
float cosAtt = max(0.0f, light->cosatt * ldir);
float distAtt = light->distatt * ldir;
attn = SafeDivide(max(0.0f, cosAtt), distAtt);
} else {
PanicAlert("LightColor");
return;
}
float cosAtt = max(0.0f, light->cosatt * ldir);
float distAtt = light->distatt * ldir;
attn = SafeDivide(max(0.0f, cosAtt), distAtt);
}
else
{
PanicAlert("LightColor");
return;
}
switch (chan.diffusefunc) {
case LIGHTDIF_NONE:
AddScaledIntegerColor(light->color, attn, lightCol);
break;
case LIGHTDIF_SIGN:
{
float difAttn = ldir * normal;
AddScaledIntegerColor(light->color, attn * difAttn, lightCol);
}
break;
switch (chan.diffusefunc)
{
case LIGHTDIF_NONE:
AddScaledIntegerColor(light->color, attn, lightCol);
break;
case LIGHTDIF_SIGN:
{
float difAttn = ldir * normal;
AddScaledIntegerColor(light->color, attn * difAttn, lightCol);
}
break;
case LIGHTDIF_CLAMP:
{
float difAttn = max(0.0f, ldir * normal);
AddScaledIntegerColor(light->color, attn * difAttn, lightCol);
}
break;
default: _assert_(0);
}
}
case LIGHTDIF_CLAMP:
{
float difAttn = max(0.0f, ldir * normal);
AddScaledIntegerColor(light->color, attn * difAttn, lightCol);
}
break;
default: _assert_(0);
}
}
}
void LightAlpha(const Vec3 &pos, const Vec3 &normal, u8 lightNum, const LitChannel &chan, float &lightCol)
{
const LightPointer *light = (const LightPointer*)&swxfregs.lights[0x10*lightNum];
const LightPointer *light = (const LightPointer*)&swxfregs.lights[0x10*lightNum];
if (!(chan.attnfunc & 1)) {
// atten disabled
switch (chan.diffusefunc) {
case LIGHTDIF_NONE:
lightCol += light->color[0];
break;
case LIGHTDIF_SIGN:
{
Vec3 ldir = (light->pos - pos).normalized();
float diffuse = ldir * normal;
lightCol += light->color[0] * diffuse;
}
break;
case LIGHTDIF_CLAMP:
{
Vec3 ldir = (light->pos - pos).normalized();
float diffuse = max(0.0f, ldir * normal);
lightCol += light->color[0] * diffuse;
}
break;
default: _assert_(0);
}
}
else { // spec and spot
Vec3 ldir = light->pos - pos;
float attn;
if (!(chan.attnfunc & 1))
{
// atten disabled
switch (chan.diffusefunc)
{
case LIGHTDIF_NONE:
lightCol += light->color[0];
break;
case LIGHTDIF_SIGN:
{
Vec3 ldir = (light->pos - pos).normalized();
float diffuse = ldir * normal;
lightCol += light->color[0] * diffuse;
}
break;
case LIGHTDIF_CLAMP:
{
Vec3 ldir = (light->pos - pos).normalized();
float diffuse = max(0.0f, ldir * normal);
lightCol += light->color[0] * diffuse;
}
break;
default: _assert_(0);
}
}
else // spec and spot
{
Vec3 ldir = light->pos - pos;
float attn;
if (chan.attnfunc == 3) { // spot
float dist2 = ldir.length2();
float dist = sqrtf(dist2);
ldir = ldir / dist;
attn = max(0.0f, ldir * light->dir);
if (chan.attnfunc == 3) // spot
{
float dist2 = ldir.length2();
float dist = sqrtf(dist2);
ldir = ldir / dist;
attn = max(0.0f, ldir * light->dir);
float cosAtt = light->cosatt.x + (light->cosatt.y * attn) + (light->cosatt.z * attn * attn);
float distAtt = light->distatt.x + (light->distatt.y * dist) + (light->distatt.z * dist2);
attn = SafeDivide(max(0.0f, cosAtt), distAtt);
}
else /* if (chan.attnfunc == 1) */ { // specular
// donko - what is going on here? 655.36 is a guess but seems about right.
attn = (light->pos * normal) > -655.36 ? max(0.0f, (light->dir * normal)) : 0;
ldir.set(1.0f, attn, attn * attn);
float cosAtt = light->cosatt.x + (light->cosatt.y * attn) + (light->cosatt.z * attn * attn);
float distAtt = light->distatt.x + (light->distatt.y * dist) + (light->distatt.z * dist2);
attn = SafeDivide(max(0.0f, cosAtt), distAtt);
}
else /* if (chan.attnfunc == 1) */ // specular
{
// donko - what is going on here? 655.36 is a guess but seems about right.
attn = (light->pos * normal) > -655.36 ? max(0.0f, (light->dir * normal)) : 0;
ldir.set(1.0f, attn, attn * attn);
float cosAtt = light->cosatt * ldir;
float distAtt = light->distatt * ldir;
attn = SafeDivide(max(0.0f, cosAtt), distAtt);
}
float cosAtt = light->cosatt * ldir;
float distAtt = light->distatt * ldir;
attn = SafeDivide(max(0.0f, cosAtt), distAtt);
}
switch (chan.diffusefunc) {
case LIGHTDIF_NONE:
lightCol += light->color[0] * attn;
break;
case LIGHTDIF_SIGN:
{
float difAttn = ldir * normal;
lightCol += light->color[0] * attn * difAttn;
}
break;
switch (chan.diffusefunc)
{
case LIGHTDIF_NONE:
lightCol += light->color[0] * attn;
break;
case LIGHTDIF_SIGN:
{
float difAttn = ldir * normal;
lightCol += light->color[0] * attn * difAttn;
}
break;
case LIGHTDIF_CLAMP:
{
float difAttn = max(0.0f, ldir * normal);
lightCol += light->color[0] * attn * difAttn;
}
break;
default: _assert_(0);
}
}
case LIGHTDIF_CLAMP:
{
float difAttn = max(0.0f, ldir * normal);
lightCol += light->color[0] * attn * difAttn;
}
break;
default: _assert_(0);
}
}
}
void TransformColor(const InputVertexData *src, OutputVertexData *dst)
{
for (u32 chan = 0; chan < swxfregs.nNumChans; chan++)
{
// abgr
u8 matcolor[4];
u8 chancolor[4];
for (u32 chan = 0; chan < swxfregs.nNumChans; chan++)
{
// abgr
u8 matcolor[4];
u8 chancolor[4];
// color
LitChannel &colorchan = swxfregs.color[chan];
if (colorchan.matsource)
*(u32*)matcolor = *(u32*)src->color[chan]; // vertex
else
*(u32*)matcolor = swxfregs.matColor[chan];
// color
LitChannel &colorchan = swxfregs.color[chan];
if (colorchan.matsource)
*(u32*)matcolor = *(u32*)src->color[chan]; // vertex
else
*(u32*)matcolor = swxfregs.matColor[chan];
if (colorchan.enablelighting)
{
Vec3 lightCol;
if (colorchan.ambsource)
{
// vertex
lightCol.x = src->color[chan][1];
lightCol.y = src->color[chan][2];
lightCol.z = src->color[chan][3];
}
else
{
u8 *ambColor = (u8*)&swxfregs.ambColor[chan];
lightCol.x = ambColor[1];
lightCol.y = ambColor[2];
lightCol.z = ambColor[3];
}
if (colorchan.enablelighting)
{
Vec3 lightCol;
if (colorchan.ambsource)
{
// vertex
lightCol.x = src->color[chan][1];
lightCol.y = src->color[chan][2];
lightCol.z = src->color[chan][3];
}
else
{
u8 *ambColor = (u8*)&swxfregs.ambColor[chan];
lightCol.x = ambColor[1];
lightCol.y = ambColor[2];
lightCol.z = ambColor[3];
}
u8 mask = colorchan.GetFullLightMask();
for (int i = 0; i < 8; ++i) {
if (mask&(1<<i))
LightColor(dst->mvPosition, dst->normal[0], i, colorchan, lightCol);
}
u8 mask = colorchan.GetFullLightMask();
for (int i = 0; i < 8; ++i)
{
if (mask&(1<<i))
LightColor(dst->mvPosition, dst->normal[0], i, colorchan, lightCol);
}
float inv = 1.0f / 255.0f;
chancolor[1] = (u8)(matcolor[1] * Clamp(lightCol.x * inv, 0.0f, 1.0f));
chancolor[2] = (u8)(matcolor[2] * Clamp(lightCol.y * inv, 0.0f, 1.0f));
chancolor[3] = (u8)(matcolor[3] * Clamp(lightCol.z * inv, 0.0f, 1.0f));
}
else
{
*(u32*)chancolor = *(u32*)matcolor;
}
float inv = 1.0f / 255.0f;
chancolor[1] = (u8)(matcolor[1] * Clamp(lightCol.x * inv, 0.0f, 1.0f));
chancolor[2] = (u8)(matcolor[2] * Clamp(lightCol.y * inv, 0.0f, 1.0f));
chancolor[3] = (u8)(matcolor[3] * Clamp(lightCol.z * inv, 0.0f, 1.0f));
}
else
{
*(u32*)chancolor = *(u32*)matcolor;
}
// alpha
LitChannel &alphachan = swxfregs.alpha[chan];
if (alphachan.matsource)
matcolor[0] = src->color[chan][0]; // vertex
else
matcolor[0] = swxfregs.matColor[chan] & 0xff;
// alpha
LitChannel &alphachan = swxfregs.alpha[chan];
if (alphachan.matsource)
matcolor[0] = src->color[chan][0]; // vertex
else
matcolor[0] = swxfregs.matColor[chan] & 0xff;
if (swxfregs.alpha[chan].enablelighting)
{
float lightCol;
if (alphachan.ambsource)
lightCol = src->color[chan][0]; // vertex
else
lightCol = (float)(swxfregs.ambColor[chan] & 0xff);
if (swxfregs.alpha[chan].enablelighting)
{
float lightCol;
if (alphachan.ambsource)
lightCol = src->color[chan][0]; // vertex
else
lightCol = (float)(swxfregs.ambColor[chan] & 0xff);
u8 mask = alphachan.GetFullLightMask();
for (int i = 0; i < 8; ++i) {
if (mask&(1<<i))
LightAlpha(dst->mvPosition, dst->normal[0], i, alphachan, lightCol);
}
u8 mask = alphachan.GetFullLightMask();
for (int i = 0; i < 8; ++i)
{
if (mask&(1<<i))
LightAlpha(dst->mvPosition, dst->normal[0], i, alphachan, lightCol);
}
chancolor[0] = (u8)(matcolor[0] * Clamp(lightCol / 255.0f, 0.0f, 1.0f));
}
else
{
chancolor[0] = matcolor[0];
}
chancolor[0] = (u8)(matcolor[0] * Clamp(lightCol / 255.0f, 0.0f, 1.0f));
}
else
{
chancolor[0] = matcolor[0];
}
// abgr -> rgba
*(u32*)dst->color[chan] = Common::swap32(*(u32*)chancolor);
}
// abgr -> rgba
*(u32*)dst->color[chan] = Common::swap32(*(u32*)chancolor);
}
}
void TransformTexCoord(const InputVertexData *src, OutputVertexData *dst, bool specialCase)
{
for (u32 coordNum = 0; coordNum < swxfregs.numTexGens; coordNum++)
{
const TexMtxInfo &texinfo = swxfregs.texMtxInfo[coordNum];
for (u32 coordNum = 0; coordNum < swxfregs.numTexGens; coordNum++)
{
const TexMtxInfo &texinfo = swxfregs.texMtxInfo[coordNum];
switch (texinfo.texgentype)
{
case XF_TEXGEN_REGULAR:
TransformTexCoordRegular(texinfo, coordNum, specialCase, src, dst);
break;
case XF_TEXGEN_EMBOSS_MAP:
{
const LightPointer *light = (const LightPointer*)&swxfregs.lights[0x10*texinfo.embosslightshift];
switch (texinfo.texgentype)
{
case XF_TEXGEN_REGULAR:
TransformTexCoordRegular(texinfo, coordNum, specialCase, src, dst);
break;
case XF_TEXGEN_EMBOSS_MAP:
{
const LightPointer *light = (const LightPointer*)&swxfregs.lights[0x10*texinfo.embosslightshift];
Vec3 ldir = (light->pos - dst->mvPosition).normalized();
float d1 = ldir * dst->normal[1];
float d2 = ldir * dst->normal[2];
Vec3 ldir = (light->pos - dst->mvPosition).normalized();
float d1 = ldir * dst->normal[1];
float d2 = ldir * dst->normal[2];
dst->texCoords[coordNum].x = dst->texCoords[texinfo.embosssourceshift].x + d1;
dst->texCoords[coordNum].y = dst->texCoords[texinfo.embosssourceshift].y + d2;
dst->texCoords[coordNum].z = dst->texCoords[texinfo.embosssourceshift].z;
}
break;
case XF_TEXGEN_COLOR_STRGBC0:
_assert_(texinfo.sourcerow == XF_SRCCOLORS_INROW);
_assert_(texinfo.inputform == XF_TEXINPUT_AB11);
dst->texCoords[coordNum].x = (float)dst->color[0][0] / 255.0f;
dst->texCoords[coordNum].y = (float)dst->color[0][1] / 255.0f;
dst->texCoords[coordNum].z = 1.0f;
break;
case XF_TEXGEN_COLOR_STRGBC1:
_assert_(texinfo.sourcerow == XF_SRCCOLORS_INROW);
_assert_(texinfo.inputform == XF_TEXINPUT_AB11);
dst->texCoords[coordNum].x = (float)dst->color[1][0] / 255.0f;
dst->texCoords[coordNum].y = (float)dst->color[1][1] / 255.0f;
dst->texCoords[coordNum].z = 1.0f;
break;
default:
ERROR_LOG(VIDEO, "Bad tex gen type %i", texinfo.texgentype);
}
}
dst->texCoords[coordNum].x = dst->texCoords[texinfo.embosssourceshift].x + d1;
dst->texCoords[coordNum].y = dst->texCoords[texinfo.embosssourceshift].y + d2;
dst->texCoords[coordNum].z = dst->texCoords[texinfo.embosssourceshift].z;
}
break;
case XF_TEXGEN_COLOR_STRGBC0:
_assert_(texinfo.sourcerow == XF_SRCCOLORS_INROW);
_assert_(texinfo.inputform == XF_TEXINPUT_AB11);
dst->texCoords[coordNum].x = (float)dst->color[0][0] / 255.0f;
dst->texCoords[coordNum].y = (float)dst->color[0][1] / 255.0f;
dst->texCoords[coordNum].z = 1.0f;
break;
case XF_TEXGEN_COLOR_STRGBC1:
_assert_(texinfo.sourcerow == XF_SRCCOLORS_INROW);
_assert_(texinfo.inputform == XF_TEXINPUT_AB11);
dst->texCoords[coordNum].x = (float)dst->color[1][0] / 255.0f;
dst->texCoords[coordNum].y = (float)dst->color[1][1] / 255.0f;
dst->texCoords[coordNum].z = 1.0f;
break;
default:
ERROR_LOG(VIDEO, "Bad tex gen type %i", texinfo.texgentype);
}
}
for (u32 coordNum = 0; coordNum < swxfregs.numTexGens; coordNum++)
{
{
dst->texCoords[coordNum][0] *= (bpmem.texcoords[coordNum].s.scale_minus_1 + 1);
dst->texCoords[coordNum][1] *= (bpmem.texcoords[coordNum].t.scale_minus_1 + 1);
}

View File

@ -12,7 +12,7 @@
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// Official Git repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _TRANSFORM_UNIT_H_
@ -23,15 +23,15 @@ struct OutputVertexData;
namespace TransformUnit
{
void MultiplyVec2Mat24(const float *vec, const float *mat, float *result);
void MultiplyVec2Mat34(const float *vec, const float *mat, float *result);
void MultiplyVec3Mat33(const float *vec, const float *mat, float *result);
void MultiplyVec3Mat34(const float *vec, const float *mat, float *result);
void MultiplyVec2Mat24(const float *vec, const float *mat, float *result);
void MultiplyVec2Mat34(const float *vec, const float *mat, float *result);
void MultiplyVec3Mat33(const float *vec, const float *mat, float *result);
void MultiplyVec3Mat34(const float *vec, const float *mat, float *result);
void TransformPosition(const InputVertexData *src, OutputVertexData *dst);
void TransformNormal(const InputVertexData *src, bool nbt, OutputVertexData *dst);
void TransformColor(const InputVertexData *src, OutputVertexData *dst);
void TransformTexCoord(const InputVertexData *src, OutputVertexData *dst, bool specialCase);
void TransformPosition(const InputVertexData *src, OutputVertexData *dst);
void TransformNormal(const InputVertexData *src, bool nbt, OutputVertexData *dst);
void TransformColor(const InputVertexData *src, OutputVertexData *dst);
void TransformTexCoord(const InputVertexData *src, OutputVertexData *dst, bool specialCase);
}
#endif

View File

@ -12,7 +12,7 @@
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// Official Git repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _VEC3_H

View File

@ -12,7 +12,7 @@
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// Official Git repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "VideoConfigDiag.h"

View File

@ -12,7 +12,7 @@
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// Official Git repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _VIDEOSOFTWARE_CONFIG_DIAG_H_

View File

@ -12,7 +12,7 @@
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// Official Git repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "VideoCommon.h"
@ -26,15 +26,15 @@ XFRegisters swxfregs;
void InitXFMemory()
{
memset(&swxfregs, 0, sizeof(swxfregs));
memset(&swxfregs, 0, sizeof(swxfregs));
}
void XFWritten(u32 transferSize, u32 baseAddress)
{
u32 topAddress = baseAddress + transferSize;
u32 topAddress = baseAddress + transferSize;
if (baseAddress <= 0x1026 && topAddress >= 0x1020)
Clipper::SetViewOffset();
if (baseAddress <= 0x1026 && topAddress >= 0x1020)
Clipper::SetViewOffset();
// fix lights so invalid values don't trash the lighting computations
if (baseAddress <= 0x067f && topAddress >= 0x0604)
@ -63,32 +63,32 @@ void XFWritten(u32 transferSize, u32 baseAddress)
void SWLoadXFReg(u32 transferSize, u32 baseAddress, u32 *pData)
{
u32 size = transferSize;
u32 size = transferSize;
// do not allow writes past registers
if (baseAddress + transferSize > 0x1058)
{
INFO_LOG(VIDEO, "xf load exceeds address space: %x %d bytes\n", baseAddress, transferSize);
// do not allow writes past registers
if (baseAddress + transferSize > 0x1058)
{
INFO_LOG(VIDEO, "xf load exceeds address space: %x %d bytes\n", baseAddress, transferSize);
if (baseAddress >= 0x1058)
size = 0;
else
size = 0x1058 - baseAddress;
}
if (size > 0) {
memcpy_gc( &((u32*)&swxfregs)[baseAddress], pData, size * 4);
XFWritten(transferSize, baseAddress);
}
if (baseAddress >= 0x1058)
size = 0;
else
size = 0x1058 - baseAddress;
}
if (size > 0)
{
memcpy_gc( &((u32*)&swxfregs)[baseAddress], pData, size * 4);
XFWritten(transferSize, baseAddress);
}
}
void SWLoadIndexedXF(u32 val, int array)
{
int index = val >> 16;
int address = val & 0xFFF; //check mask
int size = ((val >> 12) & 0xF) + 1;
//load stuff from array to address in xf mem
int index = val >> 16;
int address = val & 0xFFF; //check mask
int size = ((val >> 12) & 0xF) + 1;
//load stuff from array to address in xf mem
u32 *pData = (u32*)Memory::GetPointer(arraybases[array] + arraystrides[array]*index);

View File

@ -12,7 +12,7 @@
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// Official Git repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _XFMEMLOADER_H_
@ -31,49 +31,49 @@
#define XF_TEXINPUT_AB11 0
#define XF_TEXINPUT_ABC1 1
#define XF_TEXGEN_REGULAR 0
#define XF_TEXGEN_EMBOSS_MAP 1 // used when bump mapping
#define XF_TEXGEN_REGULAR 0
#define XF_TEXGEN_EMBOSS_MAP 1 // used when bump mapping
#define XF_TEXGEN_COLOR_STRGBC0 2
#define XF_TEXGEN_COLOR_STRGBC1 3
#define XF_SRCGEOM_INROW 0 // input is abc
#define XF_SRCNORMAL_INROW 1 // input is abc
#define XF_SRCCOLORS_INROW 2
#define XF_SRCGEOM_INROW 0 // input is abc
#define XF_SRCNORMAL_INROW 1 // input is abc
#define XF_SRCCOLORS_INROW 2
#define XF_SRCBINORMAL_T_INROW 3 // input is abc
#define XF_SRCBINORMAL_B_INROW 4 // input is abc
#define XF_SRCTEX0_INROW 5
#define XF_SRCTEX1_INROW 6
#define XF_SRCTEX2_INROW 7
#define XF_SRCTEX3_INROW 8
#define XF_SRCTEX4_INROW 9
#define XF_SRCTEX5_INROW 10
#define XF_SRCTEX6_INROW 11
#define XF_SRCTEX7_INROW 12
#define XF_SRCTEX0_INROW 5
#define XF_SRCTEX1_INROW 6
#define XF_SRCTEX2_INROW 7
#define XF_SRCTEX3_INROW 8
#define XF_SRCTEX4_INROW 9
#define XF_SRCTEX5_INROW 10
#define XF_SRCTEX6_INROW 11
#define XF_SRCTEX7_INROW 12
#define GX_SRC_REG 0
#define GX_SRC_VTX 1
struct Light
{
u32 useless[3];
u32 color; //rgba
float a0; //attenuation
float a1;
float a2;
float k0; //k stuff
float k1;
float k2;
union
{
struct {
u32 useless[3];
u32 color; //rgba
float a0; //attenuation
float a1;
float a2;
float k0; //k stuff
float k1;
float k2;
union
{
struct {
float dpos[3];
float ddir[3]; // specular lights only
};
struct {
float sdir[3];
float shalfangle[3]; // specular lights only
};
};
float ddir[3]; // specular lights only
};
struct {
float sdir[3];
float shalfangle[3]; // specular lights only
};
};
};
#define LIGHTDIF_NONE 0
@ -83,74 +83,74 @@ struct Light
#define LIGHTATTN_SPEC 0 // specular attenuation
#define LIGHTATTN_SPOT 1 // distance/spotlight attenuation
#define LIGHTATTN_NONE 2
#define LIGHTATTN_DIR 3
#define LIGHTATTN_DIR 3
#define GX_PERSPECTIVE 0
#define GX_ORTHOGRAPHIC 1
union LitChannel
{
struct
{
u32 matsource : 1;
u32 enablelighting : 1;
u32 lightMask0_3 : 4;
u32 ambsource : 1;
u32 diffusefunc : 2; // LIGHTDIF_X
u32 attnfunc : 2; // LIGHTATTN_X
u32 lightMask4_7 : 4;
u32 unused : 17;
};
u32 hex;
unsigned int GetFullLightMask() const
{
return enablelighting ? (lightMask0_3 | (lightMask4_7 << 4)) : 0;
}
struct
{
u32 matsource : 1;
u32 enablelighting : 1;
u32 lightMask0_3 : 4;
u32 ambsource : 1;
u32 diffusefunc : 2; // LIGHTDIF_X
u32 attnfunc : 2; // LIGHTATTN_X
u32 lightMask4_7 : 4;
u32 unused : 17;
};
u32 hex;
unsigned int GetFullLightMask() const
{
return enablelighting ? (lightMask0_3 | (lightMask4_7 << 4)) : 0;
}
};
union INVTXSPEC
{
struct
{
u32 numcolors : 2;
u32 numnormals : 2; // 0 - nothing, 1 - just normal, 2 - normals and binormals
u32 numtextures : 4;
u32 unused : 24;
};
u32 hex;
struct
{
u32 numcolors : 2;
u32 numnormals : 2; // 0 - nothing, 1 - just normal, 2 - normals and binormals
u32 numtextures : 4;
u32 unused : 24;
};
u32 hex;
};
union TXFMatrixIndexA
{
struct
{
u32 PosNormalMtxIdx : 6;
u32 Tex0MtxIdx : 6;
u32 Tex1MtxIdx : 6;
u32 Tex2MtxIdx : 6;
u32 Tex3MtxIdx : 6;
};
struct
{
u32 Hex : 30;
u32 unused : 2;
};
struct
{
u32 PosNormalMtxIdx : 6;
u32 Tex0MtxIdx : 6;
u32 Tex1MtxIdx : 6;
u32 Tex2MtxIdx : 6;
u32 Tex3MtxIdx : 6;
};
struct
{
u32 Hex : 30;
u32 unused : 2;
};
};
union TXFMatrixIndexB
{
struct
{
u32 Tex4MtxIdx : 6;
u32 Tex5MtxIdx : 6;
u32 Tex6MtxIdx : 6;
u32 Tex7MtxIdx : 6;
};
struct
{
u32 Hex : 24;
u32 unused : 8;
};
struct
{
u32 Tex4MtxIdx : 6;
u32 Tex5MtxIdx : 6;
u32 Tex6MtxIdx : 6;
u32 Tex7MtxIdx : 6;
};
struct
{
u32 Hex : 24;
u32 unused : 8;
};
};
struct Viewport
@ -171,68 +171,68 @@ struct Projection
union TexMtxInfo
{
struct
{
u32 unknown : 1;
u32 projection : 1; // XF_TEXPROJ_X
u32 inputform : 2; // XF_TEXINPUT_X
u32 texgentype : 3; // XF_TEXGEN_X
u32 sourcerow : 5; // XF_SRCGEOM_X
u32 embosssourceshift : 3; // what generated texcoord to use
u32 embosslightshift : 3; // light index that is used
};
u32 hex;
struct
{
u32 unknown : 1;
u32 projection : 1; // XF_TEXPROJ_X
u32 inputform : 2; // XF_TEXINPUT_X
u32 texgentype : 3; // XF_TEXGEN_X
u32 sourcerow : 5; // XF_SRCGEOM_X
u32 embosssourceshift : 3; // what generated texcoord to use
u32 embosslightshift : 3; // light index that is used
};
u32 hex;
};
union PostMtxInfo
{
struct
{
u32 index : 6; // base row of dual transform matrix
u32 unused : 2;
u32 normalize : 1; // normalize before send operation
};
u32 hex;
struct
{
u32 index : 6; // base row of dual transform matrix
u32 unused : 2;
u32 normalize : 1; // normalize before send operation
};
u32 hex;
};
struct XFRegisters
{
u32 posMatrices[256]; // 0x0000 - 0x00ff
u32 unk0[768]; // 0x0100 - 0x03ff
u32 normalMatrices[96]; // 0x0400 - 0x045f
u32 unk1[160]; // 0x0460 - 0x04ff
u32 postMatrices[256]; // 0x0500 - 0x05ff
u32 lights[128]; // 0x0600 - 0x067f
u32 unk2[2432]; // 0x0680 - 0x0fff
u32 error; // 0x1000
u32 diag; // 0x1001
u32 state0; // 0x1002
u32 state1; // 0x1003
u32 xfClock; // 0x1004
u32 clipDisable; // 0x1005
u32 perf0; // 0x1006
u32 perf1; // 0x1007
INVTXSPEC hostinfo; // 0x1008 number of textures,colors,normals from vertex input
u32 nNumChans; // 0x1009
u32 ambColor[2]; // 0x100a, 0x100b
u32 matColor[2]; // 0x100c, 0x100d
LitChannel color[2]; // 0x100e, 0x100f
LitChannel alpha[2]; // 0x1010, 0x1011
u32 dualTexTrans; // 0x1012
u32 unk3; // 0x1013
u32 unk4; // 0x1014
u32 unk5; // 0x1015
u32 unk6; // 0x1016
u32 unk7; // 0x1017
TXFMatrixIndexA MatrixIndexA; // 0x1018
TXFMatrixIndexB MatrixIndexB; // 0x1019
Viewport viewport; // 0x101a - 0x101f
Projection projection; // 0x1020 - 0x1026
u32 unk8[24]; // 0x1027 - 0x103e
u32 numTexGens; // 0x103f
TexMtxInfo texMtxInfo[8]; // 0x1040 - 0x1047
u32 unk9[8]; // 0x1048 - 0x104f
PostMtxInfo postMtxInfo[8]; // 0x1050 - 0x1057
u32 posMatrices[256]; // 0x0000 - 0x00ff
u32 unk0[768]; // 0x0100 - 0x03ff
u32 normalMatrices[96]; // 0x0400 - 0x045f
u32 unk1[160]; // 0x0460 - 0x04ff
u32 postMatrices[256]; // 0x0500 - 0x05ff
u32 lights[128]; // 0x0600 - 0x067f
u32 unk2[2432]; // 0x0680 - 0x0fff
u32 error; // 0x1000
u32 diag; // 0x1001
u32 state0; // 0x1002
u32 state1; // 0x1003
u32 xfClock; // 0x1004
u32 clipDisable; // 0x1005
u32 perf0; // 0x1006
u32 perf1; // 0x1007
INVTXSPEC hostinfo; // 0x1008 number of textures,colors,normals from vertex input
u32 nNumChans; // 0x1009
u32 ambColor[2]; // 0x100a, 0x100b
u32 matColor[2]; // 0x100c, 0x100d
LitChannel color[2]; // 0x100e, 0x100f
LitChannel alpha[2]; // 0x1010, 0x1011
u32 dualTexTrans; // 0x1012
u32 unk3; // 0x1013
u32 unk4; // 0x1014
u32 unk5; // 0x1015
u32 unk6; // 0x1016
u32 unk7; // 0x1017
TXFMatrixIndexA MatrixIndexA; // 0x1018
TXFMatrixIndexB MatrixIndexB; // 0x1019
Viewport viewport; // 0x101a - 0x101f
Projection projection; // 0x1020 - 0x1026
u32 unk8[24]; // 0x1027 - 0x103e
u32 numTexGens; // 0x103f
TexMtxInfo texMtxInfo[8]; // 0x1040 - 0x1047
u32 unk9[8]; // 0x1048 - 0x104f
PostMtxInfo postMtxInfo[8]; // 0x1050 - 0x1057
};
#define XFMEM_POSMATRICES 0x000
@ -249,7 +249,7 @@ extern XFRegisters swxfregs;
void InitXFMemory();
void XFWritten(u32 transferSize, u32 baseAddress);
void XFWritten(u32 transferSize, u32 baseAddress);
void SWLoadXFReg(u32 transferSize, u32 baseAddress, u32 *pData);

View File

@ -12,7 +12,7 @@
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// Official Git repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "stdafx.h"

View File

@ -12,7 +12,7 @@
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// Official Git repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#pragma once