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

View File

@ -12,7 +12,7 @@
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // 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/ // http://code.google.com/p/dolphin-emu/
#ifndef _BPMEMLOADER_H_ #ifndef _BPMEMLOADER_H_

View File

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

View File

@ -12,7 +12,7 @@
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // 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/ // http://code.google.com/p/dolphin-emu/
#ifndef _CPMEMLOADER_H_ #ifndef _CPMEMLOADER_H_

View File

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

View File

@ -12,7 +12,7 @@
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // 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/ // http://code.google.com/p/dolphin-emu/
#include "Common.h" #include "Common.h"
@ -46,57 +46,57 @@ int BufferBase[NumObjectBuffers];
void Init() void Init()
{ {
for (int i = 0; i < NumObjectBuffers; i++) for (int i = 0; i < NumObjectBuffers; i++)
{ {
memset(ObjectBuffer[i], 0, sizeof(ObjectBuffer[i])); memset(ObjectBuffer[i], 0, sizeof(ObjectBuffer[i]));
DrawnToBuffer[i] = false; DrawnToBuffer[i] = false;
ObjectBufferName[i] = 0; ObjectBufferName[i] = 0;
BufferBase[i] = 0; BufferBase[i] = 0;
} }
} }
void SaveTexture(const char* filename, u32 texmap, s32 mip) void SaveTexture(const char* filename, u32 texmap, s32 mip)
{ {
FourTexUnits& texUnit = bpmem.tex[(texmap >> 2) & 1]; FourTexUnits& texUnit = bpmem.tex[(texmap >> 2) & 1];
u8 subTexmap = texmap & 3; u8 subTexmap = texmap & 3;
TexImage0& ti0 = texUnit.texImage0[subTexmap]; TexImage0& ti0 = texUnit.texImage0[subTexmap];
u32 width = ti0.width + 1; u32 width = ti0.width + 1;
u32 height = ti0.height + 1; u32 height = ti0.height + 1;
u8 *data = new u8[width * height * 4]; 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) 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 // RGBA to BGRA
*(dst++) = sample[2]; *(dst++) = sample[2];
*(dst++) = sample[1]; *(dst++) = sample[1];
*(dst++) = sample[0]; *(dst++) = sample[0];
*(dst++) = sample[3]; *(dst++) = sample[3];
} }
} }
} }
s32 GetMaxTextureLod(u32 texmap) s32 GetMaxTextureLod(u32 texmap)
{ {
FourTexUnits& texUnit = bpmem.tex[(texmap >> 2) & 1]; FourTexUnits& texUnit = bpmem.tex[(texmap >> 2) & 1];
u8 subTexmap = texmap & 3; u8 subTexmap = texmap & 3;
u8 maxLod = texUnit.texMode1[subTexmap].max_lod; u8 maxLod = texUnit.texMode1[subTexmap].max_lod;
u8 mip = maxLod >> 4; u8 mip = maxLod >> 4;
@ -110,9 +110,9 @@ s32 GetMaxTextureLod(u32 texmap)
void DumpActiveTextures() void DumpActiveTextures()
{ {
for (unsigned int stageNum = 0; stageNum < bpmem.genMode.numindstages; stageNum++) for (unsigned int stageNum = 0; stageNum < bpmem.genMode.numindstages; stageNum++)
{ {
u32 texmap = bpmem.tevindref.getTexMap(stageNum); u32 texmap = bpmem.tevindref.getTexMap(stageNum);
s32 maxLod = GetMaxTextureLod(texmap); s32 maxLod = GetMaxTextureLod(texmap);
for (s32 mip = 0; mip <= maxLod; ++mip) for (s32 mip = 0; mip <= maxLod; ++mip)
@ -121,90 +121,96 @@ void DumpActiveTextures()
File::GetUserPath(D_DUMPTEXTURES_IDX).c_str(), File::GetUserPath(D_DUMPTEXTURES_IDX).c_str(),
swstats.thisFrame.numDrawnObjects, stageNum, texmap, mip).c_str(), texmap, mip); swstats.thisFrame.numDrawnObjects, stageNum, texmap, mip).c_str(), texmap, mip);
} }
} }
for (unsigned int stageNum = 0; stageNum <= bpmem.genMode.numtevstages; stageNum++) for (unsigned int stageNum = 0; stageNum <= bpmem.genMode.numtevstages; stageNum++)
{ {
int stageNum2 = stageNum >> 1; int stageNum2 = stageNum >> 1;
int stageOdd = stageNum&1; int stageOdd = stageNum&1;
TwoTevStageOrders &order = bpmem.tevorders[stageNum2]; 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) for (s32 mip = 0; mip <= maxLod; ++mip)
{ {
SaveTexture(StringFromFormat("%star%i_stage%i_map%i_mip%i.tga", SaveTexture(StringFromFormat("%star%i_stage%i_map%i_mip%i.tga",
File::GetUserPath(D_DUMPTEXTURES_IDX).c_str(), File::GetUserPath(D_DUMPTEXTURES_IDX).c_str(),
swstats.thisFrame.numDrawnObjects, stageNum, texmap, mip).c_str(), texmap, mip); swstats.thisFrame.numDrawnObjects, stageNum, texmap, mip).c_str(), texmap, mip);
} }
} }
} }
void DumpEfb(const char* filename) void DumpEfb(const char* filename)
{ {
u8 *data = new u8[EFB_WIDTH * EFB_HEIGHT * 4]; u8 *data = new u8[EFB_WIDTH * EFB_HEIGHT * 4];
u8 *writePtr = data; u8 *writePtr = data;
u8 sample[4]; u8 sample[4];
for (int y = 0; y < EFB_HEIGHT; y++) for (int y = 0; y < EFB_HEIGHT; y++)
for (int x = 0; x < EFB_WIDTH; x++) { {
EfbInterface::GetColor(x, y, sample); for (int x = 0; x < EFB_WIDTH; x++)
// ABGR to BGRA {
*(writePtr++) = sample[1]; EfbInterface::GetColor(x, y, sample);
*(writePtr++) = sample[2]; // ABGR to BGRA
*(writePtr++) = sample[3]; *(writePtr++) = sample[1];
*(writePtr++) = sample[0]; *(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) void DumpDepth(const char* filename)
{ {
u8 *data = new u8[EFB_WIDTH * EFB_HEIGHT * 4]; u8 *data = new u8[EFB_WIDTH * EFB_HEIGHT * 4];
u8 *writePtr = data; u8 *writePtr = data;
for (int y = 0; y < EFB_HEIGHT; y++) for (int y = 0; y < EFB_HEIGHT; y++)
for (int x = 0; x < EFB_WIDTH; x++) { {
u32 depth = EfbInterface::GetDepth(x, y); for (int x = 0; x < EFB_WIDTH; x++)
// depth to bgra {
*(writePtr++) = (depth >> 16) & 0xff; u32 depth = EfbInterface::GetDepth(x, y);
*(writePtr++) = (depth >> 8) & 0xff; // depth to bgra
*(writePtr++) = depth & 0xff; *(writePtr++) = (depth >> 16) & 0xff;
*(writePtr++) = 255; *(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) 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; u32 offset = (x + y * EFB_WIDTH) * 4;
u8 *dst = (u8*)&ObjectBuffer[buffer][offset]; u8 *dst = (u8*)&ObjectBuffer[buffer][offset];
*(dst++) = color[2]; *(dst++) = color[2];
*(dst++) = color[1]; *(dst++) = color[1];
*(dst++) = color[0]; *(dst++) = color[0];
*(dst++) = color[3]; *(dst++) = color[3];
DrawnToBuffer[buffer] = true; DrawnToBuffer[buffer] = true;
ObjectBufferName[buffer] = name; ObjectBufferName[buffer] = name;
BufferBase[buffer] = bufferBase; BufferBase[buffer] = bufferBase;
} }
void DrawTempBuffer(u8 *color, int buffer) void DrawTempBuffer(u8 *color, int buffer)
{ {
u8 *dst = (u8*)&TempBuffer[buffer]; u8 *dst = (u8*)&TempBuffer[buffer];
*(dst++) = color[2]; *(dst++) = color[2];
*(dst++) = color[1]; *(dst++) = color[1];
*(dst++) = color[0]; *(dst++) = color[0];
*(dst++) = color[3]; *(dst++) = color[3];
} }
void CopyTempBuffer(s16 x, s16 y, int bufferBase, int subBuffer, const char *name) 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]; ObjectBuffer[buffer][offset] = TempBuffer[buffer];
DrawnToBuffer[buffer] = true; DrawnToBuffer[buffer] = true;
ObjectBufferName[buffer] = name; ObjectBufferName[buffer] = name;
BufferBase[buffer] = bufferBase; BufferBase[buffer] = bufferBase;
} }
void OnObjectBegin() void OnObjectBegin()
{ {
if (!g_bSkipCurrentFrame) if (!g_bSkipCurrentFrame)
{ {
if (g_SWVideoConfig.bDumpTextures && swstats.thisFrame.numDrawnObjects >= g_SWVideoConfig.drawStart && swstats.thisFrame.numDrawnObjects < g_SWVideoConfig.drawEnd) if (g_SWVideoConfig.bDumpTextures && swstats.thisFrame.numDrawnObjects >= g_SWVideoConfig.drawStart && swstats.thisFrame.numDrawnObjects < g_SWVideoConfig.drawEnd)
DumpActiveTextures(); DumpActiveTextures();
if (g_SWVideoConfig.bHwRasterizer) if (g_SWVideoConfig.bHwRasterizer)
{ {
HwRasterizer::BeginTriangles(); HwRasterizer::BeginTriangles();
drawingHwTriangles = true; drawingHwTriangles = true;
} }
} }
} }
void OnObjectEnd() void OnObjectEnd()
{ {
if (!g_bSkipCurrentFrame) if (!g_bSkipCurrentFrame)
{ {
if (g_SWVideoConfig.bDumpObjects && swstats.thisFrame.numDrawnObjects >= g_SWVideoConfig.drawStart && swstats.thisFrame.numDrawnObjects < g_SWVideoConfig.drawEnd) if (g_SWVideoConfig.bDumpObjects && swstats.thisFrame.numDrawnObjects >= g_SWVideoConfig.drawStart && swstats.thisFrame.numDrawnObjects < g_SWVideoConfig.drawEnd)
DumpEfb(StringFromFormat("%sobject%i.tga", DumpEfb(StringFromFormat("%sobject%i.tga",
File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), File::GetUserPath(D_DUMPFRAMES_IDX).c_str(),
swstats.thisFrame.numDrawnObjects).c_str()); swstats.thisFrame.numDrawnObjects).c_str());
if (g_SWVideoConfig.bHwRasterizer || drawingHwTriangles) if (g_SWVideoConfig.bHwRasterizer || drawingHwTriangles)
{ {
HwRasterizer::EndTriangles(); HwRasterizer::EndTriangles();
drawingHwTriangles = false; drawingHwTriangles = false;
} }
for (int i = 0; i < NumObjectBuffers; i++) for (int i = 0; i < NumObjectBuffers; i++)
{ {
if (DrawnToBuffer[i]) if (DrawnToBuffer[i])
{ {
DrawnToBuffer[i] = false; DrawnToBuffer[i] = false;
(void)SaveTGA(StringFromFormat("%sobject%i_%s(%i).tga", (void)SaveTGA(StringFromFormat("%sobject%i_%s(%i).tga",
File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), File::GetUserPath(D_DUMPFRAMES_IDX).c_str(),
swstats.thisFrame.numDrawnObjects, ObjectBufferName[i], i - BufferBase[i]).c_str(), swstats.thisFrame.numDrawnObjects, ObjectBufferName[i], i - BufferBase[i]).c_str(),
EFB_WIDTH, EFB_HEIGHT, ObjectBuffer[i]); EFB_WIDTH, EFB_HEIGHT, ObjectBuffer[i]);
memset(ObjectBuffer[i], 0, sizeof(ObjectBuffer[i])); memset(ObjectBuffer[i], 0, sizeof(ObjectBuffer[i]));
} }
} }
swstats.thisFrame.numDrawnObjects++; swstats.thisFrame.numDrawnObjects++;
} }
} }
void OnFrameEnd() void OnFrameEnd()
{ {
if (!g_bSkipCurrentFrame) if (!g_bSkipCurrentFrame)
{ {
if (g_SWVideoConfig.bDumpFrames) if (g_SWVideoConfig.bDumpFrames)
{ {
DumpEfb(StringFromFormat("%sframe%i_color.tga", DumpEfb(StringFromFormat("%sframe%i_color.tga",
File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), swstats.frameCount).c_str()); File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), swstats.frameCount).c_str());
DumpDepth(StringFromFormat("%sframe%i_depth.tga", DumpDepth(StringFromFormat("%sframe%i_depth.tga",
File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), swstats.frameCount).c_str()); 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. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // 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/ // http://code.google.com/p/dolphin-emu/
#ifndef _DEBUGUTIL_H #ifndef _DEBUGUTIL_H
@ -20,18 +20,18 @@
namespace DebugUtil 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 OnObjectBegin();
void OnObjectEnd(); 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 DrawTempBuffer(u8 *color, int buffer);
void CopyTempBuffer(s16 x, s16 y, int bufferBase, int subBuffer, const char *name); 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. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // 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/ // http://code.google.com/p/dolphin-emu/
#include "BPMemLoader.h" #include "BPMemLoader.h"
@ -30,84 +30,83 @@
namespace EfbCopy namespace EfbCopy
{ {
void CopyToXfb() void CopyToXfb()
{ {
GLInterface->Update(); // just updates the render window position and the backbuffer size GLInterface->Update(); // just updates the render window position and the backbuffer size
if (!g_SWVideoConfig.bHwRasterizer) if (!g_SWVideoConfig.bHwRasterizer)
{ {
// copy to open gl for rendering // copy to open gl for rendering
EfbInterface::UpdateColorTexture(); EfbInterface::UpdateColorTexture();
SWRenderer::DrawTexture(EfbInterface::efbColorTexture, EFB_WIDTH, EFB_HEIGHT); SWRenderer::DrawTexture(EfbInterface::efbColorTexture, EFB_WIDTH, EFB_HEIGHT);
} }
SWRenderer::SwapBuffer(); SWRenderer::SwapBuffer();
}
} void CopyToRam()
{
void CopyToRam() if (!g_SWVideoConfig.bHwRasterizer)
{
if (!g_SWVideoConfig.bHwRasterizer)
{ {
u8 *dest_ptr = Memory::GetPointer(bpmem.copyTexDest << 5); u8 *dest_ptr = Memory::GetPointer(bpmem.copyTexDest << 5);
TextureEncoder::Encode(dest_ptr); TextureEncoder::Encode(dest_ptr);
} }
} }
void ClearEfb() void ClearEfb()
{ {
u32 clearColor = (bpmem.clearcolorAR & 0xff) << 24 | bpmem.clearcolorGB << 8 | (bpmem.clearcolorAR & 0xff00) >> 8; u32 clearColor = (bpmem.clearcolorAR & 0xff) << 24 | bpmem.clearcolorGB << 8 | (bpmem.clearcolorAR & 0xff00) >> 8;
int left = bpmem.copyTexSrcXY.x; int left = bpmem.copyTexSrcXY.x;
int top = bpmem.copyTexSrcXY.y; int top = bpmem.copyTexSrcXY.y;
int right = left + bpmem.copyTexSrcWH.x; int right = left + bpmem.copyTexSrcWH.x;
int bottom = top + bpmem.copyTexSrcWH.y; int bottom = top + bpmem.copyTexSrcWH.y;
for (u16 y = top; y <= bottom; y++) for (u16 y = top; y <= bottom; y++)
{ {
for (u16 x = left; x <= right; x++) for (u16 x = left; x <= right; x++)
{ {
EfbInterface::SetColor(x, y, (u8*)(&clearColor)); EfbInterface::SetColor(x, y, (u8*)(&clearColor));
EfbInterface::SetDepth(x, y, bpmem.clearZValue); EfbInterface::SetDepth(x, y, bpmem.clearZValue);
} }
} }
} }
void CopyEfb() void CopyEfb()
{ {
if (bpmem.triggerEFBCopy.copy_to_xfb) if (bpmem.triggerEFBCopy.copy_to_xfb)
DebugUtil::OnFrameEnd(); DebugUtil::OnFrameEnd();
if (!g_bSkipCurrentFrame) if (!g_bSkipCurrentFrame)
{ {
if (bpmem.triggerEFBCopy.copy_to_xfb) if (bpmem.triggerEFBCopy.copy_to_xfb)
{ {
CopyToXfb(); CopyToXfb();
Core::Callback_VideoCopiedToXFB(true); Core::Callback_VideoCopiedToXFB(true);
swstats.frameCount++; swstats.frameCount++;
} }
else else
{ {
CopyToRam(); CopyToRam();
} }
if (bpmem.triggerEFBCopy.clear) if (bpmem.triggerEFBCopy.clear)
{ {
if (g_SWVideoConfig.bHwRasterizer) if (g_SWVideoConfig.bHwRasterizer)
HwRasterizer::Clear(); HwRasterizer::Clear();
else else
ClearEfb(); ClearEfb();
} }
} }
else else
{ {
if (bpmem.triggerEFBCopy.copy_to_xfb) if (bpmem.triggerEFBCopy.copy_to_xfb)
{ {
// no frame rendered but tell that a frame has finished for frame skip counter // no frame rendered but tell that a frame has finished for frame skip counter
Core::Callback_VideoCopiedToXFB(false); Core::Callback_VideoCopiedToXFB(false);
} }
} }
} }
} }

View File

@ -12,7 +12,7 @@
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // 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/ // http://code.google.com/p/dolphin-emu/
#ifndef _EFB_COPY_H_ #ifndef _EFB_COPY_H_
@ -23,9 +23,9 @@
namespace EfbCopy namespace EfbCopy
{ {
// Copy the EFB to RAM as a texture format or XFB // Copy the EFB to RAM as a texture format or XFB
// Clear the EFB if needed // Clear the EFB if needed
void CopyEfb(); void CopyEfb();
} }

View File

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

View File

@ -12,7 +12,7 @@
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // 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/ // http://code.google.com/p/dolphin-emu/
#ifndef _EFB_INTERFACE_H_ #ifndef _EFB_INTERFACE_H_
@ -22,32 +22,32 @@
namespace EfbInterface 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 }; 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 // does full blending of an incoming pixel
void BlendTev(u16 x, u16 y, u8 *color); void BlendTev(u16 x, u16 y, u8 *color);
// compare z at location x,y // compare z at location x,y
// writes it if it passes // writes it if it passes
// returns result of compare. // returns result of compare.
bool ZCompare(u16 x, u16 y, u32 z); bool ZCompare(u16 x, u16 y, u32 z);
// sets the color and alpha // sets the color and alpha
void SetColor(u16 x, u16 y, u8 *color); void SetColor(u16 x, u16 y, u8 *color);
void SetDepth(u16 x, u16 y, u32 depth); void SetDepth(u16 x, u16 y, u32 depth);
void GetColor(u16 x, u16 y, u8 *color); void GetColor(u16 x, u16 y, u8 *color);
u32 GetDepth(u16 x, u16 y); u32 GetDepth(u16 x, u16 y);
u8* GetPixelPointer(u16 x, u16 y, bool depth); u8* GetPixelPointer(u16 x, u16 y, bool depth);
void UpdateColorTexture(); void UpdateColorTexture();
extern u8 efbColorTexture[EFB_WIDTH*EFB_HEIGHT*4]; // RGBA format extern u8 efbColorTexture[EFB_WIDTH*EFB_HEIGHT*4]; // RGBA format
void DoState(PointerWrap &p); void DoState(PointerWrap &p);
} }
#endif #endif

View File

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

View File

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

View File

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

View File

@ -12,7 +12,7 @@
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // 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/ // http://code.google.com/p/dolphin-emu/
#include "Common.h" #include "Common.h"
@ -61,258 +61,258 @@ void DoState(PointerWrap &p)
void DecodePrimitiveStream(u32 iBufferSize) void DecodePrimitiveStream(u32 iBufferSize)
{ {
u32 vertexSize = vertexLoader.GetVertexSize(); u32 vertexSize = vertexLoader.GetVertexSize();
bool skipPrimitives = g_bSkipCurrentFrame || bool skipPrimitives = g_bSkipCurrentFrame ||
swstats.thisFrame.numDrawnObjects < g_SWVideoConfig.drawStart || swstats.thisFrame.numDrawnObjects < g_SWVideoConfig.drawStart ||
swstats.thisFrame.numDrawnObjects >= g_SWVideoConfig.drawEnd; swstats.thisFrame.numDrawnObjects >= g_SWVideoConfig.drawEnd;
if (skipPrimitives) if (skipPrimitives)
{ {
while (streamSize > 0 && iBufferSize >= vertexSize) while (streamSize > 0 && iBufferSize >= vertexSize)
{ {
g_pVideoData += vertexSize; g_pVideoData += vertexSize;
iBufferSize -= vertexSize; iBufferSize -= vertexSize;
streamSize--; streamSize--;
} }
} }
else else
{ {
while (streamSize > 0 && iBufferSize >= vertexSize) while (streamSize > 0 && iBufferSize >= vertexSize)
{ {
vertexLoader.LoadVertex(); vertexLoader.LoadVertex();
iBufferSize -= vertexSize; iBufferSize -= vertexSize;
streamSize--; streamSize--;
} }
} }
if (streamSize == 0) if (streamSize == 0)
{ {
// return to normal command processing // return to normal command processing
ResetDecoding(); ResetDecoding();
} }
} }
void ReadXFData(u32 iBufferSize) 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]; u32 pData[16];
for (int i = 0; i < streamSize; i++) for (int i = 0; i < streamSize; i++)
pData[i] = DataReadU32(); pData[i] = DataReadU32();
SWLoadXFReg(streamSize, streamAddress, pData); SWLoadXFReg(streamSize, streamAddress, pData);
// return to normal command processing // return to normal command processing
ResetDecoding(); ResetDecoding();
} }
void ExecuteDisplayList(u32 addr, u32 count) 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)) while (OpcodeDecoder::CommandRunnable(count))
{ {
OpcodeDecoder::Run(count); OpcodeDecoder::Run(count);
// if data was read by the opcode decoder then the video data pointer changed // if data was read by the opcode decoder then the video data pointer changed
u32 readCount = (u32)(g_pVideoData - dlStart); u32 readCount = (u32)(g_pVideoData - dlStart);
dlStart = g_pVideoData; 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) 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) if (Cmd == GX_NOP)
return; return;
// Causes a SIGBUS error on Android // Causes a SIGBUS error on Android
// XXX: Investigate // XXX: Investigate
#ifndef ANDROID #ifndef ANDROID
// check if switching in or out of an object // check if switching in or out of an object
// only used for debuggging // only used for debuggging
if (inObjectStream && (Cmd & 0x87) != lastPrimCmd) if (inObjectStream && (Cmd & 0x87) != lastPrimCmd)
{ {
inObjectStream = false; inObjectStream = false;
DebugUtil::OnObjectEnd(); DebugUtil::OnObjectEnd();
} }
if (Cmd & 0x80 && !inObjectStream) if (Cmd & 0x80 && !inObjectStream)
{ {
inObjectStream = true; inObjectStream = true;
lastPrimCmd = Cmd & 0x87; lastPrimCmd = Cmd & 0x87;
DebugUtil::OnObjectBegin(); DebugUtil::OnObjectBegin();
} }
#endif #endif
switch(Cmd) switch(Cmd)
{ {
case GX_NOP: case GX_NOP:
break; break;
case GX_LOAD_CP_REG: //0x08 case GX_LOAD_CP_REG: //0x08
{ {
u32 SubCmd = DataReadU8(); u32 SubCmd = DataReadU8();
u32 Value = DataReadU32(); u32 Value = DataReadU32();
SWLoadCPReg(SubCmd, Value); SWLoadCPReg(SubCmd, Value);
} }
break; break;
case GX_LOAD_XF_REG: case GX_LOAD_XF_REG:
{ {
u32 Cmd2 = DataReadU32(); u32 Cmd2 = DataReadU32();
streamSize = ((Cmd2 >> 16) & 15) + 1; streamSize = ((Cmd2 >> 16) & 15) + 1;
streamAddress = Cmd2 & 0xFFFF; streamAddress = Cmd2 & 0xFFFF;
currentFunction = ReadXFData; currentFunction = ReadXFData;
minCommandSize = streamSize * 4; minCommandSize = streamSize * 4;
readOpcode = false; readOpcode = false;
} }
break; break;
case GX_LOAD_INDX_A: //used for position matrices case GX_LOAD_INDX_A: //used for position matrices
SWLoadIndexedXF(DataReadU32(), 0xC); SWLoadIndexedXF(DataReadU32(), 0xC);
break; break;
case GX_LOAD_INDX_B: //used for normal matrices case GX_LOAD_INDX_B: //used for normal matrices
SWLoadIndexedXF(DataReadU32(), 0xD); SWLoadIndexedXF(DataReadU32(), 0xD);
break; break;
case GX_LOAD_INDX_C: //used for postmatrices case GX_LOAD_INDX_C: //used for postmatrices
SWLoadIndexedXF(DataReadU32(), 0xE); SWLoadIndexedXF(DataReadU32(), 0xE);
break; break;
case GX_LOAD_INDX_D: //used for lights case GX_LOAD_INDX_D: //used for lights
SWLoadIndexedXF(DataReadU32(), 0xF); SWLoadIndexedXF(DataReadU32(), 0xF);
break; break;
case GX_CMD_CALL_DL: case GX_CMD_CALL_DL:
{ {
u32 dwAddr = DataReadU32(); u32 dwAddr = DataReadU32();
u32 dwCount = DataReadU32(); u32 dwCount = DataReadU32();
ExecuteDisplayList(dwAddr, dwCount); ExecuteDisplayList(dwAddr, dwCount);
} }
break; break;
case 0x44: case 0x44:
// zelda 4 swords calls it and checks the metrics registers after that // zelda 4 swords calls it and checks the metrics registers after that
break; break;
case GX_CMD_INVL_VC:// Invalidate (vertex cache?) case GX_CMD_INVL_VC:// Invalidate (vertex cache?)
DEBUG_LOG(VIDEO, "Invalidate (vertex cache?)"); DEBUG_LOG(VIDEO, "Invalidate (vertex cache?)");
break; break;
case GX_LOAD_BP_REG: //0x61 case GX_LOAD_BP_REG: //0x61
{ {
u32 cmd = DataReadU32(); u32 cmd = DataReadU32();
SWLoadBPReg(cmd); SWLoadBPReg(cmd);
} }
break; break;
// draw primitives // draw primitives
default: default:
if (Cmd & 0x80) if (Cmd & 0x80)
{ {
u8 vatIndex = Cmd & GX_VAT_MASK; u8 vatIndex = Cmd & GX_VAT_MASK;
u8 primitiveType = (Cmd & GX_PRIMITIVE_MASK) >> GX_PRIMITIVE_SHIFT; u8 primitiveType = (Cmd & GX_PRIMITIVE_MASK) >> GX_PRIMITIVE_SHIFT;
vertexLoader.SetFormat(vatIndex, primitiveType); vertexLoader.SetFormat(vatIndex, primitiveType);
// switch to primitive processing
streamSize = DataReadU16();
currentFunction = DecodePrimitiveStream;
minCommandSize = vertexLoader.GetVertexSize();
readOpcode = false;
INCSTAT(swstats.thisFrame.numPrimatives); // switch to primitive processing
DEBUG_LOG(VIDEO, "Draw begin"); streamSize = DataReadU16();
} currentFunction = DecodePrimitiveStream;
else minCommandSize = vertexLoader.GetVertexSize();
{ readOpcode = false;
PanicAlert("GFX: Unknown Opcode (0x%x).\n", Cmd);
break; INCSTAT(swstats.thisFrame.numPrimatives);
} DEBUG_LOG(VIDEO, "Draw begin");
break; }
} else
{
PanicAlert("GFX: Unknown Opcode (0x%x).\n", Cmd);
break;
}
break;
}
} }
void Init() void Init()
{ {
inObjectStream = false; inObjectStream = false;
lastPrimCmd = 0; lastPrimCmd = 0;
ResetDecoding(); ResetDecoding();
} }
void ResetDecoding() void ResetDecoding()
{ {
currentFunction = DecodeStandard; currentFunction = DecodeStandard;
minCommandSize = 1; minCommandSize = 1;
readOpcode = true; readOpcode = true;
} }
bool CommandRunnable(u32 iBufferSize) bool CommandRunnable(u32 iBufferSize)
{ {
if (iBufferSize < minCommandSize) if (iBufferSize < minCommandSize)
return false; return false;
if (readOpcode) if (readOpcode)
{ {
u8 Cmd = DataPeek8(0); u8 Cmd = DataPeek8(0);
u32 minSize = 1; u32 minSize = 1;
switch(Cmd) switch(Cmd)
{ {
case GX_LOAD_CP_REG: //0x08 case GX_LOAD_CP_REG: //0x08
minSize = 6; minSize = 6;
break; break;
case GX_LOAD_XF_REG: case GX_LOAD_XF_REG:
minSize = 5; minSize = 5;
break; break;
case GX_LOAD_INDX_A: //used for position matrices case GX_LOAD_INDX_A: //used for position matrices
minSize = 5; minSize = 5;
break; break;
case GX_LOAD_INDX_B: //used for normal matrices case GX_LOAD_INDX_B: //used for normal matrices
minSize = 5; minSize = 5;
break; break;
case GX_LOAD_INDX_C: //used for postmatrices case GX_LOAD_INDX_C: //used for postmatrices
minSize = 5; minSize = 5;
break; break;
case GX_LOAD_INDX_D: //used for lights case GX_LOAD_INDX_D: //used for lights
minSize = 5; minSize = 5;
break; break;
case GX_CMD_CALL_DL: case GX_CMD_CALL_DL:
minSize = 9; minSize = 9;
break; break;
case GX_LOAD_BP_REG: //0x61 case GX_LOAD_BP_REG: //0x61
minSize = 5; minSize = 5;
break; break;
// draw primitives // draw primitives
default: default:
if (Cmd & 0x80) if (Cmd & 0x80)
minSize = 3; minSize = 3;
break; break;
} }
return (iBufferSize >= minSize); return (iBufferSize >= minSize);
} }
return true; return true;
} }
void Run(u32 iBufferSize) 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. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // 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/ // http://code.google.com/p/dolphin-emu/
@ -25,39 +25,39 @@
namespace OpcodeDecoder namespace OpcodeDecoder
{ {
#define GX_NOP 0x00 #define GX_NOP 0x00
#define GX_LOAD_BP_REG 0x61 #define GX_LOAD_BP_REG 0x61
#define GX_LOAD_CP_REG 0x08 #define GX_LOAD_CP_REG 0x08
#define GX_LOAD_XF_REG 0x10 #define GX_LOAD_XF_REG 0x10
#define GX_LOAD_INDX_A 0x20 #define GX_LOAD_INDX_A 0x20
#define GX_LOAD_INDX_B 0x28 #define GX_LOAD_INDX_B 0x28
#define GX_LOAD_INDX_C 0x30 #define GX_LOAD_INDX_C 0x30
#define GX_LOAD_INDX_D 0x38 #define GX_LOAD_INDX_D 0x38
#define GX_CMD_CALL_DL 0x40 #define GX_CMD_CALL_DL 0x40
#define GX_CMD_INVL_VC 0x48 #define GX_CMD_INVL_VC 0x48
#define GX_PRIMITIVE_MASK 0x78 #define GX_PRIMITIVE_MASK 0x78
#define GX_PRIMITIVE_SHIFT 3 #define GX_PRIMITIVE_SHIFT 3
#define GX_VAT_MASK 0x07 #define GX_VAT_MASK 0x07
//these are defined 1/8th of their real values and without their top bit //these are defined 1/8th of their real values and without their top bit
#define GX_DRAW_QUADS 0x0 //0x80 #define GX_DRAW_QUADS 0x0 //0x80
#define GX_DRAW_TRIANGLES 0x2 //0x90 #define GX_DRAW_TRIANGLES 0x2 //0x90
#define GX_DRAW_TRIANGLE_STRIP 0x3 //0x98 #define GX_DRAW_TRIANGLE_STRIP 0x3 //0x98
#define GX_DRAW_TRIANGLE_FAN 0x4 //0xA0 #define GX_DRAW_TRIANGLE_FAN 0x4 //0xA0
#define GX_DRAW_LINES 0x5 //0xA8 #define GX_DRAW_LINES 0x5 //0xA8
#define GX_DRAW_LINE_STRIP 0x6 //0xB0 #define GX_DRAW_LINE_STRIP 0x6 //0xB0
#define GX_DRAW_POINTS 0x7 //0xB8 #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); void DoState(PointerWrap &p);
} }

View File

@ -12,7 +12,7 @@
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // 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/ // http://code.google.com/p/dolphin-emu/
#include "../../Plugin_VideoOGL/Src/GLUtil.h" #include "../../Plugin_VideoOGL/Src/GLUtil.h"
@ -23,110 +23,112 @@
// globals // globals
const GLubyte rasters[][13] = { const GLubyte rasters[][13] = {
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, 0x00, 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, 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, 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, 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, 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, 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, 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, 0x03, 0x03, 0x07, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0, 0xff},
{0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xc7, 0xfe, 0xc0, 0xc0, 0xc0, 0xe7, 0x7e}, {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, 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, 0xc3, 0xc3, 0xe7, 0x7e, 0xe7, 0xc3, 0xc3, 0xe7, 0x7e},
{0x00, 0x00, 0x7e, 0xe7, 0x03, 0x03, 0x03, 0x7f, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18}, {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}, {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, 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, 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, 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, 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, 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, 0x7f, 0xc0, 0xc0, 0xfe, 0xc3, 0xc3, 0x7e, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x33, 0x1e}, {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}, {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, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0},
{0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x18, 0x00}, {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}, {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, 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, 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, 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, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xfc, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 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}, {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}, {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, 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, 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, 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, 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, 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, 0xe7, 0xff, 0xdb, 0xc3, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0x3c, 0x66, 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}, {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, 0xff, 0x60, 0x30, 0x18, 0x0c, 0x06, 0xff, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x0f, 0x18, 0x18, 0x18, 0x38, 0xf0, 0x38, 0x18, 0x18, 0x18, 0x0f}, {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}, {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, 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, 0x06, 0x8f, 0xf1, 0x60, 0x00, 0x00, 0x00}
}; };
RasterFont::RasterFont() RasterFont::RasterFont()
{ {
// set GL modes // set GL modes
glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
// create the raster font // create the raster font
fontOffset = glGenLists(128); fontOffset = glGenLists(128);
for (int i = 32; i < 127; i++) { for (int i = 32; i < 127; i++)
{
glNewList(i + fontOffset, GL_COMPILE); glNewList(i + fontOffset, GL_COMPILE);
glBitmap(8, 13, 0.0f, 2.0f, 10.0f, 0.0f, rasters[i - 32]); glBitmap(8, 13, 0.0f, 2.0f, 10.0f, 0.0f, rasters[i - 32]);
glEndList(); glEndList();
@ -153,7 +155,8 @@ void RasterFont::printString(const char *s, double x, double y, double z)
char *s2 = temp_buffer; char *s2 = temp_buffer;
memcpy(s2, s, length); memcpy(s2, s, length);
s2[length] = 0; s2[length] = 0;
for (int i = 0; i < length; i++) { for (int i = 0; i < length; i++)
{
if (s2[i] < 32 || s2[i] > 126) if (s2[i] < 32 || s2[i] > 126)
s2[i] = '!'; s2[i] = '!';
} }
@ -209,7 +212,9 @@ void RasterFont::printMultilineText(const char *text, double start_x, double sta
*t++ = ' '; *t++ = ' ';
} }
else else
{
*t++ = *text; *t++ = *text;
}
text++; text++;
} }

View File

@ -12,30 +12,31 @@
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // 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/ // http://code.google.com/p/dolphin-emu/
#ifndef _RASTERFONT_H_ #ifndef _RASTERFONT_H_
#define _RASTERFONT_H_ #define _RASTERFONT_H_
class RasterFont { class RasterFont
{
public: public:
RasterFont(); RasterFont();
~RasterFont(void); ~RasterFont(void);
static int debug; static int debug;
// some useful constants // some useful constants
enum {char_width = 10}; enum {char_width = 10};
enum {char_height = 15}; enum {char_height = 15};
// and the happy helper functions // and the happy helper functions
void printString(const char *s, double x, double y, double z=0.0); 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 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); void printMultilineText(const char *text, double x, double y, double z, int bbWidth, int bbHeight);
private: private:
int fontOffset; int fontOffset;
char *temp_buffer; char *temp_buffer;
enum {TEMP_BUFFER_SIZE = 64 * 1024}; 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. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // 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/ // http://code.google.com/p/dolphin-emu/
#include "Common.h" #include "Common.h"
@ -97,34 +97,34 @@ void Init()
inline int iround(float x) inline int iround(float x)
{ {
int t; int t;
#if defined(_WIN32) && !defined(_M_X64) #if defined(_WIN32) && !defined(_M_X64)
__asm __asm
{ {
fld x fld x
fistp t fistp t
} }
#else #else
t = (int)x; t = (int)x;
if((x - t) >= 0.5) if((x - t) >= 0.5)
return t + 1; return t + 1;
#endif #endif
return t; return t;
} }
void SetScissor() void SetScissor()
{ {
int xoff = bpmem.scissorOffset.x * 2 - 342; int xoff = bpmem.scissorOffset.x * 2 - 342;
int yoff = bpmem.scissorOffset.y * 2 - 342; int yoff = bpmem.scissorOffset.y * 2 - 342;
scissorLeft = bpmem.scissorTL.x - xoff - 342; scissorLeft = bpmem.scissorTL.x - xoff - 342;
if (scissorLeft < 0) scissorLeft = 0; if (scissorLeft < 0) scissorLeft = 0;
scissorTop = bpmem.scissorTL.y - yoff - 342; scissorTop = bpmem.scissorTL.y - yoff - 342;
if (scissorTop < 0) scissorTop = 0; if (scissorTop < 0) scissorTop = 0;
scissorRight = bpmem.scissorBR.x - xoff - 341; scissorRight = bpmem.scissorBR.x - xoff - 341;
if (scissorRight > EFB_WIDTH) scissorRight = EFB_WIDTH; if (scissorRight > EFB_WIDTH) scissorRight = EFB_WIDTH;
@ -134,12 +134,12 @@ void SetScissor()
void SetTevReg(int reg, int comp, bool konst, s16 color) 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) 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 dx = vertexOffsetX + (float)(x - vertex0X);
float dy = vertexOffsetY + (float)(y - vertex0Y); 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.TextureLod[i] = rasterBlock.TextureLod[i];
tev.TextureLinear[i] = rasterBlock.TextureLinear[i]; tev.TextureLinear[i] = rasterBlock.TextureLinear[i];
} }
tev.Draw(); tev.Draw();
} }
void InitTriangle(float X1, float Y1, s32 xi, s32 yi) void InitTriangle(float X1, float Y1, s32 xi, s32 yi)
{ {
vertex0X = xi; vertex0X = xi;
vertex0Y = yi; vertex0Y = yi;
// adjust a little less than 0.5 // adjust a little less than 0.5
const float adjust = 0.495f; 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) void InitSlope(Slope *slope, float f1, float f2, float f3, float DX31, float DX12, float DY12, float DY31)
{ {
float DF31 = f3 - f1; float DF31 = f3 - f1;
float DF21 = f2 - f1; float DF21 = f2 - f1;
float a = DF31 * -DY12 - DF21 * DY31; float a = DF31 * -DY12 - DF21 * DY31;
float b = DX31 * DF21 + DX12 * DF31; float b = DX31 * DF21 + DX12 * DF31;
float c = -DX12 * DY31 - DX31 * -DY12; float c = -DX12 * DY31 - DX31 * -DY12;
slope->dfdx = -a / c; slope->dfdx = -a / c;
slope->dfdy = -b / c; slope->dfdy = -b / c;
slope->f0 = f1; slope->f0 = f1;
} }
inline void CalculateLOD(s32 &lod, bool &linear, u32 texmap, u32 texcoord) 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) void DrawTriangleFrontFace(OutputVertexData *v0, OutputVertexData *v1, OutputVertexData *v2)
{ {
INCSTAT(swstats.thisFrame.numTrianglesDrawn); INCSTAT(swstats.thisFrame.numTrianglesDrawn);
if (g_SWVideoConfig.bHwRasterizer) if (g_SWVideoConfig.bHwRasterizer)
{ {
HwRasterizer::DrawTriangleFrontFace(v0, v1, v2); HwRasterizer::DrawTriangleFrontFace(v0, v1, v2);
return; 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 // could also take floor and adjust -8
const s32 Y1 = iround(16.0f * v0->screenPosition[1]) - 9; const s32 Y1 = iround(16.0f * v0->screenPosition[1]) - 9;
const s32 Y2 = iround(16.0f * v1->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 X2 = iround(16.0f * v1->screenPosition[0]) - 9;
const s32 X3 = iround(16.0f * v2->screenPosition[0]) - 9; const s32 X3 = iround(16.0f * v2->screenPosition[0]) - 9;
// Deltas // Deltas
const s32 DX12 = X1 - X2; const s32 DX12 = X1 - X2;
const s32 DX23 = X2 - X3; const s32 DX23 = X2 - X3;
const s32 DX31 = X3 - X1; const s32 DX31 = X3 - X1;
const s32 DY12 = Y1 - Y2; const s32 DY12 = Y1 - Y2;
const s32 DY23 = Y2 - Y3; const s32 DY23 = Y2 - Y3;
const s32 DY31 = Y3 - Y1; const s32 DY31 = Y3 - Y1;
// Fixed-pos32 deltas // Fixed-pos32 deltas
const s32 FDX12 = DX12 << 4; const s32 FDX12 = DX12 << 4;
const s32 FDX23 = DX23 << 4; const s32 FDX23 = DX23 << 4;
const s32 FDX31 = DX31 << 4; const s32 FDX31 = DX31 << 4;
const s32 FDY12 = DY12 << 4; const s32 FDY12 = DY12 << 4;
const s32 FDY23 = DY23 << 4; const s32 FDY23 = DY23 << 4;
const s32 FDY31 = DY31 << 4; const s32 FDY31 = DY31 << 4;
// Bounding rectangle // Bounding rectangle
s32 minx = (min(min(X1, X2), X3) + 0xF) >> 4; s32 minx = (min(min(X1, X2), X3) + 0xF) >> 4;
s32 maxx = (max(max(X1, X2), X3) + 0xF) >> 4; s32 maxx = (max(max(X1, X2), X3) + 0xF) >> 4;
s32 miny = (min(min(Y1, Y2), Y3) + 0xF) >> 4; s32 miny = (min(min(Y1, Y2), Y3) + 0xF) >> 4;
s32 maxy = (max(max(Y1, Y2), Y3) + 0xF) >> 4; s32 maxy = (max(max(Y1, Y2), Y3) + 0xF) >> 4;
// scissor // scissor
minx = max(minx, scissorLeft); minx = max(minx, scissorLeft);
maxx = min(maxx, scissorRight); maxx = min(maxx, scissorRight);
miny = max(miny, scissorTop); miny = max(miny, scissorTop);
maxy = min(maxy, scissorBottom); maxy = min(maxy, scissorBottom);
if (minx >= maxx || miny >= maxy) if (minx >= maxx || miny >= maxy)
return; return;
// Setup slopes // Setup slopes
float fltx1 = v0->screenPosition.x; float fltx1 = v0->screenPosition.x;
float flty1 = v0->screenPosition.y; float flty1 = v0->screenPosition.y;
float fltdx31 = v2->screenPosition.x - fltx1; float fltdx31 = v2->screenPosition.x - fltx1;
float fltdx12 = fltx1 - v1->screenPosition.x; float fltdx12 = fltx1 - v1->screenPosition.x;
float fltdy12 = flty1 - v1->screenPosition.y; float fltdy12 = flty1 - v1->screenPosition.y;
float fltdy31 = v2->screenPosition.y - flty1; float fltdy31 = v2->screenPosition.y - flty1;
InitTriangle(fltx1, flty1, (X1 + 0xF) >> 4, (Y1 + 0xF) >> 4); 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 }; 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); InitSlope(&WSlope, w[0], w[1], w[2], fltdx31, fltdx12, fltdy12, fltdy31);
if (!bpmem.genMode.zfreeze || !g_SWVideoConfig.bZFreeze) 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(unsigned int i = 0; i < bpmem.genMode.numcolchans; i++)
{ {
for(int comp = 0; comp < 4; comp++) 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); 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(unsigned int i = 0; i < bpmem.genMode.numtexgens; i++)
{ {
for(int comp = 0; comp < 3; comp++) 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); 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 // Start in corner of 8x8 block
minx &= ~(BLOCK_SIZE - 1); minx &= ~(BLOCK_SIZE - 1);
miny &= ~(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;
// Correct for fill convention // Half-edge constants
if(DY12 < 0 || (DY12 == 0 && DX12 > 0)) C1++; s32 C1 = DY12 * X1 - DX12 * Y1;
if(DY23 < 0 || (DY23 == 0 && DX23 > 0)) C2++; s32 C2 = DY23 * X2 - DX23 * Y2;
if(DY31 < 0 || (DY31 == 0 && DX31 > 0)) C3++; s32 C3 = DY31 * X3 - DX31 * Y3;
// Loop through blocks // Correct for fill convention
for(s32 y = miny; y < maxy; y += BLOCK_SIZE) if(DY12 < 0 || (DY12 == 0 && DX12 > 0)) C1++;
{ if(DY23 < 0 || (DY23 == 0 && DX23 > 0)) C2++;
for(s32 x = minx; x < maxx; x += BLOCK_SIZE) if(DY31 < 0 || (DY31 == 0 && DX31 > 0)) C3++;
{
// 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;
// Evaluate half-space functions // Loop through blocks
bool a00 = C1 + DX12 * y0 - DY12 * x0 > 0; for(s32 y = miny; y < maxy; y += BLOCK_SIZE)
bool a10 = C1 + DX12 * y0 - DY12 * x1 > 0; {
bool a01 = C1 + DX12 * y1 - DY12 * x0 > 0; for(s32 x = minx; x < maxx; x += BLOCK_SIZE)
bool a11 = C1 + DX12 * y1 - DY12 * x1 > 0; {
int a = (a00 << 0) | (a10 << 1) | (a01 << 2) | (a11 << 3); // Corners of block
s32 x0 = x << 4;
bool b00 = C2 + DX23 * y0 - DY23 * x0 > 0; s32 x1 = (x + BLOCK_SIZE - 1) << 4;
bool b10 = C2 + DX23 * y0 - DY23 * x1 > 0; s32 y0 = y << 4;
bool b01 = C2 + DX23 * y1 - DY23 * x0 > 0; s32 y1 = (y + BLOCK_SIZE - 1) << 4;
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 // Evaluate half-space functions
if(a == 0x0 || b == 0x0 || c == 0x0) continue; 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); BuildBlock(x, y);
// Accept whole block when totally covered // Accept whole block when totally covered
if(a == 0xF && b == 0xF && c == 0xF) if(a == 0xF && b == 0xF && c == 0xF)
{ {
for(s32 iy = 0; iy < BLOCK_SIZE; iy++) for(s32 iy = 0; iy < BLOCK_SIZE; iy++)
{ {
for(s32 ix = 0; ix < BLOCK_SIZE; ix++) for(s32 ix = 0; ix < BLOCK_SIZE; ix++)
{ {
Draw(x + ix, y + iy, ix, iy); Draw(x + ix, y + iy, ix, iy);
} }
} }
} }
else // Partially covered block else // Partially covered block
{ {
s32 CY1 = C1 + DX12 * y0 - DY12 * x0; s32 CY1 = C1 + DX12 * y0 - DY12 * x0;
s32 CY2 = C2 + DX23 * y0 - DY23 * x0; s32 CY2 = C2 + DX23 * y0 - DY23 * x0;
s32 CY3 = C3 + DX31 * y0 - DY31 * x0; s32 CY3 = C3 + DX31 * y0 - DY31 * x0;
for(s32 iy = 0; iy < BLOCK_SIZE; iy++) for(s32 iy = 0; iy < BLOCK_SIZE; iy++)
{ {
s32 CX1 = CY1; s32 CX1 = CY1;
s32 CX2 = CY2; s32 CX2 = CY2;
s32 CX3 = CY3; s32 CX3 = CY3;
for(s32 ix = 0; ix < BLOCK_SIZE; ix++) for(s32 ix = 0; ix < BLOCK_SIZE; ix++)
{ {
if(CX1 > 0 && CX2 > 0 && CX3 > 0) if(CX1 > 0 && CX2 > 0 && CX3 > 0)
{ {
Draw(x + ix, y + iy, ix, iy); Draw(x + ix, y + iy, ix, iy);
} }
CX1 -= FDY12; CX1 -= FDY12;
CX2 -= FDY23; CX2 -= FDY23;
CX3 -= FDY31; CX3 -= FDY31;
} }
CY1 += FDX12;
CY2 += FDX23;
CY3 += FDX31;
}
}
}
}
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. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // 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/ // http://code.google.com/p/dolphin-emu/
#ifndef _RASTERIZER_H_ #ifndef _RASTERIZER_H_
@ -23,19 +23,19 @@
namespace Rasterizer 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 struct Slope
{ {
float dfdx; float dfdx;
float dfdy; float dfdy;
float f0; float f0;
float GetValue(float dx, float dy) { return f0 + (dfdx * dx) + (dfdy * dy); } float GetValue(float dx, float dy) { return f0 + (dfdx * dx) + (dfdy * dy); }
void DoState(PointerWrap &p) void DoState(PointerWrap &p)
@ -44,7 +44,7 @@ namespace Rasterizer
p.Do(dfdy); p.Do(dfdy);
p.Do(f0); p.Do(f0);
} }
}; };
struct RasterBlockPixel struct RasterBlockPixel
{ {
@ -62,7 +62,6 @@ namespace Rasterizer
}; };
void DoState(PointerWrap &p); void DoState(PointerWrap &p);
} }
#endif #endif

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -12,7 +12,7 @@
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // 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/ // http://code.google.com/p/dolphin-emu/
#include "SWStatistics.h" #include "SWStatistics.h"
@ -29,7 +29,7 @@ void Xchg(T& a, T&b)
SWStatistics::SWStatistics() SWStatistics::SWStatistics()
{ {
frameCount = 0; frameCount = 0;
} }
void SWStatistics::ResetFrame() void SWStatistics::ResetFrame()

View File

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

View File

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

View File

@ -12,7 +12,7 @@
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // 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/ // http://code.google.com/p/dolphin-emu/
#ifndef _VERTEXLOADER_H_ #ifndef _VERTEXLOADER_H_
@ -28,48 +28,48 @@ class SetupUnit;
class SWVertexLoader class SWVertexLoader
{ {
u32 m_VertexSize; u32 m_VertexSize;
VAT* m_CurrentVat; VAT* m_CurrentVat;
TPipelineFunction m_positionLoader;
TPipelineFunction m_normalLoader;
TPipelineFunction m_colorLoader[2];
TPipelineFunction m_texCoordLoader[8];
InputVertexData m_Vertex; TPipelineFunction m_positionLoader;
TPipelineFunction m_normalLoader;
TPipelineFunction m_colorLoader[2];
TPipelineFunction m_texCoordLoader[8];
typedef void (*AttributeLoader)(SWVertexLoader*, InputVertexData*, u8); InputVertexData m_Vertex;
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);
// attribute loader functions typedef void (*AttributeLoader)(SWVertexLoader*, InputVertexData*, u8);
static void LoadPosMtx(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 unused); struct AttrLoaderCall
static void LoadTexMtx(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 index); {
static void LoadPosition(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 unused); AttributeLoader loader;
static void LoadNormal(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 unused); u8 index;
static void LoadColor(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 index); };
static void LoadTexCoord(SWVertexLoader *vertexLoader, InputVertexData *vertex, 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; bool m_TexGenSpecialCase;
public: 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); void DoState(PointerWrap &p);
}; };

View File

@ -12,7 +12,7 @@
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // 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/ // http://code.google.com/p/dolphin-emu/
#include "FileUtil.h" #include "FileUtil.h"

View File

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

View File

@ -12,7 +12,7 @@
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // 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/ // 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; u32 value = 0;
switch (type) switch (type)
{ {
case PEEK_Z: case PEEK_Z:
{ {
value = EfbInterface::GetDepth(x, y); value = EfbInterface::GetDepth(x, y);
break; break;
} }
case POKE_Z:
break;
case PEEK_COLOR:
{
u32 color = 0;
EfbInterface::GetColor(x, y, (u8*)&color);
// rgba to argb case POKE_Z:
value = (color >> 8) | (color & 0xff) << 24; break;
break;
}
case POKE_COLOR:
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) u32 VideoSoftware::Video_GetQueryResult(PerfQueryType type)
@ -256,7 +258,7 @@ bool VideoSoftware::Video_Screenshot(const char *_szFilename)
void VideoSoftware::Video_EnterLoop() void VideoSoftware::Video_EnterLoop()
{ {
std::lock_guard<std::mutex> lk(m_csSWVidOccupied); std::lock_guard<std::mutex> lk(m_csSWVidOccupied);
fifoStateRun = true; fifoStateRun = true;
while (fifoStateRun) while (fifoStateRun)
{ {
@ -279,7 +281,7 @@ void VideoSoftware::Video_EnterLoop()
void VideoSoftware::Video_ExitLoop() 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 // 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. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // 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/ // http://code.google.com/p/dolphin-emu/
#include "SetupUnit.h" #include "SetupUnit.h"
@ -27,7 +27,7 @@ void SetupUnit::Init(u8 primitiveType)
{ {
m_PrimType = primitiveType; m_PrimType = primitiveType;
m_VertexCounter = 0; m_VertexCounter = 0;
m_VertPointer[0] = &m_Vertices[0]; m_VertPointer[0] = &m_Vertices[0];
m_VertPointer[1] = &m_Vertices[1]; m_VertPointer[1] = &m_Vertices[1];
m_VertPointer[2] = &m_Vertices[2]; m_VertPointer[2] = &m_Vertices[2];
@ -36,130 +36,130 @@ void SetupUnit::Init(u8 primitiveType)
void SetupUnit::SetupVertex() void SetupUnit::SetupVertex()
{ {
switch(m_PrimType) switch(m_PrimType)
{ {
case GX_DRAW_QUADS: case GX_DRAW_QUADS:
SetupQuad(); SetupQuad();
break; break;
case GX_DRAW_TRIANGLES: case GX_DRAW_TRIANGLES:
SetupTriangle(); SetupTriangle();
break; break;
case GX_DRAW_TRIANGLE_STRIP: case GX_DRAW_TRIANGLE_STRIP:
SetupTriStrip(); SetupTriStrip();
break; break;
case GX_DRAW_TRIANGLE_FAN: case GX_DRAW_TRIANGLE_FAN:
SetupTriFan(); SetupTriFan();
break; break;
case GX_DRAW_LINES: case GX_DRAW_LINES:
SetupLine(); SetupLine();
break; break;
case GX_DRAW_LINE_STRIP: case GX_DRAW_LINE_STRIP:
SetupLineStrip(); SetupLineStrip();
break; break;
case GX_DRAW_POINTS: case GX_DRAW_POINTS:
SetupPoint(); SetupPoint();
break; break;
} }
} }
void SetupUnit::SetupQuad() void SetupUnit::SetupQuad()
{ {
if (m_VertexCounter < 2) if (m_VertexCounter < 2)
{ {
m_VertexCounter++; m_VertexCounter++;
m_VertWritePointer = m_VertPointer[m_VertexCounter]; m_VertWritePointer = m_VertPointer[m_VertexCounter];
return; 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++;
m_VertexCounter &= 3; m_VertexCounter &= 3;
m_VertWritePointer = &m_Vertices[m_VertexCounter & 1]; m_VertWritePointer = &m_Vertices[m_VertexCounter & 1];
OutputVertexData* temp = m_VertPointer[1]; OutputVertexData* temp = m_VertPointer[1];
m_VertPointer[1] = m_VertPointer[2]; m_VertPointer[1] = m_VertPointer[2];
m_VertPointer[2] = temp; m_VertPointer[2] = temp;
} }
void SetupUnit::SetupTriangle() void SetupUnit::SetupTriangle()
{ {
if (m_VertexCounter < 2) if (m_VertexCounter < 2)
{ {
m_VertexCounter++; m_VertexCounter++;
m_VertWritePointer = m_VertPointer[m_VertexCounter]; m_VertWritePointer = m_VertPointer[m_VertexCounter];
return; 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_VertexCounter = 0;
m_VertWritePointer = m_VertPointer[0]; m_VertWritePointer = m_VertPointer[0];
} }
void SetupUnit::SetupTriStrip() void SetupUnit::SetupTriStrip()
{ {
if (m_VertexCounter < 2) if (m_VertexCounter < 2)
{ {
m_VertexCounter++; m_VertexCounter++;
m_VertWritePointer = m_VertPointer[m_VertexCounter]; m_VertWritePointer = m_VertPointer[m_VertexCounter];
return; 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++;
m_VertPointer[2 - (m_VertexCounter & 1)] = m_VertPointer[0]; m_VertPointer[2 - (m_VertexCounter & 1)] = m_VertPointer[0];
m_VertWritePointer = 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() void SetupUnit::SetupTriFan()
{ {
if (m_VertexCounter < 2) if (m_VertexCounter < 2)
{ {
m_VertexCounter++; m_VertexCounter++;
m_VertWritePointer = m_VertPointer[m_VertexCounter]; m_VertWritePointer = m_VertPointer[m_VertexCounter];
return; 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++;
m_VertPointer[1] = m_VertPointer[2]; m_VertPointer[1] = m_VertPointer[2];
m_VertPointer[2] = &m_Vertices[2 - (m_VertexCounter & 1)]; m_VertPointer[2] = &m_Vertices[2 - (m_VertexCounter & 1)];
m_VertWritePointer = m_VertPointer[2]; m_VertWritePointer = m_VertPointer[2];
} }
void SetupUnit::SetupLine() void SetupUnit::SetupLine()
{ {
if (m_VertexCounter < 1) if (m_VertexCounter < 1)
{ {
m_VertexCounter++; m_VertexCounter++;
m_VertWritePointer = m_VertPointer[m_VertexCounter]; m_VertWritePointer = m_VertPointer[m_VertexCounter];
return; return;
} }
Clipper::ProcessLine(m_VertPointer[0], m_VertPointer[1]); Clipper::ProcessLine(m_VertPointer[0], m_VertPointer[1]);
m_VertexCounter = 0; m_VertexCounter = 0;
m_VertWritePointer = m_VertPointer[0]; m_VertWritePointer = m_VertPointer[0];
} }
void SetupUnit::SetupLineStrip() void SetupUnit::SetupLineStrip()
{ {
if (m_VertexCounter < 1) if (m_VertexCounter < 1)
{ {
m_VertexCounter++; m_VertexCounter++;
m_VertWritePointer = m_VertPointer[m_VertexCounter]; m_VertWritePointer = m_VertPointer[m_VertexCounter];
return; return;
} }
m_VertexCounter++; m_VertexCounter++;
Clipper::ProcessLine(m_VertPointer[0], m_VertPointer[1]); Clipper::ProcessLine(m_VertPointer[0], m_VertPointer[1]);
m_VertWritePointer = m_VertPointer[0]; 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. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // 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/ // http://code.google.com/p/dolphin-emu/
@ -25,27 +25,27 @@
class SetupUnit class SetupUnit
{ {
u8 m_PrimType; u8 m_PrimType;
int m_VertexCounter; int m_VertexCounter;
OutputVertexData m_Vertices[3]; OutputVertexData m_Vertices[3];
OutputVertexData *m_VertPointer[3]; OutputVertexData *m_VertPointer[3];
OutputVertexData *m_VertWritePointer; OutputVertexData *m_VertWritePointer;
void SetupQuad(); void SetupQuad();
void SetupTriangle(); void SetupTriangle();
void SetupTriStrip(); void SetupTriStrip();
void SetupTriFan(); void SetupTriFan();
void SetupLine(); void SetupLine();
void SetupLineStrip(); void SetupLineStrip();
void SetupPoint(); void SetupPoint();
public: 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); 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. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // 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/ // http://code.google.com/p/dolphin-emu/
#ifndef _TEV_H_ #ifndef _TEV_H_
@ -23,12 +23,13 @@
class Tev class Tev
{ {
struct InputRegType { struct InputRegType
unsigned a : 8; {
unsigned b : 8; unsigned a : 8;
unsigned c : 8; unsigned b : 8;
signed d : 11; unsigned c : 8;
}; signed d : 11;
};
struct TextureCoordinateType struct TextureCoordinateType
{ {
@ -36,26 +37,26 @@ class Tev
signed t : 24; signed t : 24;
}; };
// color order: ABGR // color order: ABGR
s16 Reg[4][4]; s16 Reg[4][4];
s16 KonstantColors[4][4]; s16 KonstantColors[4][4];
s16 TexColor[4]; s16 TexColor[4];
s16 RasColor[4]; s16 RasColor[4];
s16 StageKonst[4]; s16 StageKonst[4];
s16 Zero16[4]; s16 Zero16[4];
s16 FixedConstants[9]; s16 FixedConstants[9];
u8 AlphaBump; u8 AlphaBump;
u8 IndirectTex[4][4]; u8 IndirectTex[4][4];
TextureCoordinateType TexCoord; TextureCoordinateType TexCoord;
s16 *m_ColorInputLUT[16][3]; s16 *m_ColorInputLUT[16][3];
s16 *m_AlphaInputLUT[8]; // values must point to ABGR color s16 *m_AlphaInputLUT[8]; // values must point to ABGR color
s16 *m_KonstLUT[32][4]; s16 *m_KonstLUT[32][4];
u8 *m_RasColorLUT[8]; u8 *m_RasColorLUT[8];
s16 m_BiasLUT[4]; s16 m_BiasLUT[4];
u8 m_ScaleLShiftLUT[4]; u8 m_ScaleLShiftLUT[4];
u8 m_ScaleRShiftLUT[4]; u8 m_ScaleRShiftLUT[4];
// enumeration for color input LUT // enumeration for color input LUT
enum enum
@ -72,29 +73,29 @@ class Tev
INDIRECT = 32 INDIRECT = 32
}; };
void SetRasColor(int colorChan, int swaptable); void SetRasColor(int colorChan, int swaptable);
void DrawColorRegular(TevStageCombiner::ColorCombiner &cc); void DrawColorRegular(TevStageCombiner::ColorCombiner &cc);
void DrawColorCompare(TevStageCombiner::ColorCombiner &cc); void DrawColorCompare(TevStageCombiner::ColorCombiner &cc);
void DrawAlphaRegular(TevStageCombiner::AlphaCombiner &ac); void DrawAlphaRegular(TevStageCombiner::AlphaCombiner &ac);
void DrawAlphaCompare(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: public:
s32 Position[3]; s32 Position[3];
u8 Color[2][4]; // must be RGBA for correct swap table ordering u8 Color[2][4]; // must be RGBA for correct swap table ordering
TextureCoordinateType Uv[8]; TextureCoordinateType Uv[8];
s32 IndirectLod[4]; s32 IndirectLod[4];
bool IndirectLinear[4]; bool IndirectLinear[4];
s32 TextureLod[16]; s32 TextureLod[16];
bool TextureLinear[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 }; 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. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // 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/ // http://code.google.com/p/dolphin-emu/
@ -23,7 +23,7 @@
namespace TextureEncoder namespace TextureEncoder
{ {
void Encode(u8 *dest_ptr); void Encode(u8 *dest_ptr);
} }
#endif #endif

View File

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

View File

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

View File

@ -12,7 +12,7 @@
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // 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/ // http://code.google.com/p/dolphin-emu/
#ifndef _VEC3_H #ifndef _VEC3_H

View File

@ -12,7 +12,7 @@
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // 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/ // http://code.google.com/p/dolphin-emu/
#include "VideoConfigDiag.h" #include "VideoConfigDiag.h"

View File

@ -12,7 +12,7 @@
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // 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/ // http://code.google.com/p/dolphin-emu/
#ifndef _VIDEOSOFTWARE_CONFIG_DIAG_H_ #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. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // 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/ // http://code.google.com/p/dolphin-emu/
#include "VideoCommon.h" #include "VideoCommon.h"
@ -26,15 +26,15 @@ XFRegisters swxfregs;
void InitXFMemory() void InitXFMemory()
{ {
memset(&swxfregs, 0, sizeof(swxfregs)); memset(&swxfregs, 0, sizeof(swxfregs));
} }
void XFWritten(u32 transferSize, u32 baseAddress) void XFWritten(u32 transferSize, u32 baseAddress)
{ {
u32 topAddress = baseAddress + transferSize; u32 topAddress = baseAddress + transferSize;
if (baseAddress <= 0x1026 && topAddress >= 0x1020) if (baseAddress <= 0x1026 && topAddress >= 0x1020)
Clipper::SetViewOffset(); Clipper::SetViewOffset();
// fix lights so invalid values don't trash the lighting computations // fix lights so invalid values don't trash the lighting computations
if (baseAddress <= 0x067f && topAddress >= 0x0604) if (baseAddress <= 0x067f && topAddress >= 0x0604)
@ -63,32 +63,32 @@ void XFWritten(u32 transferSize, u32 baseAddress)
void SWLoadXFReg(u32 transferSize, u32 baseAddress, u32 *pData) void SWLoadXFReg(u32 transferSize, u32 baseAddress, u32 *pData)
{ {
u32 size = transferSize; u32 size = transferSize;
// do not allow writes past registers // do not allow writes past registers
if (baseAddress + transferSize > 0x1058) if (baseAddress + transferSize > 0x1058)
{ {
INFO_LOG(VIDEO, "xf load exceeds address space: %x %d bytes\n", baseAddress, transferSize); INFO_LOG(VIDEO, "xf load exceeds address space: %x %d bytes\n", baseAddress, transferSize);
if (baseAddress >= 0x1058) if (baseAddress >= 0x1058)
size = 0; size = 0;
else else
size = 0x1058 - baseAddress; size = 0x1058 - baseAddress;
} }
if (size > 0) {
memcpy_gc( &((u32*)&swxfregs)[baseAddress], pData, size * 4);
XFWritten(transferSize, baseAddress);
}
if (size > 0)
{
memcpy_gc( &((u32*)&swxfregs)[baseAddress], pData, size * 4);
XFWritten(transferSize, baseAddress);
}
} }
void SWLoadIndexedXF(u32 val, int array) void SWLoadIndexedXF(u32 val, int array)
{ {
int index = val >> 16; int index = val >> 16;
int address = val & 0xFFF; //check mask int address = val & 0xFFF; //check mask
int size = ((val >> 12) & 0xF) + 1; int size = ((val >> 12) & 0xF) + 1;
//load stuff from array to address in xf mem //load stuff from array to address in xf mem
u32 *pData = (u32*)Memory::GetPointer(arraybases[array] + arraystrides[array]*index); 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. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // 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/ // http://code.google.com/p/dolphin-emu/
#ifndef _XFMEMLOADER_H_ #ifndef _XFMEMLOADER_H_
@ -31,49 +31,49 @@
#define XF_TEXINPUT_AB11 0 #define XF_TEXINPUT_AB11 0
#define XF_TEXINPUT_ABC1 1 #define XF_TEXINPUT_ABC1 1
#define XF_TEXGEN_REGULAR 0 #define XF_TEXGEN_REGULAR 0
#define XF_TEXGEN_EMBOSS_MAP 1 // used when bump mapping #define XF_TEXGEN_EMBOSS_MAP 1 // used when bump mapping
#define XF_TEXGEN_COLOR_STRGBC0 2 #define XF_TEXGEN_COLOR_STRGBC0 2
#define XF_TEXGEN_COLOR_STRGBC1 3 #define XF_TEXGEN_COLOR_STRGBC1 3
#define XF_SRCGEOM_INROW 0 // input is abc #define XF_SRCGEOM_INROW 0 // input is abc
#define XF_SRCNORMAL_INROW 1 // input is abc #define XF_SRCNORMAL_INROW 1 // input is abc
#define XF_SRCCOLORS_INROW 2 #define XF_SRCCOLORS_INROW 2
#define XF_SRCBINORMAL_T_INROW 3 // input is abc #define XF_SRCBINORMAL_T_INROW 3 // input is abc
#define XF_SRCBINORMAL_B_INROW 4 // input is abc #define XF_SRCBINORMAL_B_INROW 4 // input is abc
#define XF_SRCTEX0_INROW 5 #define XF_SRCTEX0_INROW 5
#define XF_SRCTEX1_INROW 6 #define XF_SRCTEX1_INROW 6
#define XF_SRCTEX2_INROW 7 #define XF_SRCTEX2_INROW 7
#define XF_SRCTEX3_INROW 8 #define XF_SRCTEX3_INROW 8
#define XF_SRCTEX4_INROW 9 #define XF_SRCTEX4_INROW 9
#define XF_SRCTEX5_INROW 10 #define XF_SRCTEX5_INROW 10
#define XF_SRCTEX6_INROW 11 #define XF_SRCTEX6_INROW 11
#define XF_SRCTEX7_INROW 12 #define XF_SRCTEX7_INROW 12
#define GX_SRC_REG 0 #define GX_SRC_REG 0
#define GX_SRC_VTX 1 #define GX_SRC_VTX 1
struct Light struct Light
{ {
u32 useless[3]; u32 useless[3];
u32 color; //rgba u32 color; //rgba
float a0; //attenuation float a0; //attenuation
float a1; float a1;
float a2; float a2;
float k0; //k stuff float k0; //k stuff
float k1; float k1;
float k2; float k2;
union union
{ {
struct { struct {
float dpos[3]; float dpos[3];
float ddir[3]; // specular lights only float ddir[3]; // specular lights only
}; };
struct { struct {
float sdir[3]; float sdir[3];
float shalfangle[3]; // specular lights only float shalfangle[3]; // specular lights only
}; };
}; };
}; };
#define LIGHTDIF_NONE 0 #define LIGHTDIF_NONE 0
@ -83,74 +83,74 @@ struct Light
#define LIGHTATTN_SPEC 0 // specular attenuation #define LIGHTATTN_SPEC 0 // specular attenuation
#define LIGHTATTN_SPOT 1 // distance/spotlight attenuation #define LIGHTATTN_SPOT 1 // distance/spotlight attenuation
#define LIGHTATTN_NONE 2 #define LIGHTATTN_NONE 2
#define LIGHTATTN_DIR 3 #define LIGHTATTN_DIR 3
#define GX_PERSPECTIVE 0 #define GX_PERSPECTIVE 0
#define GX_ORTHOGRAPHIC 1 #define GX_ORTHOGRAPHIC 1
union LitChannel union LitChannel
{ {
struct struct
{ {
u32 matsource : 1; u32 matsource : 1;
u32 enablelighting : 1; u32 enablelighting : 1;
u32 lightMask0_3 : 4; u32 lightMask0_3 : 4;
u32 ambsource : 1; u32 ambsource : 1;
u32 diffusefunc : 2; // LIGHTDIF_X u32 diffusefunc : 2; // LIGHTDIF_X
u32 attnfunc : 2; // LIGHTATTN_X u32 attnfunc : 2; // LIGHTATTN_X
u32 lightMask4_7 : 4; u32 lightMask4_7 : 4;
u32 unused : 17; u32 unused : 17;
}; };
u32 hex; u32 hex;
unsigned int GetFullLightMask() const unsigned int GetFullLightMask() const
{ {
return enablelighting ? (lightMask0_3 | (lightMask4_7 << 4)) : 0; return enablelighting ? (lightMask0_3 | (lightMask4_7 << 4)) : 0;
} }
}; };
union INVTXSPEC union INVTXSPEC
{ {
struct struct
{ {
u32 numcolors : 2; u32 numcolors : 2;
u32 numnormals : 2; // 0 - nothing, 1 - just normal, 2 - normals and binormals u32 numnormals : 2; // 0 - nothing, 1 - just normal, 2 - normals and binormals
u32 numtextures : 4; u32 numtextures : 4;
u32 unused : 24; u32 unused : 24;
}; };
u32 hex; u32 hex;
}; };
union TXFMatrixIndexA union TXFMatrixIndexA
{ {
struct struct
{ {
u32 PosNormalMtxIdx : 6; u32 PosNormalMtxIdx : 6;
u32 Tex0MtxIdx : 6; u32 Tex0MtxIdx : 6;
u32 Tex1MtxIdx : 6; u32 Tex1MtxIdx : 6;
u32 Tex2MtxIdx : 6; u32 Tex2MtxIdx : 6;
u32 Tex3MtxIdx : 6; u32 Tex3MtxIdx : 6;
}; };
struct struct
{ {
u32 Hex : 30; u32 Hex : 30;
u32 unused : 2; u32 unused : 2;
}; };
}; };
union TXFMatrixIndexB union TXFMatrixIndexB
{ {
struct struct
{ {
u32 Tex4MtxIdx : 6; u32 Tex4MtxIdx : 6;
u32 Tex5MtxIdx : 6; u32 Tex5MtxIdx : 6;
u32 Tex6MtxIdx : 6; u32 Tex6MtxIdx : 6;
u32 Tex7MtxIdx : 6; u32 Tex7MtxIdx : 6;
}; };
struct struct
{ {
u32 Hex : 24; u32 Hex : 24;
u32 unused : 8; u32 unused : 8;
}; };
}; };
struct Viewport struct Viewport
@ -171,68 +171,68 @@ struct Projection
union TexMtxInfo union TexMtxInfo
{ {
struct struct
{ {
u32 unknown : 1; u32 unknown : 1;
u32 projection : 1; // XF_TEXPROJ_X u32 projection : 1; // XF_TEXPROJ_X
u32 inputform : 2; // XF_TEXINPUT_X u32 inputform : 2; // XF_TEXINPUT_X
u32 texgentype : 3; // XF_TEXGEN_X u32 texgentype : 3; // XF_TEXGEN_X
u32 sourcerow : 5; // XF_SRCGEOM_X u32 sourcerow : 5; // XF_SRCGEOM_X
u32 embosssourceshift : 3; // what generated texcoord to use u32 embosssourceshift : 3; // what generated texcoord to use
u32 embosslightshift : 3; // light index that is used u32 embosslightshift : 3; // light index that is used
}; };
u32 hex; u32 hex;
}; };
union PostMtxInfo union PostMtxInfo
{ {
struct struct
{ {
u32 index : 6; // base row of dual transform matrix u32 index : 6; // base row of dual transform matrix
u32 unused : 2; u32 unused : 2;
u32 normalize : 1; // normalize before send operation u32 normalize : 1; // normalize before send operation
}; };
u32 hex; u32 hex;
}; };
struct XFRegisters struct XFRegisters
{ {
u32 posMatrices[256]; // 0x0000 - 0x00ff u32 posMatrices[256]; // 0x0000 - 0x00ff
u32 unk0[768]; // 0x0100 - 0x03ff u32 unk0[768]; // 0x0100 - 0x03ff
u32 normalMatrices[96]; // 0x0400 - 0x045f u32 normalMatrices[96]; // 0x0400 - 0x045f
u32 unk1[160]; // 0x0460 - 0x04ff u32 unk1[160]; // 0x0460 - 0x04ff
u32 postMatrices[256]; // 0x0500 - 0x05ff u32 postMatrices[256]; // 0x0500 - 0x05ff
u32 lights[128]; // 0x0600 - 0x067f u32 lights[128]; // 0x0600 - 0x067f
u32 unk2[2432]; // 0x0680 - 0x0fff u32 unk2[2432]; // 0x0680 - 0x0fff
u32 error; // 0x1000 u32 error; // 0x1000
u32 diag; // 0x1001 u32 diag; // 0x1001
u32 state0; // 0x1002 u32 state0; // 0x1002
u32 state1; // 0x1003 u32 state1; // 0x1003
u32 xfClock; // 0x1004 u32 xfClock; // 0x1004
u32 clipDisable; // 0x1005 u32 clipDisable; // 0x1005
u32 perf0; // 0x1006 u32 perf0; // 0x1006
u32 perf1; // 0x1007 u32 perf1; // 0x1007
INVTXSPEC hostinfo; // 0x1008 number of textures,colors,normals from vertex input INVTXSPEC hostinfo; // 0x1008 number of textures,colors,normals from vertex input
u32 nNumChans; // 0x1009 u32 nNumChans; // 0x1009
u32 ambColor[2]; // 0x100a, 0x100b u32 ambColor[2]; // 0x100a, 0x100b
u32 matColor[2]; // 0x100c, 0x100d u32 matColor[2]; // 0x100c, 0x100d
LitChannel color[2]; // 0x100e, 0x100f LitChannel color[2]; // 0x100e, 0x100f
LitChannel alpha[2]; // 0x1010, 0x1011 LitChannel alpha[2]; // 0x1010, 0x1011
u32 dualTexTrans; // 0x1012 u32 dualTexTrans; // 0x1012
u32 unk3; // 0x1013 u32 unk3; // 0x1013
u32 unk4; // 0x1014 u32 unk4; // 0x1014
u32 unk5; // 0x1015 u32 unk5; // 0x1015
u32 unk6; // 0x1016 u32 unk6; // 0x1016
u32 unk7; // 0x1017 u32 unk7; // 0x1017
TXFMatrixIndexA MatrixIndexA; // 0x1018 TXFMatrixIndexA MatrixIndexA; // 0x1018
TXFMatrixIndexB MatrixIndexB; // 0x1019 TXFMatrixIndexB MatrixIndexB; // 0x1019
Viewport viewport; // 0x101a - 0x101f Viewport viewport; // 0x101a - 0x101f
Projection projection; // 0x1020 - 0x1026 Projection projection; // 0x1020 - 0x1026
u32 unk8[24]; // 0x1027 - 0x103e u32 unk8[24]; // 0x1027 - 0x103e
u32 numTexGens; // 0x103f u32 numTexGens; // 0x103f
TexMtxInfo texMtxInfo[8]; // 0x1040 - 0x1047 TexMtxInfo texMtxInfo[8]; // 0x1040 - 0x1047
u32 unk9[8]; // 0x1048 - 0x104f u32 unk9[8]; // 0x1048 - 0x104f
PostMtxInfo postMtxInfo[8]; // 0x1050 - 0x1057 PostMtxInfo postMtxInfo[8]; // 0x1050 - 0x1057
}; };
#define XFMEM_POSMATRICES 0x000 #define XFMEM_POSMATRICES 0x000
@ -249,7 +249,7 @@ extern XFRegisters swxfregs;
void InitXFMemory(); void InitXFMemory();
void XFWritten(u32 transferSize, u32 baseAddress); void XFWritten(u32 transferSize, u32 baseAddress);
void SWLoadXFReg(u32 transferSize, u32 baseAddress, u32 *pData); 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. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // 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/ // http://code.google.com/p/dolphin-emu/
#include "stdafx.h" #include "stdafx.h"

View File

@ -12,7 +12,7 @@
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // 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/ // http://code.google.com/p/dolphin-emu/
#pragma once #pragma once