Merge remote-tracking branch 'origin/master' into Android-trash

Conflicts:
	Source/Plugins/Plugin_VideoSoftware/Src/SWRenderer.cpp
This commit is contained in:
Ryan Houdek 2013-04-14 20:43:42 -05:00
commit 37b67971e7
52 changed files with 4634 additions and 4568 deletions

View File

@ -535,7 +535,7 @@ bool Subtype_RamWriteAndFill(const ARAddr addr, const u32 data)
case DATATYPE_32BIT_FLOAT: case DATATYPE_32BIT_FLOAT:
case DATATYPE_32BIT: // Dword write case DATATYPE_32BIT: // Dword write
LogInfo("32bit Write"); LogInfo("32-bit Write");
LogInfo("--------"); LogInfo("--------");
Memory::Write_U32(data, new_addr); Memory::Write_U32(data, new_addr);
LogInfo("Wrote %08x to address %08x", data, new_addr); LogInfo("Wrote %08x to address %08x", data, new_addr);

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 { enum {
SKIP_FLAG = -1, SKIP_FLAG = -1,
CLIP_POS_X_BIT = 0x01, CLIP_POS_X_BIT = 0x01,
CLIP_NEG_X_BIT = 0x02, CLIP_NEG_X_BIT = 0x02,
CLIP_POS_Y_BIT = 0x04, CLIP_POS_Y_BIT = 0x04,
CLIP_NEG_Y_BIT = 0x08, CLIP_NEG_Y_BIT = 0x08,
CLIP_POS_Z_BIT = 0x10, CLIP_POS_Z_BIT = 0x10,
CLIP_NEG_Z_BIT = 0x20 CLIP_NEG_Z_BIT = 0x20
}; };
static inline int CalcClipMask(OutputVertexData *v) static inline int CalcClipMask(OutputVertexData *v)
{ {
int cmask = 0; int cmask = 0;
Vec4 pos = v->projectedPosition; Vec4 pos = v->projectedPosition;
if (pos.w - pos.x < 0) cmask |= CLIP_POS_X_BIT; if (pos.w - pos.x < 0) cmask |= CLIP_POS_X_BIT;
if (pos.x + pos.w < 0) cmask |= CLIP_NEG_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.w - pos.y < 0) cmask |= CLIP_POS_Y_BIT;
if (pos.y + pos.w < 0) cmask |= CLIP_NEG_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.w * pos.z > 0) cmask |= CLIP_POS_Z_BIT;
if (pos.z + pos.w < 0) cmask |= CLIP_NEG_Z_BIT; if (pos.z + pos.w < 0) cmask |= CLIP_NEG_Z_BIT;
return cmask; return cmask;
} }
static inline void AddInterpolatedVertex(float t, int out, int in, int& numVertices) static inline void AddInterpolatedVertex(float t, int out, int in, int& numVertices)
{ {
Vertices[numVertices]->Lerp(t, Vertices[out], Vertices[in]); Vertices[numVertices]->Lerp(t, Vertices[out], Vertices[in]);
numVertices++; numVertices++;
} }
#define DIFFERENT_SIGNS(x,y) ((x <= 0 && y > 0) || (x > 0 && y <= 0)) #define DIFFERENT_SIGNS(x,y) ((x <= 0 && y > 0) || (x > 0 && y <= 0))
#define CLIP_DOTPROD(I, 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) (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 POLY_CLIP( PLANE_BIT, A, B, C, D ) \
{ \ { \
if (mask & PLANE_BIT) { \ if (mask & PLANE_BIT) { \
int idxPrev = inlist[0]; \ int idxPrev = inlist[0]; \
float dpPrev = CLIP_DOTPROD(idxPrev, A, B, C, D ); \ float dpPrev = CLIP_DOTPROD(idxPrev, A, B, C, D ); \
int outcount = 0; \ int outcount = 0; \
\ \
inlist[n] = inlist[0]; \ inlist[n] = inlist[0]; \
for (int j = 1; j <= n; j++) { \ for (int j = 1; j <= n; j++) { \
int idx = inlist[j]; \ int idx = inlist[j]; \
float dp = CLIP_DOTPROD(idx, A, B, C, D ); \ float dp = CLIP_DOTPROD(idx, A, B, C, D ); \
if (dpPrev >= 0) { \ if (dpPrev >= 0) { \
outlist[outcount++] = idxPrev; \ outlist[outcount++] = idxPrev; \
} \ } \
\ \
if (DIFFERENT_SIGNS(dp, dpPrev)) { \ if (DIFFERENT_SIGNS(dp, dpPrev)) { \
if (dp < 0) { \ if (dp < 0) { \
float t = dp / (dp - dpPrev); \ float t = dp / (dp - dpPrev); \
AddInterpolatedVertex(t, idx, idxPrev, numVertices); \ AddInterpolatedVertex(t, idx, idxPrev, numVertices); \
} else { \ } else { \
float t = dpPrev / (dpPrev - dp); \ float t = dpPrev / (dpPrev - dp); \
AddInterpolatedVertex(t, idxPrev, idx, numVertices); \ AddInterpolatedVertex(t, idxPrev, idx, numVertices); \
} \ } \
outlist[outcount++] = numVertices - 1; \ outlist[outcount++] = numVertices - 1; \
} \ } \
\ \
idxPrev = idx; \ idxPrev = idx; \
dpPrev = dp; \ dpPrev = dp; \
} \ } \
\ \
if (outcount < 3) \ if (outcount < 3) \
continue; \ continue; \
\ \
{ \ { \
int *tmp = inlist; \ int *tmp = inlist; \
inlist = outlist; \ inlist = outlist; \
outlist = tmp; \ outlist = tmp; \
n = outcount; \ 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[0]);
mask |= CalcClipMask(Vertices[1]); mask |= CalcClipMask(Vertices[1]);
mask |= CalcClipMask(Vertices[2]); mask |= CalcClipMask(Vertices[2]);
if (mask != 0) if (mask != 0)
{ {
for(int i = 0; i < 3; i += 3) for(int i = 0; i < 3; i += 3)
{ {
int vlist[2][2*6+1]; int vlist[2][2*6+1];
int *inlist = vlist[0], *outlist = vlist[1]; int *inlist = vlist[0], *outlist = vlist[1];
int n = 3; int n = 3;
int numVertices = 3; int numVertices = 3;
inlist[0] = 0; inlist[0] = 0;
inlist[1] = 1; inlist[1] = 1;
inlist[2] = 2; inlist[2] = 2;
// mark this triangle as unused in case it should be completely // mark this triangle as unused in case it should be completely
// clipped // clipped
indices[0] = SKIP_FLAG; indices[0] = SKIP_FLAG;
indices[1] = SKIP_FLAG; indices[1] = SKIP_FLAG;
indices[2] = SKIP_FLAG; indices[2] = SKIP_FLAG;
POLY_CLIP(CLIP_POS_X_BIT, -1, 0, 0, 1); POLY_CLIP(CLIP_POS_X_BIT, -1, 0, 0, 1);
POLY_CLIP(CLIP_NEG_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_POS_Y_BIT, 0, -1, 0, 1);
POLY_CLIP(CLIP_NEG_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_POS_Z_BIT, 0, 0, 0, 1);
POLY_CLIP(CLIP_NEG_Z_BIT, 0, 0, 1, 1); POLY_CLIP(CLIP_NEG_Z_BIT, 0, 0, 1, 1);
INCSTAT(swstats.thisFrame.numTrianglesClipped); INCSTAT(swstats.thisFrame.numTrianglesClipped);
// transform the poly in inlist into triangles // transform the poly in inlist into triangles
indices[0] = inlist[0]; indices[0] = inlist[0];
indices[1] = inlist[1]; indices[1] = inlist[1];
indices[2] = inlist[2]; indices[2] = inlist[2];
for (int j = 3; j < n; ++j) { for (int j = 3; j < n; ++j) {
indices[numIndices++] = inlist[0]; indices[numIndices++] = inlist[0];
indices[numIndices++] = inlist[j - 1]; indices[numIndices++] = inlist[j - 1];
indices[numIndices++] = inlist[j]; 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, 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,
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; int numIndices = 3;
if (backface) if (backface)
{ {
Vertices[0] = v0; Vertices[0] = v0;
Vertices[1] = v2; Vertices[1] = v2;
Vertices[2] = v1; Vertices[2] = v1;
} }
else else
{ {
Vertices[0] = v0; Vertices[0] = v0;
Vertices[1] = v1; Vertices[1] = v1;
Vertices[2] = v2; Vertices[2] = v2;
} }
ClipTriangle(indices, numIndices); ClipTriangle(indices, numIndices);
for(int i = 0; i+3 <= numIndices; i+=3) 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;
@ -394,56 +396,56 @@ namespace Clipper
} }
} }
bool CullTest(OutputVertexData *v0, OutputVertexData *v1, OutputVertexData *v2, bool &backface) bool CullTest(OutputVertexData *v0, OutputVertexData *v1, OutputVertexData *v2, bool &backface)
{ {
int mask = CalcClipMask(v0); int mask = CalcClipMask(v0);
mask &= CalcClipMask(v1); mask &= CalcClipMask(v1);
mask &= CalcClipMask(v2); mask &= CalcClipMask(v2);
if(mask) if(mask)
{ {
INCSTAT(swstats.thisFrame.numTrianglesRejected) INCSTAT(swstats.thisFrame.numTrianglesRejected)
return false; return false;
} }
float x0 = v0->projectedPosition.x; float x0 = v0->projectedPosition.x;
float x1 = v1->projectedPosition.x; float x1 = v1->projectedPosition.x;
float x2 = v2->projectedPosition.x; float x2 = v2->projectedPosition.x;
float y1 = v1->projectedPosition.y; float y1 = v1->projectedPosition.y;
float y0 = v0->projectedPosition.y; float y0 = v0->projectedPosition.y;
float y2 = v2->projectedPosition.y; float y2 = v2->projectedPosition.y;
float w0 = v0->projectedPosition.w; float w0 = v0->projectedPosition.w;
float w1 = v1->projectedPosition.w; float w1 = v1->projectedPosition.w;
float w2 = v2->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 normalZDir = (x0*w2 - x2*w0)*y1 + (x2*y0 - x0*y2)*w1 + (y2*w0 - y0*w2)*x1;
backface = normalZDir <= 0.0f; backface = normalZDir <= 0.0f;
if ((bpmem.genMode.cullmode & 1) && !backface) // cull frontfacing if ((bpmem.genMode.cullmode & 1) && !backface) // cull frontfacing
{ {
INCSTAT(swstats.thisFrame.numTrianglesCulled) INCSTAT(swstats.thisFrame.numTrianglesCulled)
return false; return false;
} }
if ((bpmem.genMode.cullmode & 2) && backface) // cull backfacing if ((bpmem.genMode.cullmode & 2) && backface) // cull backfacing
{ {
INCSTAT(swstats.thisFrame.numTrianglesCulled) INCSTAT(swstats.thisFrame.numTrianglesCulled)
return false; return false;
} }
return true; return true;
} }
void PerspectiveDivide(OutputVertexData *vertex) void PerspectiveDivide(OutputVertexData *vertex)
{ {
Vec4 &projected = vertex->projectedPosition; Vec4 &projected = vertex->projectedPosition;
Vec3 &screen = vertex->screenPosition; Vec3 &screen = vertex->screenPosition;
float wInverse = 1.0f/projected.w; float wInverse = 1.0f/projected.w;
screen.x = projected.x * wInverse * swxfregs.viewport.wd + m_ViewOffset[0]; screen.x = projected.x * wInverse * swxfregs.viewport.wd + m_ViewOffset[0];
screen.y = projected.y * wInverse * swxfregs.viewport.ht + m_ViewOffset[1]; screen.y = projected.y * wInverse * swxfregs.viewport.ht + m_ViewOffset[1];
screen.z = projected.z * wInverse * swxfregs.viewport.zRange + swxfregs.viewport.farZ; 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); GetTextureBGRA(data, texmap, mip, width, height);
(void)SaveTGA(filename, width, height, data); (void)SaveTGA(filename, width, height, data);
delete []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 val = *dst & 0xff000000;
val |= depth & 0x00ffffff;
*dst = val;
}
break;
case PIXELFMT_RGB565_Z16:
{
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: case PIXELFMT_RGB565_Z16:
ERROR_LOG(VIDEO, "Unsupported pixel format: %i", bpmem.zcontrol.pixel_format); {
} INFO_LOG(VIDEO, "PIXELFMT_RGB565_Z16 is not supported correctly yet");
} u32 *dst = (u32*)&efb[offset];
u32 val = *dst & 0xff000000;
val |= depth & 0x00ffffff;
*dst = val;
}
break;
default:
ERROR_LOG(VIDEO, "Unsupported pixel format: %i", bpmem.zcontrol.pixel_format);
}
}
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); u32 df = (dstFactor & 0xff);
df += df >> 7; df += df >> 7;
u32 color = (srcClr[i] * sf + dstClr[i] * df) >> 8; u32 color = (srcClr[i] * sf + dstClr[i] * df) >> 8;
dstClr[i] = (color>255)?255:color; dstClr[i] = (color>255)?255:color;
dstFactor >>= 8; dstFactor >>= 8;
srcFactor >>= 8; srcFactor >>= 8;
} }
} }
void LogicBlend(u32 srcClr, u32 &dstClr, int op) void LogicBlend(u32 srcClr, u32 &dstClr, int op)
{ {
switch (op) { switch (op)
case 0: // clear {
dstClr = 0; case 0: // clear
break; dstClr = 0;
case 1: // and break;
dstClr = srcClr & dstClr; case 1: // and
break; dstClr = srcClr & dstClr;
case 2: // revand break;
dstClr = srcClr & (~dstClr); case 2: // revand
break; dstClr = srcClr & (~dstClr);
case 3: // copy break;
dstClr = srcClr; case 3: // copy
break; dstClr = srcClr;
case 4: // invand break;
dstClr = (~srcClr) & dstClr; case 4: // invand
break; dstClr = (~srcClr) & dstClr;
case 5: // noop 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,31 +22,31 @@
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);
} }

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 // switch to primitive processing
streamSize = DataReadU16(); streamSize = DataReadU16();
currentFunction = DecodePrimitiveStream; currentFunction = DecodePrimitiveStream;
minCommandSize = vertexLoader.GetVertexSize(); minCommandSize = vertexLoader.GetVertexSize();
readOpcode = false; readOpcode = false;
INCSTAT(swstats.thisFrame.numPrimatives); INCSTAT(swstats.thisFrame.numPrimatives);
DEBUG_LOG(VIDEO, "Draw begin"); DEBUG_LOG(VIDEO, "Draw begin");
} }
else else
{ {
PanicAlert("GFX: Unknown Opcode (0x%x).\n", Cmd); PanicAlert("GFX: Unknown Opcode (0x%x).\n", Cmd);
break; break;
} }
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,27 +97,27 @@ 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;
@ -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);
@ -201,13 +201,13 @@ inline void Draw(s32 x, s32 y, s32 xi, s32 yi)
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 // Half-edge constants
s32 C1 = DY12 * X1 - DX12 * Y1; s32 C1 = DY12 * X1 - DX12 * Y1;
s32 C2 = DY23 * X2 - DX23 * Y2; s32 C2 = DY23 * X2 - DX23 * Y2;
s32 C3 = DY31 * X3 - DX31 * Y3; s32 C3 = DY31 * X3 - DX31 * Y3;
// Correct for fill convention // Correct for fill convention
if(DY12 < 0 || (DY12 == 0 && DX12 > 0)) C1++; if(DY12 < 0 || (DY12 == 0 && DX12 > 0)) C1++;
if(DY23 < 0 || (DY23 == 0 && DX23 > 0)) C2++; if(DY23 < 0 || (DY23 == 0 && DX23 > 0)) C2++;
if(DY31 < 0 || (DY31 == 0 && DX31 > 0)) C3++; if(DY31 < 0 || (DY31 == 0 && DX31 > 0)) C3++;
// Loop through blocks // Loop through blocks
for(s32 y = miny; y < maxy; y += BLOCK_SIZE) for(s32 y = miny; y < maxy; y += BLOCK_SIZE)
{ {
for(s32 x = minx; x < maxx; x += BLOCK_SIZE) for(s32 x = minx; x < maxx; x += BLOCK_SIZE)
{ {
// Corners of block // Corners of block
s32 x0 = x << 4; s32 x0 = x << 4;
s32 x1 = (x + BLOCK_SIZE - 1) << 4; s32 x1 = (x + BLOCK_SIZE - 1) << 4;
s32 y0 = y << 4; s32 y0 = y << 4;
s32 y1 = (y + BLOCK_SIZE - 1) << 4; s32 y1 = (y + BLOCK_SIZE - 1) << 4;
// Evaluate half-space functions // Evaluate half-space functions
bool a00 = C1 + DX12 * y0 - DY12 * x0 > 0; bool a00 = C1 + DX12 * y0 - DY12 * x0 > 0;
bool a10 = C1 + DX12 * y0 - DY12 * x1 > 0; bool a10 = C1 + DX12 * y0 - DY12 * x1 > 0;
bool a01 = C1 + DX12 * y1 - DY12 * x0 > 0; bool a01 = C1 + DX12 * y1 - DY12 * x0 > 0;
bool a11 = C1 + DX12 * y1 - DY12 * x1 > 0; bool a11 = C1 + DX12 * y1 - DY12 * x1 > 0;
int a = (a00 << 0) | (a10 << 1) | (a01 << 2) | (a11 << 3); int a = (a00 << 0) | (a10 << 1) | (a01 << 2) | (a11 << 3);
bool b00 = C2 + DX23 * y0 - DY23 * x0 > 0; bool b00 = C2 + DX23 * y0 - DY23 * x0 > 0;
bool b10 = C2 + DX23 * y0 - DY23 * x1 > 0; bool b10 = C2 + DX23 * y0 - DY23 * x1 > 0;
bool b01 = C2 + DX23 * y1 - DY23 * x0 > 0; bool b01 = C2 + DX23 * y1 - DY23 * x0 > 0;
bool b11 = C2 + DX23 * y1 - DY23 * x1 > 0; bool b11 = C2 + DX23 * y1 - DY23 * x1 > 0;
int b = (b00 << 0) | (b10 << 1) | (b01 << 2) | (b11 << 3); int b = (b00 << 0) | (b10 << 1) | (b01 << 2) | (b11 << 3);
bool c00 = C3 + DX31 * y0 - DY31 * x0 > 0; bool c00 = C3 + DX31 * y0 - DY31 * x0 > 0;
bool c10 = C3 + DX31 * y0 - DY31 * x1 > 0; bool c10 = C3 + DX31 * y0 - DY31 * x1 > 0;
bool c01 = C3 + DX31 * y1 - DY31 * x0 > 0; bool c01 = C3 + DX31 * y1 - DY31 * x0 > 0;
bool c11 = C3 + DX31 * y1 - DY31 * x1 > 0; bool c11 = C3 + DX31 * y1 - DY31 * x1 > 0;
int c = (c00 << 0) | (c10 << 1) | (c01 << 2) | (c11 << 3); int c = (c00 << 0) | (c10 << 1) | (c01 << 2) | (c11 << 3);
// Skip block when outside an edge // Skip block when outside an edge
if(a == 0x0 || b == 0x0 || c == 0x0) continue; 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 // run the opcode decoder
do { do
RunBuffer(); {
} while (cpreg.ctrl.GPReadEnable && !AtBreakpoint() && cpreg.readptr != cpreg.writeptr); RunBuffer();
} while (cpreg.ctrl.GPReadEnable && !AtBreakpoint() && cpreg.readptr != cpreg.writeptr);
FPURoundMode::LoadSIMDState(); 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;
@ -196,76 +197,76 @@ void Write16(const u16 _Value, const u32 _Address)
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); _dbg_assert_(COMMANDPROCESSOR, writePos >= readPos);
g_pVideoData = &commandBuffer[readPos]; g_pVideoData = &commandBuffer[readPos];
u32 availableBytes = writePos - readPos; u32 availableBytes = writePos - readPos;
while (OpcodeDecoder::CommandRunnable(availableBytes)) while (OpcodeDecoder::CommandRunnable(availableBytes))
{ {
cpreg.status.CommandIdle = 0; cpreg.status.CommandIdle = 0;
OpcodeDecoder::Run(availableBytes); OpcodeDecoder::Run(availableBytes);
// 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
readPos = (u32)(g_pVideoData - &commandBuffer[0]); readPos = (u32)(g_pVideoData - &commandBuffer[0]);
_dbg_assert_(VIDEO, writePos >= readPos); _dbg_assert_(VIDEO, writePos >= readPos);
availableBytes = writePos - readPos; availableBytes = writePos - readPos;
} }
cpreg.status.CommandIdle = 1; cpreg.status.CommandIdle = 1;
bool ranDecoder = false; bool ranDecoder = false;
// move data remaing in command buffer // move data remaing in command buffer
if (readPos > 0) if (readPos > 0)
{ {
memmove(&commandBuffer[0], &commandBuffer[readPos], availableBytes); memmove(&commandBuffer[0], &commandBuffer[readPos], availableBytes);
writePos -= readPos; writePos -= readPos;
readPos = 0; readPos = 0;
ranDecoder = true; ranDecoder = true;
} }
return ranDecoder; 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,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 _COMMANDPROCESSOR_H_ #ifndef _COMMANDPROCESSOR_H_
@ -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"
@ -116,20 +116,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);
@ -206,9 +206,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);

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)

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_positionLoader;
TPipelineFunction m_normalLoader; TPipelineFunction m_normalLoader;
TPipelineFunction m_colorLoader[2]; TPipelineFunction m_colorLoader[2];
TPipelineFunction m_texCoordLoader[8]; TPipelineFunction m_texCoordLoader[8];
InputVertexData m_Vertex; InputVertexData m_Vertex;
typedef void (*AttributeLoader)(SWVertexLoader*, InputVertexData*, u8); typedef void (*AttributeLoader)(SWVertexLoader*, InputVertexData*, u8);
struct AttrLoaderCall struct AttrLoaderCall
{ {
AttributeLoader loader; AttributeLoader loader;
u8 index; u8 index;
}; };
AttrLoaderCall m_AttributeLoaders[1+8+1+1+2+8]; AttrLoaderCall m_AttributeLoaders[1+8+1+1+2+8];
int m_NumAttributeLoaders; int m_NumAttributeLoaders;
void AddAttributeLoader(AttributeLoader loader, u8 index=0); void AddAttributeLoader(AttributeLoader loader, u8 index=0);
// attribute loader functions // attribute loader functions
static void LoadPosMtx(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 unused); static void LoadPosMtx(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 unused);
static void LoadTexMtx(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 index); static void LoadTexMtx(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 index);
static void LoadPosition(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 unused); static void LoadPosition(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 unused);
static void LoadNormal(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 LoadColor(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 index);
static void LoadTexCoord(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 index); static void LoadTexCoord(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 index);
SetupUnit *m_SetupUnit; 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: case PEEK_COLOR:
break; {
} u32 color = 0;
EfbInterface::GetColor(x, y, (u8*)&color);
return value; // 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"
@ -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,9 +100,9 @@ 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
@ -114,11 +114,11 @@ void Sample(s32 s, s32 t, s32 lod, bool linear, u8 texmap, u8 *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)
@ -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 imageTPlus1 = imageT + 1;
int fractT = t & 0x7f; int fractT = t & 0x7f;
u8 sampledTex[4]; u8 sampledTex[4];
u32 texel[4]; u32 texel[4];
WrapCoord(imageS, tm0.wrap_s, imageWidth); WrapCoord(imageS, tm0.wrap_s, imageWidth);
WrapCoord(imageT, tm0.wrap_t, imageHeight); WrapCoord(imageT, tm0.wrap_t, imageHeight);
WrapCoord(imageSPlus1, tm0.wrap_s, imageWidth); WrapCoord(imageSPlus1, tm0.wrap_s, imageWidth);
WrapCoord(imageTPlus1, tm0.wrap_t, imageHeight); 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)
@ -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

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