Merge remote-tracking branch 'origin/master' into Android-trash
Conflicts: Source/Plugins/Plugin_VideoSoftware/Src/SWRenderer.cpp
This commit is contained in:
commit
37b67971e7
|
@ -535,7 +535,7 @@ bool Subtype_RamWriteAndFill(const ARAddr addr, const u32 data)
|
|||
|
||||
case DATATYPE_32BIT_FLOAT:
|
||||
case DATATYPE_32BIT: // Dword write
|
||||
LogInfo("32bit Write");
|
||||
LogInfo("32-bit Write");
|
||||
LogInfo("--------");
|
||||
Memory::Write_U32(data, new_addr);
|
||||
LogInfo("Wrote %08x to address %08x", data, new_addr);
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// Official Git repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "VideoCommon.h"
|
||||
|
@ -29,67 +29,67 @@
|
|||
|
||||
void InitBPMemory()
|
||||
{
|
||||
memset(&bpmem, 0, sizeof(bpmem));
|
||||
bpmem.bpMask = 0xFFFFFF;
|
||||
memset(&bpmem, 0, sizeof(bpmem));
|
||||
bpmem.bpMask = 0xFFFFFF;
|
||||
}
|
||||
|
||||
void SWLoadBPReg(u32 value)
|
||||
{
|
||||
//handle the mask register
|
||||
//handle the mask register
|
||||
int address = value >> 24;
|
||||
int oldval = ((u32*)&bpmem)[address];
|
||||
int newval = (oldval & ~bpmem.bpMask) | (value & bpmem.bpMask);
|
||||
|
||||
((u32*)&bpmem)[address] = newval;
|
||||
((u32*)&bpmem)[address] = newval;
|
||||
|
||||
//reset the mask register
|
||||
if (address != 0xFE)
|
||||
bpmem.bpMask = 0xFFFFFF;
|
||||
|
||||
SWBPWritten(address, newval);
|
||||
SWBPWritten(address, newval);
|
||||
}
|
||||
|
||||
void SWBPWritten(int address, int newvalue)
|
||||
{
|
||||
switch (address)
|
||||
switch (address)
|
||||
{
|
||||
case BPMEM_SCISSORTL:
|
||||
case BPMEM_SCISSORBR:
|
||||
case BPMEM_SCISSOROFFSET:
|
||||
Rasterizer::SetScissor();
|
||||
break;
|
||||
case BPMEM_SCISSORTL:
|
||||
case BPMEM_SCISSORBR:
|
||||
case BPMEM_SCISSOROFFSET:
|
||||
Rasterizer::SetScissor();
|
||||
break;
|
||||
case BPMEM_SETDRAWDONE: // This is called when the game is done drawing (eg: like in DX: Begin(); Draw(); End();)
|
||||
switch (bpmem.drawdone & 0xFF)
|
||||
{
|
||||
case 0x02:
|
||||
SWPixelEngine::SetFinish(); // may generate interrupt
|
||||
DEBUG_LOG(VIDEO, "GXSetDrawDone SetPEFinish (value: 0x%02X)", (bpmem.drawdone & 0xFFFF));
|
||||
break;
|
||||
{
|
||||
case 0x02:
|
||||
SWPixelEngine::SetFinish(); // may generate interrupt
|
||||
DEBUG_LOG(VIDEO, "GXSetDrawDone SetPEFinish (value: 0x%02X)", (bpmem.drawdone & 0xFFFF));
|
||||
break;
|
||||
|
||||
default:
|
||||
WARN_LOG(VIDEO, "GXSetDrawDone ??? (value 0x%02X)", (bpmem.drawdone & 0xFFFF));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
WARN_LOG(VIDEO, "GXSetDrawDone ??? (value 0x%02X)", (bpmem.drawdone & 0xFFFF));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case BPMEM_PE_TOKEN_ID: // Pixel Engine Token ID
|
||||
DEBUG_LOG(VIDEO, "SetPEToken 0x%04x", (bpmem.petoken & 0xFFFF));
|
||||
SWPixelEngine::SetToken(static_cast<u16>(bpmem.petokenint & 0xFFFF), false);
|
||||
break;
|
||||
case BPMEM_PE_TOKEN_INT_ID: // Pixel Engine Interrupt Token ID
|
||||
DEBUG_LOG(VIDEO, "SetPEToken + INT 0x%04x", (bpmem.petokenint & 0xFFFF));
|
||||
SWPixelEngine::SetToken(static_cast<u16>(bpmem.petokenint & 0xFFFF), true);
|
||||
break;
|
||||
case BPMEM_TRIGGER_EFB_COPY:
|
||||
EfbCopy::CopyEfb();
|
||||
break;
|
||||
case BPMEM_CLEARBBOX1:
|
||||
SWPixelEngine::pereg.boxRight = newvalue >> 10;
|
||||
SWPixelEngine::pereg.boxLeft = newvalue & 0x3ff;
|
||||
break;
|
||||
case BPMEM_CLEARBBOX2:
|
||||
SWPixelEngine::pereg.boxBottom = newvalue >> 10;
|
||||
SWPixelEngine::pereg.boxTop = newvalue & 0x3ff;
|
||||
break;
|
||||
DEBUG_LOG(VIDEO, "SetPEToken 0x%04x", (bpmem.petoken & 0xFFFF));
|
||||
SWPixelEngine::SetToken(static_cast<u16>(bpmem.petokenint & 0xFFFF), false);
|
||||
break;
|
||||
case BPMEM_PE_TOKEN_INT_ID: // Pixel Engine Interrupt Token ID
|
||||
DEBUG_LOG(VIDEO, "SetPEToken + INT 0x%04x", (bpmem.petokenint & 0xFFFF));
|
||||
SWPixelEngine::SetToken(static_cast<u16>(bpmem.petokenint & 0xFFFF), true);
|
||||
break;
|
||||
case BPMEM_TRIGGER_EFB_COPY:
|
||||
EfbCopy::CopyEfb();
|
||||
break;
|
||||
case BPMEM_CLEARBBOX1:
|
||||
SWPixelEngine::pereg.boxRight = newvalue >> 10;
|
||||
SWPixelEngine::pereg.boxLeft = newvalue & 0x3ff;
|
||||
break;
|
||||
case BPMEM_CLEARBBOX2:
|
||||
SWPixelEngine::pereg.boxBottom = newvalue >> 10;
|
||||
SWPixelEngine::pereg.boxTop = newvalue & 0x3ff;
|
||||
break;
|
||||
case BPMEM_CLEAR_PIXEL_PERF:
|
||||
// TODO: I didn't test if the value written to this register affects the amount of cleared registers
|
||||
SWPixelEngine::pereg.perfZcompInputZcomplocLo = 0;
|
||||
|
@ -105,16 +105,16 @@ void SWBPWritten(int address, int newvalue)
|
|||
SWPixelEngine::pereg.perfEfbCopyClocksLo = 0;
|
||||
SWPixelEngine::pereg.perfEfbCopyClocksHi = 0;
|
||||
break;
|
||||
case BPMEM_LOADTLUT0: // This one updates bpmem.tlutXferSrc, no need to do anything here.
|
||||
case BPMEM_LOADTLUT0: // This one updates bpmem.tlutXferSrc, no need to do anything here.
|
||||
break;
|
||||
case BPMEM_LOADTLUT1: // Load a Texture Look Up Table
|
||||
{
|
||||
u32 tlutTMemAddr = (newvalue & 0x3FF) << 9;
|
||||
u32 tlutXferCount = (newvalue & 0x1FFC00) >> 5;
|
||||
{
|
||||
u32 tlutTMemAddr = (newvalue & 0x3FF) << 9;
|
||||
u32 tlutXferCount = (newvalue & 0x1FFC00) >> 5;
|
||||
|
||||
u8 *ptr = 0;
|
||||
|
||||
// TODO - figure out a cleaner way.
|
||||
// TODO - figure out a cleaner way.
|
||||
if (Core::g_CoreStartupParameter.bWii)
|
||||
ptr = Memory::GetPointer(bpmem.tmem_config.tlut_src << 5);
|
||||
else
|
||||
|
@ -125,7 +125,7 @@ void SWBPWritten(int address, int newvalue)
|
|||
else
|
||||
PanicAlert("Invalid palette pointer %08x %08x %08x", bpmem.tmem_config.tlut_src, bpmem.tmem_config.tlut_src << 5, (bpmem.tmem_config.tlut_src & 0xFFFFF)<< 5);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
case BPMEM_PRELOAD_MODE:
|
||||
if (newvalue != 0)
|
||||
|
@ -166,36 +166,36 @@ void SWBPWritten(int address, int newvalue)
|
|||
}
|
||||
break;
|
||||
|
||||
case BPMEM_TEV_REGISTER_L: // Reg 1
|
||||
case BPMEM_TEV_REGISTER_L: // Reg 1
|
||||
case BPMEM_TEV_REGISTER_L+2: // Reg 2
|
||||
case BPMEM_TEV_REGISTER_L+4: // Reg 3
|
||||
case BPMEM_TEV_REGISTER_L+6: // Reg 4
|
||||
{
|
||||
int regNum = (address >> 1 ) & 0x3;
|
||||
ColReg& reg = bpmem.tevregs[regNum].low;
|
||||
bool konst = reg.type;
|
||||
ColReg& reg = bpmem.tevregs[regNum].low;
|
||||
bool konst = reg.type;
|
||||
|
||||
Rasterizer::SetTevReg(regNum, Tev::ALP_C, konst, reg.b); // A
|
||||
Rasterizer::SetTevReg(regNum, Tev::RED_C, konst, reg.a); // R
|
||||
Rasterizer::SetTevReg(regNum, Tev::RED_C, konst, reg.a); // R
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case BPMEM_TEV_REGISTER_H: // Reg 1
|
||||
case BPMEM_TEV_REGISTER_H: // Reg 1
|
||||
case BPMEM_TEV_REGISTER_H+2: // Reg 2
|
||||
case BPMEM_TEV_REGISTER_H+4: // Reg 3
|
||||
case BPMEM_TEV_REGISTER_H+6: // Reg 4
|
||||
{
|
||||
int regNum = (address >> 1 ) & 0x3;
|
||||
ColReg& reg = bpmem.tevregs[regNum].high;
|
||||
bool konst = reg.type;
|
||||
ColReg& reg = bpmem.tevregs[regNum].high;
|
||||
bool konst = reg.type;
|
||||
|
||||
Rasterizer::SetTevReg(regNum, Tev::GRN_C, konst, reg.b); // G
|
||||
Rasterizer::SetTevReg(regNum, Tev::BLU_C, konst, reg.a); // B
|
||||
Rasterizer::SetTevReg(regNum, Tev::GRN_C, konst, reg.b); // G
|
||||
Rasterizer::SetTevReg(regNum, Tev::BLU_C, konst, reg.a); // B
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// Official Git repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _BPMEMLOADER_H_
|
||||
|
|
|
@ -22,10 +22,10 @@
|
|||
|
||||
void SWLoadCPReg(u32 sub_cmd, u32 value)
|
||||
{
|
||||
switch (sub_cmd & 0xF0)
|
||||
switch (sub_cmd & 0xF0)
|
||||
{
|
||||
case 0x30:
|
||||
MatrixIndexA.Hex = value;
|
||||
MatrixIndexA.Hex = value;
|
||||
break;
|
||||
|
||||
case 0x40:
|
||||
|
@ -60,7 +60,7 @@ void SWLoadCPReg(u32 sub_cmd, u32 value)
|
|||
// Pointers to vertex arrays in GC RAM
|
||||
case 0xA0:
|
||||
arraybases[sub_cmd & 0xF] = value;
|
||||
cached_arraybases[sub_cmd & 0xF] = Memory::GetPointer(value);
|
||||
cached_arraybases[sub_cmd & 0xF] = Memory::GetPointer(value);
|
||||
break;
|
||||
|
||||
case 0xB0:
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// Official Git repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _CPMEMLOADER_H_
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// Official Git repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
/*
|
||||
|
@ -62,8 +62,8 @@ namespace Clipper
|
|||
|
||||
float m_ViewOffset[2];
|
||||
|
||||
OutputVertexData ClippedVertices[NUM_CLIPPED_VERTICES];
|
||||
OutputVertexData *Vertices[NUM_INDICES];
|
||||
OutputVertexData ClippedVertices[NUM_CLIPPED_VERTICES];
|
||||
OutputVertexData *Vertices[NUM_INDICES];
|
||||
|
||||
void DoState(PointerWrap &p)
|
||||
{
|
||||
|
@ -72,94 +72,94 @@ namespace Clipper
|
|||
ClippedVertices[i].DoState(p);
|
||||
}
|
||||
|
||||
void Init()
|
||||
{
|
||||
for (int i = 0; i < NUM_CLIPPED_VERTICES; ++i)
|
||||
Vertices[i+3] = &ClippedVertices[i];
|
||||
}
|
||||
void Init()
|
||||
{
|
||||
for (int i = 0; i < NUM_CLIPPED_VERTICES; ++i)
|
||||
Vertices[i+3] = &ClippedVertices[i];
|
||||
}
|
||||
|
||||
void SetViewOffset()
|
||||
{
|
||||
m_ViewOffset[0] = swxfregs.viewport.xOrig - 342;
|
||||
m_ViewOffset[1] = swxfregs.viewport.yOrig - 342;
|
||||
}
|
||||
void SetViewOffset()
|
||||
{
|
||||
m_ViewOffset[0] = swxfregs.viewport.xOrig - 342;
|
||||
m_ViewOffset[1] = swxfregs.viewport.yOrig - 342;
|
||||
}
|
||||
|
||||
|
||||
enum {
|
||||
SKIP_FLAG = -1,
|
||||
CLIP_POS_X_BIT = 0x01,
|
||||
CLIP_NEG_X_BIT = 0x02,
|
||||
CLIP_POS_Y_BIT = 0x04,
|
||||
CLIP_NEG_Y_BIT = 0x08,
|
||||
CLIP_POS_Z_BIT = 0x10,
|
||||
CLIP_NEG_Z_BIT = 0x20
|
||||
};
|
||||
|
||||
static inline int CalcClipMask(OutputVertexData *v)
|
||||
{
|
||||
int cmask = 0;
|
||||
Vec4 pos = v->projectedPosition;
|
||||
if (pos.w - pos.x < 0) cmask |= CLIP_POS_X_BIT;
|
||||
if (pos.x + pos.w < 0) cmask |= CLIP_NEG_X_BIT;
|
||||
if (pos.w - pos.y < 0) cmask |= CLIP_POS_Y_BIT;
|
||||
if (pos.y + pos.w < 0) cmask |= CLIP_NEG_Y_BIT;
|
||||
if (pos.w * pos.z > 0) cmask |= CLIP_POS_Z_BIT;
|
||||
if (pos.z + pos.w < 0) cmask |= CLIP_NEG_Z_BIT;
|
||||
return cmask;
|
||||
}
|
||||
enum {
|
||||
SKIP_FLAG = -1,
|
||||
CLIP_POS_X_BIT = 0x01,
|
||||
CLIP_NEG_X_BIT = 0x02,
|
||||
CLIP_POS_Y_BIT = 0x04,
|
||||
CLIP_NEG_Y_BIT = 0x08,
|
||||
CLIP_POS_Z_BIT = 0x10,
|
||||
CLIP_NEG_Z_BIT = 0x20
|
||||
};
|
||||
|
||||
static inline void AddInterpolatedVertex(float t, int out, int in, int& numVertices)
|
||||
{
|
||||
Vertices[numVertices]->Lerp(t, Vertices[out], Vertices[in]);
|
||||
numVertices++;
|
||||
}
|
||||
static inline int CalcClipMask(OutputVertexData *v)
|
||||
{
|
||||
int cmask = 0;
|
||||
Vec4 pos = v->projectedPosition;
|
||||
if (pos.w - pos.x < 0) cmask |= CLIP_POS_X_BIT;
|
||||
if (pos.x + pos.w < 0) cmask |= CLIP_NEG_X_BIT;
|
||||
if (pos.w - pos.y < 0) cmask |= CLIP_POS_Y_BIT;
|
||||
if (pos.y + pos.w < 0) cmask |= CLIP_NEG_Y_BIT;
|
||||
if (pos.w * pos.z > 0) cmask |= CLIP_POS_Z_BIT;
|
||||
if (pos.z + pos.w < 0) cmask |= CLIP_NEG_Z_BIT;
|
||||
return cmask;
|
||||
}
|
||||
|
||||
#define DIFFERENT_SIGNS(x,y) ((x <= 0 && y > 0) || (x > 0 && y <= 0))
|
||||
static inline void AddInterpolatedVertex(float t, int out, int in, int& numVertices)
|
||||
{
|
||||
Vertices[numVertices]->Lerp(t, Vertices[out], Vertices[in]);
|
||||
numVertices++;
|
||||
}
|
||||
|
||||
#define CLIP_DOTPROD(I, A, B, C, D) \
|
||||
(Vertices[I]->projectedPosition.x * A + Vertices[I]->projectedPosition.y * B + Vertices[I]->projectedPosition.z * C + Vertices[I]->projectedPosition.w * D)
|
||||
#define DIFFERENT_SIGNS(x,y) ((x <= 0 && y > 0) || (x > 0 && y <= 0))
|
||||
|
||||
#define POLY_CLIP( PLANE_BIT, A, B, C, D ) \
|
||||
{ \
|
||||
if (mask & PLANE_BIT) { \
|
||||
int idxPrev = inlist[0]; \
|
||||
float dpPrev = CLIP_DOTPROD(idxPrev, A, B, C, D ); \
|
||||
int outcount = 0; \
|
||||
\
|
||||
inlist[n] = inlist[0]; \
|
||||
for (int j = 1; j <= n; j++) { \
|
||||
int idx = inlist[j]; \
|
||||
float dp = CLIP_DOTPROD(idx, A, B, C, D ); \
|
||||
if (dpPrev >= 0) { \
|
||||
outlist[outcount++] = idxPrev; \
|
||||
} \
|
||||
\
|
||||
if (DIFFERENT_SIGNS(dp, dpPrev)) { \
|
||||
if (dp < 0) { \
|
||||
float t = dp / (dp - dpPrev); \
|
||||
AddInterpolatedVertex(t, idx, idxPrev, numVertices); \
|
||||
} else { \
|
||||
float t = dpPrev / (dpPrev - dp); \
|
||||
AddInterpolatedVertex(t, idxPrev, idx, numVertices); \
|
||||
} \
|
||||
outlist[outcount++] = numVertices - 1; \
|
||||
} \
|
||||
\
|
||||
idxPrev = idx; \
|
||||
dpPrev = dp; \
|
||||
} \
|
||||
\
|
||||
if (outcount < 3) \
|
||||
continue; \
|
||||
\
|
||||
{ \
|
||||
int *tmp = inlist; \
|
||||
inlist = outlist; \
|
||||
outlist = tmp; \
|
||||
n = outcount; \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
#define CLIP_DOTPROD(I, A, B, C, D) \
|
||||
(Vertices[I]->projectedPosition.x * A + Vertices[I]->projectedPosition.y * B + Vertices[I]->projectedPosition.z * C + Vertices[I]->projectedPosition.w * D)
|
||||
|
||||
#define POLY_CLIP( PLANE_BIT, A, B, C, D ) \
|
||||
{ \
|
||||
if (mask & PLANE_BIT) { \
|
||||
int idxPrev = inlist[0]; \
|
||||
float dpPrev = CLIP_DOTPROD(idxPrev, A, B, C, D ); \
|
||||
int outcount = 0; \
|
||||
\
|
||||
inlist[n] = inlist[0]; \
|
||||
for (int j = 1; j <= n; j++) { \
|
||||
int idx = inlist[j]; \
|
||||
float dp = CLIP_DOTPROD(idx, A, B, C, D ); \
|
||||
if (dpPrev >= 0) { \
|
||||
outlist[outcount++] = idxPrev; \
|
||||
} \
|
||||
\
|
||||
if (DIFFERENT_SIGNS(dp, dpPrev)) { \
|
||||
if (dp < 0) { \
|
||||
float t = dp / (dp - dpPrev); \
|
||||
AddInterpolatedVertex(t, idx, idxPrev, numVertices); \
|
||||
} else { \
|
||||
float t = dpPrev / (dpPrev - dp); \
|
||||
AddInterpolatedVertex(t, idxPrev, idx, numVertices); \
|
||||
} \
|
||||
outlist[outcount++] = numVertices - 1; \
|
||||
} \
|
||||
\
|
||||
idxPrev = idx; \
|
||||
dpPrev = dp; \
|
||||
} \
|
||||
\
|
||||
if (outcount < 3) \
|
||||
continue; \
|
||||
\
|
||||
{ \
|
||||
int *tmp = inlist; \
|
||||
inlist = outlist; \
|
||||
outlist = tmp; \
|
||||
n = outcount; \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
#define LINE_CLIP(PLANE_BIT, A, B, C, D ) \
|
||||
{ \
|
||||
|
@ -173,63 +173,63 @@ namespace Clipper
|
|||
return; \
|
||||
\
|
||||
if (neg_dp1) { \
|
||||
float t = dp1 / (dp1 - dp0); \
|
||||
float t = dp1 / (dp1 - dp0); \
|
||||
if (t > t1) t1 = t; \
|
||||
} else if (neg_dp0) { \
|
||||
float t = dp0 / (dp0 - dp1); \
|
||||
float t = dp0 / (dp0 - dp1); \
|
||||
if (t > t0) t0 = t; \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
void ClipTriangle(int *indices, int &numIndices)
|
||||
{
|
||||
int mask = 0;
|
||||
|
||||
mask |= CalcClipMask(Vertices[0]);
|
||||
mask |= CalcClipMask(Vertices[1]);
|
||||
mask |= CalcClipMask(Vertices[2]);
|
||||
void ClipTriangle(int *indices, int &numIndices)
|
||||
{
|
||||
int mask = 0;
|
||||
|
||||
if (mask != 0)
|
||||
{
|
||||
for(int i = 0; i < 3; i += 3)
|
||||
{
|
||||
int vlist[2][2*6+1];
|
||||
int *inlist = vlist[0], *outlist = vlist[1];
|
||||
int n = 3;
|
||||
int numVertices = 3;
|
||||
mask |= CalcClipMask(Vertices[0]);
|
||||
mask |= CalcClipMask(Vertices[1]);
|
||||
mask |= CalcClipMask(Vertices[2]);
|
||||
|
||||
inlist[0] = 0;
|
||||
inlist[1] = 1;
|
||||
inlist[2] = 2;
|
||||
if (mask != 0)
|
||||
{
|
||||
for(int i = 0; i < 3; i += 3)
|
||||
{
|
||||
int vlist[2][2*6+1];
|
||||
int *inlist = vlist[0], *outlist = vlist[1];
|
||||
int n = 3;
|
||||
int numVertices = 3;
|
||||
|
||||
// mark this triangle as unused in case it should be completely
|
||||
// clipped
|
||||
indices[0] = SKIP_FLAG;
|
||||
indices[1] = SKIP_FLAG;
|
||||
indices[2] = SKIP_FLAG;
|
||||
inlist[0] = 0;
|
||||
inlist[1] = 1;
|
||||
inlist[2] = 2;
|
||||
|
||||
POLY_CLIP(CLIP_POS_X_BIT, -1, 0, 0, 1);
|
||||
POLY_CLIP(CLIP_NEG_X_BIT, 1, 0, 0, 1);
|
||||
POLY_CLIP(CLIP_POS_Y_BIT, 0, -1, 0, 1);
|
||||
POLY_CLIP(CLIP_NEG_Y_BIT, 0, 1, 0, 1);
|
||||
POLY_CLIP(CLIP_POS_Z_BIT, 0, 0, 0, 1);
|
||||
POLY_CLIP(CLIP_NEG_Z_BIT, 0, 0, 1, 1);
|
||||
// mark this triangle as unused in case it should be completely
|
||||
// clipped
|
||||
indices[0] = SKIP_FLAG;
|
||||
indices[1] = SKIP_FLAG;
|
||||
indices[2] = SKIP_FLAG;
|
||||
|
||||
INCSTAT(swstats.thisFrame.numTrianglesClipped);
|
||||
POLY_CLIP(CLIP_POS_X_BIT, -1, 0, 0, 1);
|
||||
POLY_CLIP(CLIP_NEG_X_BIT, 1, 0, 0, 1);
|
||||
POLY_CLIP(CLIP_POS_Y_BIT, 0, -1, 0, 1);
|
||||
POLY_CLIP(CLIP_NEG_Y_BIT, 0, 1, 0, 1);
|
||||
POLY_CLIP(CLIP_POS_Z_BIT, 0, 0, 0, 1);
|
||||
POLY_CLIP(CLIP_NEG_Z_BIT, 0, 0, 1, 1);
|
||||
|
||||
// transform the poly in inlist into triangles
|
||||
indices[0] = inlist[0];
|
||||
indices[1] = inlist[1];
|
||||
indices[2] = inlist[2];
|
||||
for (int j = 3; j < n; ++j) {
|
||||
indices[numIndices++] = inlist[0];
|
||||
indices[numIndices++] = inlist[j - 1];
|
||||
indices[numIndices++] = inlist[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
INCSTAT(swstats.thisFrame.numTrianglesClipped);
|
||||
|
||||
// transform the poly in inlist into triangles
|
||||
indices[0] = inlist[0];
|
||||
indices[1] = inlist[1];
|
||||
indices[2] = inlist[2];
|
||||
for (int j = 3; j < n; ++j) {
|
||||
indices[numIndices++] = inlist[0];
|
||||
indices[numIndices++] = inlist[j - 1];
|
||||
indices[numIndices++] = inlist[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ClipLine(int *indices)
|
||||
{
|
||||
|
@ -267,59 +267,61 @@ namespace Clipper
|
|||
|
||||
int numVertices = 2;
|
||||
|
||||
if (clip_mask[0]) {
|
||||
if (clip_mask[0])
|
||||
{
|
||||
indices[0] = numVertices;
|
||||
AddInterpolatedVertex(t0, 0, 1, numVertices);
|
||||
}
|
||||
|
||||
if (clip_mask[1]) {
|
||||
if (clip_mask[1])
|
||||
{
|
||||
indices[1] = numVertices;
|
||||
AddInterpolatedVertex(t1, 1, 0, numVertices);
|
||||
}
|
||||
}
|
||||
|
||||
void ProcessTriangle(OutputVertexData *v0, OutputVertexData *v1, OutputVertexData *v2)
|
||||
{
|
||||
INCSTAT(swstats.thisFrame.numTrianglesIn)
|
||||
void ProcessTriangle(OutputVertexData *v0, OutputVertexData *v1, OutputVertexData *v2)
|
||||
{
|
||||
INCSTAT(swstats.thisFrame.numTrianglesIn)
|
||||
|
||||
bool backface;
|
||||
bool backface;
|
||||
|
||||
if(!CullTest(v0, v1, v2, backface))
|
||||
return;
|
||||
|
||||
int indices[NUM_INDICES] = { 0, 1, 2, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG,
|
||||
SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG,
|
||||
SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG };
|
||||
int numIndices = 3;
|
||||
if(!CullTest(v0, v1, v2, backface))
|
||||
return;
|
||||
|
||||
if (backface)
|
||||
{
|
||||
Vertices[0] = v0;
|
||||
Vertices[1] = v2;
|
||||
Vertices[2] = v1;
|
||||
}
|
||||
else
|
||||
{
|
||||
Vertices[0] = v0;
|
||||
Vertices[1] = v1;
|
||||
Vertices[2] = v2;
|
||||
}
|
||||
int indices[NUM_INDICES] = { 0, 1, 2, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG,
|
||||
SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG,
|
||||
SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG };
|
||||
int numIndices = 3;
|
||||
|
||||
ClipTriangle(indices, numIndices);
|
||||
if (backface)
|
||||
{
|
||||
Vertices[0] = v0;
|
||||
Vertices[1] = v2;
|
||||
Vertices[2] = v1;
|
||||
}
|
||||
else
|
||||
{
|
||||
Vertices[0] = v0;
|
||||
Vertices[1] = v1;
|
||||
Vertices[2] = v2;
|
||||
}
|
||||
|
||||
for(int i = 0; i+3 <= numIndices; i+=3)
|
||||
{
|
||||
ClipTriangle(indices, numIndices);
|
||||
|
||||
for(int i = 0; i+3 <= numIndices; i+=3)
|
||||
{
|
||||
_assert_(i < NUM_INDICES);
|
||||
if(indices[i] != SKIP_FLAG)
|
||||
{
|
||||
PerspectiveDivide(Vertices[indices[i]]);
|
||||
PerspectiveDivide(Vertices[indices[i+1]]);
|
||||
PerspectiveDivide(Vertices[indices[i+2]]);
|
||||
{
|
||||
PerspectiveDivide(Vertices[indices[i]]);
|
||||
PerspectiveDivide(Vertices[indices[i+1]]);
|
||||
PerspectiveDivide(Vertices[indices[i+2]]);
|
||||
|
||||
Rasterizer::DrawTriangleFrontFace(Vertices[indices[i]], Vertices[indices[i+1]], Vertices[indices[i+2]]);
|
||||
}
|
||||
}
|
||||
}
|
||||
Rasterizer::DrawTriangleFrontFace(Vertices[indices[i]], Vertices[indices[i+1]], Vertices[indices[i+2]]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CopyVertex(OutputVertexData *dst, OutputVertexData *src, float dx, float dy, unsigned int sOffset)
|
||||
{
|
||||
|
@ -343,7 +345,7 @@ namespace Clipper
|
|||
int indices[4] = { 0, 1, SKIP_FLAG, SKIP_FLAG };
|
||||
|
||||
Vertices[0] = lineV0;
|
||||
Vertices[1] = lineV1;
|
||||
Vertices[1] = lineV1;
|
||||
|
||||
// point to a valid vertex to store to when clipping
|
||||
Vertices[2] = &ClippedVertices[17];
|
||||
|
@ -356,7 +358,7 @@ namespace Clipper
|
|||
OutputVertexData *v1 = Vertices[indices[1]];
|
||||
|
||||
PerspectiveDivide(v0);
|
||||
PerspectiveDivide(v1);
|
||||
PerspectiveDivide(v1);
|
||||
|
||||
float dx = v1->screenPosition.x - v0->screenPosition.x;
|
||||
float dy = v1->screenPosition.y - v0->screenPosition.y;
|
||||
|
@ -393,57 +395,57 @@ namespace Clipper
|
|||
Rasterizer::DrawTriangleFrontFace(&triangle[0], &triangle[1], &triangle[2]);
|
||||
}
|
||||
}
|
||||
|
||||
bool CullTest(OutputVertexData *v0, OutputVertexData *v1, OutputVertexData *v2, bool &backface)
|
||||
{
|
||||
int mask = CalcClipMask(v0);
|
||||
mask &= CalcClipMask(v1);
|
||||
mask &= CalcClipMask(v2);
|
||||
|
||||
if(mask)
|
||||
{
|
||||
INCSTAT(swstats.thisFrame.numTrianglesRejected)
|
||||
return false;
|
||||
}
|
||||
bool CullTest(OutputVertexData *v0, OutputVertexData *v1, OutputVertexData *v2, bool &backface)
|
||||
{
|
||||
int mask = CalcClipMask(v0);
|
||||
mask &= CalcClipMask(v1);
|
||||
mask &= CalcClipMask(v2);
|
||||
|
||||
float x0 = v0->projectedPosition.x;
|
||||
float x1 = v1->projectedPosition.x;
|
||||
float x2 = v2->projectedPosition.x;
|
||||
float y1 = v1->projectedPosition.y;
|
||||
float y0 = v0->projectedPosition.y;
|
||||
float y2 = v2->projectedPosition.y;
|
||||
float w0 = v0->projectedPosition.w;
|
||||
float w1 = v1->projectedPosition.w;
|
||||
float w2 = v2->projectedPosition.w;
|
||||
if(mask)
|
||||
{
|
||||
INCSTAT(swstats.thisFrame.numTrianglesRejected)
|
||||
return false;
|
||||
}
|
||||
|
||||
float normalZDir = (x0*w2 - x2*w0)*y1 + (x2*y0 - x0*y2)*w1 + (y2*w0 - y0*w2)*x1;
|
||||
float x0 = v0->projectedPosition.x;
|
||||
float x1 = v1->projectedPosition.x;
|
||||
float x2 = v2->projectedPosition.x;
|
||||
float y1 = v1->projectedPosition.y;
|
||||
float y0 = v0->projectedPosition.y;
|
||||
float y2 = v2->projectedPosition.y;
|
||||
float w0 = v0->projectedPosition.w;
|
||||
float w1 = v1->projectedPosition.w;
|
||||
float w2 = v2->projectedPosition.w;
|
||||
|
||||
backface = normalZDir <= 0.0f;
|
||||
float normalZDir = (x0*w2 - x2*w0)*y1 + (x2*y0 - x0*y2)*w1 + (y2*w0 - y0*w2)*x1;
|
||||
|
||||
if ((bpmem.genMode.cullmode & 1) && !backface) // cull frontfacing
|
||||
{
|
||||
INCSTAT(swstats.thisFrame.numTrianglesCulled)
|
||||
return false;
|
||||
}
|
||||
backface = normalZDir <= 0.0f;
|
||||
|
||||
if ((bpmem.genMode.cullmode & 2) && backface) // cull backfacing
|
||||
{
|
||||
INCSTAT(swstats.thisFrame.numTrianglesCulled)
|
||||
return false;
|
||||
}
|
||||
if ((bpmem.genMode.cullmode & 1) && !backface) // cull frontfacing
|
||||
{
|
||||
INCSTAT(swstats.thisFrame.numTrianglesCulled)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
if ((bpmem.genMode.cullmode & 2) && backface) // cull backfacing
|
||||
{
|
||||
INCSTAT(swstats.thisFrame.numTrianglesCulled)
|
||||
return false;
|
||||
}
|
||||
|
||||
void PerspectiveDivide(OutputVertexData *vertex)
|
||||
{
|
||||
Vec4 &projected = vertex->projectedPosition;
|
||||
Vec3 &screen = vertex->screenPosition;
|
||||
return true;
|
||||
}
|
||||
|
||||
void PerspectiveDivide(OutputVertexData *vertex)
|
||||
{
|
||||
Vec4 &projected = vertex->projectedPosition;
|
||||
Vec3 &screen = vertex->screenPosition;
|
||||
|
||||
float wInverse = 1.0f/projected.w;
|
||||
screen.x = projected.x * wInverse * swxfregs.viewport.wd + m_ViewOffset[0];
|
||||
screen.y = projected.y * wInverse * swxfregs.viewport.ht + m_ViewOffset[1];
|
||||
screen.z = projected.z * wInverse * swxfregs.viewport.zRange + swxfregs.viewport.farZ;
|
||||
}
|
||||
|
||||
float wInverse = 1.0f/projected.w;
|
||||
screen.x = projected.x * wInverse * swxfregs.viewport.wd + m_ViewOffset[0];
|
||||
screen.y = projected.y * wInverse * swxfregs.viewport.ht + m_ViewOffset[1];
|
||||
screen.z = projected.z * wInverse * swxfregs.viewport.zRange + swxfregs.viewport.farZ;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// Official Git repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _CLIPPER_H_
|
||||
|
@ -26,17 +26,17 @@
|
|||
|
||||
namespace Clipper
|
||||
{
|
||||
void Init();
|
||||
void Init();
|
||||
|
||||
void SetViewOffset();
|
||||
void SetViewOffset();
|
||||
|
||||
void ProcessTriangle(OutputVertexData *v0, OutputVertexData *v1, OutputVertexData *v2);
|
||||
void ProcessTriangle(OutputVertexData *v0, OutputVertexData *v1, OutputVertexData *v2);
|
||||
|
||||
void ProcessLine(OutputVertexData *v0, OutputVertexData *v1);
|
||||
|
||||
bool CullTest(OutputVertexData *v0, OutputVertexData *v1, OutputVertexData *v2, bool &backface);
|
||||
bool CullTest(OutputVertexData *v0, OutputVertexData *v1, OutputVertexData *v2, bool &backface);
|
||||
|
||||
void PerspectiveDivide(OutputVertexData *vertex);
|
||||
void PerspectiveDivide(OutputVertexData *vertex);
|
||||
|
||||
void DoState(PointerWrap &p);
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// Official Git repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "Common.h"
|
||||
|
@ -46,57 +46,57 @@ int BufferBase[NumObjectBuffers];
|
|||
|
||||
void Init()
|
||||
{
|
||||
for (int i = 0; i < NumObjectBuffers; i++)
|
||||
{
|
||||
memset(ObjectBuffer[i], 0, sizeof(ObjectBuffer[i]));
|
||||
DrawnToBuffer[i] = false;
|
||||
ObjectBufferName[i] = 0;
|
||||
for (int i = 0; i < NumObjectBuffers; i++)
|
||||
{
|
||||
memset(ObjectBuffer[i], 0, sizeof(ObjectBuffer[i]));
|
||||
DrawnToBuffer[i] = false;
|
||||
ObjectBufferName[i] = 0;
|
||||
BufferBase[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SaveTexture(const char* filename, u32 texmap, s32 mip)
|
||||
{
|
||||
FourTexUnits& texUnit = bpmem.tex[(texmap >> 2) & 1];
|
||||
u8 subTexmap = texmap & 3;
|
||||
FourTexUnits& texUnit = bpmem.tex[(texmap >> 2) & 1];
|
||||
u8 subTexmap = texmap & 3;
|
||||
|
||||
TexImage0& ti0 = texUnit.texImage0[subTexmap];
|
||||
TexImage0& ti0 = texUnit.texImage0[subTexmap];
|
||||
|
||||
u32 width = ti0.width + 1;
|
||||
u32 height = ti0.height + 1;
|
||||
|
||||
u8 *data = new u8[width * height * 4];
|
||||
|
||||
GetTextureBGRA(data, texmap, mip, width, height);
|
||||
|
||||
(void)SaveTGA(filename, width, height, data);
|
||||
GetTextureBGRA(data, texmap, mip, width, height);
|
||||
|
||||
delete []data;
|
||||
(void)SaveTGA(filename, width, height, data);
|
||||
|
||||
delete []data;
|
||||
}
|
||||
|
||||
void GetTextureBGRA(u8 *dst, u32 texmap, s32 mip, u32 width, u32 height)
|
||||
{
|
||||
u8 sample[4];
|
||||
u8 sample[4];
|
||||
|
||||
for (u32 y = 0; y < height; y++)
|
||||
for (u32 y = 0; y < height; y++)
|
||||
{
|
||||
for (u32 x = 0; x < width; x++)
|
||||
for (u32 x = 0; x < width; x++)
|
||||
{
|
||||
TextureSampler::SampleMip(x << 7, y << 7, mip, false, texmap, sample);
|
||||
|
||||
TextureSampler::SampleMip(x << 7, y << 7, mip, false, texmap, sample);
|
||||
|
||||
// RGBA to BGRA
|
||||
*(dst++) = sample[2];
|
||||
*(dst++) = sample[1];
|
||||
*(dst++) = sample[0];
|
||||
*(dst++) = sample[3];
|
||||
}
|
||||
*(dst++) = sample[2];
|
||||
*(dst++) = sample[1];
|
||||
*(dst++) = sample[0];
|
||||
*(dst++) = sample[3];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
s32 GetMaxTextureLod(u32 texmap)
|
||||
{
|
||||
FourTexUnits& texUnit = bpmem.tex[(texmap >> 2) & 1];
|
||||
u8 subTexmap = texmap & 3;
|
||||
u8 subTexmap = texmap & 3;
|
||||
|
||||
u8 maxLod = texUnit.texMode1[subTexmap].max_lod;
|
||||
u8 mip = maxLod >> 4;
|
||||
|
@ -110,9 +110,9 @@ s32 GetMaxTextureLod(u32 texmap)
|
|||
|
||||
void DumpActiveTextures()
|
||||
{
|
||||
for (unsigned int stageNum = 0; stageNum < bpmem.genMode.numindstages; stageNum++)
|
||||
{
|
||||
u32 texmap = bpmem.tevindref.getTexMap(stageNum);
|
||||
for (unsigned int stageNum = 0; stageNum < bpmem.genMode.numindstages; stageNum++)
|
||||
{
|
||||
u32 texmap = bpmem.tevindref.getTexMap(stageNum);
|
||||
|
||||
s32 maxLod = GetMaxTextureLod(texmap);
|
||||
for (s32 mip = 0; mip <= maxLod; ++mip)
|
||||
|
@ -121,90 +121,96 @@ void DumpActiveTextures()
|
|||
File::GetUserPath(D_DUMPTEXTURES_IDX).c_str(),
|
||||
swstats.thisFrame.numDrawnObjects, stageNum, texmap, mip).c_str(), texmap, mip);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned int stageNum = 0; stageNum <= bpmem.genMode.numtevstages; stageNum++)
|
||||
{
|
||||
int stageNum2 = stageNum >> 1;
|
||||
int stageOdd = stageNum&1;
|
||||
TwoTevStageOrders &order = bpmem.tevorders[stageNum2];
|
||||
for (unsigned int stageNum = 0; stageNum <= bpmem.genMode.numtevstages; stageNum++)
|
||||
{
|
||||
int stageNum2 = stageNum >> 1;
|
||||
int stageOdd = stageNum&1;
|
||||
TwoTevStageOrders &order = bpmem.tevorders[stageNum2];
|
||||
|
||||
int texmap = order.getTexMap(stageOdd);
|
||||
int texmap = order.getTexMap(stageOdd);
|
||||
|
||||
s32 maxLod = GetMaxTextureLod(texmap);
|
||||
s32 maxLod = GetMaxTextureLod(texmap);
|
||||
for (s32 mip = 0; mip <= maxLod; ++mip)
|
||||
{
|
||||
SaveTexture(StringFromFormat("%star%i_stage%i_map%i_mip%i.tga",
|
||||
File::GetUserPath(D_DUMPTEXTURES_IDX).c_str(),
|
||||
swstats.thisFrame.numDrawnObjects, stageNum, texmap, mip).c_str(), texmap, mip);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DumpEfb(const char* filename)
|
||||
{
|
||||
u8 *data = new u8[EFB_WIDTH * EFB_HEIGHT * 4];
|
||||
u8 *writePtr = data;
|
||||
u8 sample[4];
|
||||
u8 *data = new u8[EFB_WIDTH * EFB_HEIGHT * 4];
|
||||
u8 *writePtr = data;
|
||||
u8 sample[4];
|
||||
|
||||
for (int y = 0; y < EFB_HEIGHT; y++)
|
||||
for (int x = 0; x < EFB_WIDTH; x++) {
|
||||
EfbInterface::GetColor(x, y, sample);
|
||||
// ABGR to BGRA
|
||||
*(writePtr++) = sample[1];
|
||||
*(writePtr++) = sample[2];
|
||||
*(writePtr++) = sample[3];
|
||||
*(writePtr++) = sample[0];
|
||||
}
|
||||
for (int y = 0; y < EFB_HEIGHT; y++)
|
||||
{
|
||||
for (int x = 0; x < EFB_WIDTH; x++)
|
||||
{
|
||||
EfbInterface::GetColor(x, y, sample);
|
||||
// ABGR to BGRA
|
||||
*(writePtr++) = sample[1];
|
||||
*(writePtr++) = sample[2];
|
||||
*(writePtr++) = sample[3];
|
||||
*(writePtr++) = sample[0];
|
||||
}
|
||||
}
|
||||
|
||||
(void)SaveTGA(filename, EFB_WIDTH, EFB_HEIGHT, data);
|
||||
(void)SaveTGA(filename, EFB_WIDTH, EFB_HEIGHT, data);
|
||||
|
||||
delete []data;
|
||||
delete []data;
|
||||
}
|
||||
|
||||
void DumpDepth(const char* filename)
|
||||
{
|
||||
u8 *data = new u8[EFB_WIDTH * EFB_HEIGHT * 4];
|
||||
u8 *writePtr = data;
|
||||
u8 *data = new u8[EFB_WIDTH * EFB_HEIGHT * 4];
|
||||
u8 *writePtr = data;
|
||||
|
||||
for (int y = 0; y < EFB_HEIGHT; y++)
|
||||
for (int x = 0; x < EFB_WIDTH; x++) {
|
||||
u32 depth = EfbInterface::GetDepth(x, y);
|
||||
// depth to bgra
|
||||
*(writePtr++) = (depth >> 16) & 0xff;
|
||||
*(writePtr++) = (depth >> 8) & 0xff;
|
||||
*(writePtr++) = depth & 0xff;
|
||||
*(writePtr++) = 255;
|
||||
}
|
||||
for (int y = 0; y < EFB_HEIGHT; y++)
|
||||
{
|
||||
for (int x = 0; x < EFB_WIDTH; x++)
|
||||
{
|
||||
u32 depth = EfbInterface::GetDepth(x, y);
|
||||
// depth to bgra
|
||||
*(writePtr++) = (depth >> 16) & 0xff;
|
||||
*(writePtr++) = (depth >> 8) & 0xff;
|
||||
*(writePtr++) = depth & 0xff;
|
||||
*(writePtr++) = 255;
|
||||
}
|
||||
}
|
||||
|
||||
(void)SaveTGA(filename, EFB_WIDTH, EFB_HEIGHT, data);
|
||||
(void)SaveTGA(filename, EFB_WIDTH, EFB_HEIGHT, data);
|
||||
|
||||
delete []data;
|
||||
delete []data;
|
||||
}
|
||||
|
||||
void DrawObjectBuffer(s16 x, s16 y, u8 *color, int bufferBase, int subBuffer, const char *name)
|
||||
{
|
||||
int buffer = bufferBase + subBuffer;
|
||||
int buffer = bufferBase + subBuffer;
|
||||
|
||||
u32 offset = (x + y * EFB_WIDTH) * 4;
|
||||
u8 *dst = (u8*)&ObjectBuffer[buffer][offset];
|
||||
*(dst++) = color[2];
|
||||
*(dst++) = color[1];
|
||||
*(dst++) = color[0];
|
||||
*(dst++) = color[3];
|
||||
u8 *dst = (u8*)&ObjectBuffer[buffer][offset];
|
||||
*(dst++) = color[2];
|
||||
*(dst++) = color[1];
|
||||
*(dst++) = color[0];
|
||||
*(dst++) = color[3];
|
||||
|
||||
DrawnToBuffer[buffer] = true;
|
||||
ObjectBufferName[buffer] = name;
|
||||
DrawnToBuffer[buffer] = true;
|
||||
ObjectBufferName[buffer] = name;
|
||||
BufferBase[buffer] = bufferBase;
|
||||
}
|
||||
|
||||
void DrawTempBuffer(u8 *color, int buffer)
|
||||
{
|
||||
u8 *dst = (u8*)&TempBuffer[buffer];
|
||||
*(dst++) = color[2];
|
||||
*(dst++) = color[1];
|
||||
*(dst++) = color[0];
|
||||
*(dst++) = color[3];
|
||||
*(dst++) = color[2];
|
||||
*(dst++) = color[1];
|
||||
*(dst++) = color[0];
|
||||
*(dst++) = color[3];
|
||||
}
|
||||
|
||||
void CopyTempBuffer(s16 x, s16 y, int bufferBase, int subBuffer, const char *name)
|
||||
|
@ -215,69 +221,69 @@ void CopyTempBuffer(s16 x, s16 y, int bufferBase, int subBuffer, const char *nam
|
|||
ObjectBuffer[buffer][offset] = TempBuffer[buffer];
|
||||
|
||||
DrawnToBuffer[buffer] = true;
|
||||
ObjectBufferName[buffer] = name;
|
||||
ObjectBufferName[buffer] = name;
|
||||
BufferBase[buffer] = bufferBase;
|
||||
}
|
||||
|
||||
void OnObjectBegin()
|
||||
{
|
||||
if (!g_bSkipCurrentFrame)
|
||||
{
|
||||
if (g_SWVideoConfig.bDumpTextures && swstats.thisFrame.numDrawnObjects >= g_SWVideoConfig.drawStart && swstats.thisFrame.numDrawnObjects < g_SWVideoConfig.drawEnd)
|
||||
DumpActiveTextures();
|
||||
if (!g_bSkipCurrentFrame)
|
||||
{
|
||||
if (g_SWVideoConfig.bDumpTextures && swstats.thisFrame.numDrawnObjects >= g_SWVideoConfig.drawStart && swstats.thisFrame.numDrawnObjects < g_SWVideoConfig.drawEnd)
|
||||
DumpActiveTextures();
|
||||
|
||||
if (g_SWVideoConfig.bHwRasterizer)
|
||||
if (g_SWVideoConfig.bHwRasterizer)
|
||||
{
|
||||
HwRasterizer::BeginTriangles();
|
||||
HwRasterizer::BeginTriangles();
|
||||
drawingHwTriangles = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OnObjectEnd()
|
||||
{
|
||||
if (!g_bSkipCurrentFrame)
|
||||
{
|
||||
if (g_SWVideoConfig.bDumpObjects && swstats.thisFrame.numDrawnObjects >= g_SWVideoConfig.drawStart && swstats.thisFrame.numDrawnObjects < g_SWVideoConfig.drawEnd)
|
||||
if (!g_bSkipCurrentFrame)
|
||||
{
|
||||
if (g_SWVideoConfig.bDumpObjects && swstats.thisFrame.numDrawnObjects >= g_SWVideoConfig.drawStart && swstats.thisFrame.numDrawnObjects < g_SWVideoConfig.drawEnd)
|
||||
DumpEfb(StringFromFormat("%sobject%i.tga",
|
||||
File::GetUserPath(D_DUMPFRAMES_IDX).c_str(),
|
||||
swstats.thisFrame.numDrawnObjects).c_str());
|
||||
|
||||
if (g_SWVideoConfig.bHwRasterizer || drawingHwTriangles)
|
||||
if (g_SWVideoConfig.bHwRasterizer || drawingHwTriangles)
|
||||
{
|
||||
HwRasterizer::EndTriangles();
|
||||
HwRasterizer::EndTriangles();
|
||||
drawingHwTriangles = false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < NumObjectBuffers; i++)
|
||||
{
|
||||
if (DrawnToBuffer[i])
|
||||
{
|
||||
DrawnToBuffer[i] = false;
|
||||
for (int i = 0; i < NumObjectBuffers; i++)
|
||||
{
|
||||
if (DrawnToBuffer[i])
|
||||
{
|
||||
DrawnToBuffer[i] = false;
|
||||
(void)SaveTGA(StringFromFormat("%sobject%i_%s(%i).tga",
|
||||
File::GetUserPath(D_DUMPFRAMES_IDX).c_str(),
|
||||
swstats.thisFrame.numDrawnObjects, ObjectBufferName[i], i - BufferBase[i]).c_str(),
|
||||
EFB_WIDTH, EFB_HEIGHT, ObjectBuffer[i]);
|
||||
memset(ObjectBuffer[i], 0, sizeof(ObjectBuffer[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
swstats.thisFrame.numDrawnObjects++;
|
||||
}
|
||||
swstats.thisFrame.numDrawnObjects++;
|
||||
}
|
||||
}
|
||||
|
||||
void OnFrameEnd()
|
||||
{
|
||||
if (!g_bSkipCurrentFrame)
|
||||
{
|
||||
if (g_SWVideoConfig.bDumpFrames)
|
||||
{
|
||||
if (!g_bSkipCurrentFrame)
|
||||
{
|
||||
if (g_SWVideoConfig.bDumpFrames)
|
||||
{
|
||||
DumpEfb(StringFromFormat("%sframe%i_color.tga",
|
||||
File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), swstats.frameCount).c_str());
|
||||
DumpDepth(StringFromFormat("%sframe%i_depth.tga",
|
||||
File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), swstats.frameCount).c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// Official Git repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _DEBUGUTIL_H
|
||||
|
@ -20,18 +20,18 @@
|
|||
|
||||
namespace DebugUtil
|
||||
{
|
||||
void Init();
|
||||
void Init();
|
||||
|
||||
void GetTextureBGRA(u8 *dst, u32 texmap, s32 mip, u32 width, u32 height);
|
||||
void GetTextureBGRA(u8 *dst, u32 texmap, s32 mip, u32 width, u32 height);
|
||||
|
||||
void DumpActiveTextures();
|
||||
void DumpActiveTextures();
|
||||
|
||||
void OnObjectBegin();
|
||||
void OnObjectEnd();
|
||||
void OnObjectBegin();
|
||||
void OnObjectEnd();
|
||||
|
||||
void OnFrameEnd();
|
||||
void OnFrameEnd();
|
||||
|
||||
void DrawObjectBuffer(s16 x, s16 y, u8 *color, int bufferBase, int subBuffer, const char *name);
|
||||
void DrawObjectBuffer(s16 x, s16 y, u8 *color, int bufferBase, int subBuffer, const char *name);
|
||||
|
||||
void DrawTempBuffer(u8 *color, int buffer);
|
||||
void CopyTempBuffer(s16 x, s16 y, int bufferBase, int subBuffer, const char *name);
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// Official Git repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "BPMemLoader.h"
|
||||
|
@ -30,84 +30,83 @@
|
|||
|
||||
namespace EfbCopy
|
||||
{
|
||||
void CopyToXfb()
|
||||
{
|
||||
GLInterface->Update(); // just updates the render window position and the backbuffer size
|
||||
void CopyToXfb()
|
||||
{
|
||||
GLInterface->Update(); // just updates the render window position and the backbuffer size
|
||||
|
||||
if (!g_SWVideoConfig.bHwRasterizer)
|
||||
{
|
||||
// copy to open gl for rendering
|
||||
EfbInterface::UpdateColorTexture();
|
||||
SWRenderer::DrawTexture(EfbInterface::efbColorTexture, EFB_WIDTH, EFB_HEIGHT);
|
||||
}
|
||||
{
|
||||
// copy to open gl for rendering
|
||||
EfbInterface::UpdateColorTexture();
|
||||
SWRenderer::DrawTexture(EfbInterface::efbColorTexture, EFB_WIDTH, EFB_HEIGHT);
|
||||
}
|
||||
|
||||
SWRenderer::SwapBuffer();
|
||||
SWRenderer::SwapBuffer();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void CopyToRam()
|
||||
{
|
||||
if (!g_SWVideoConfig.bHwRasterizer)
|
||||
void CopyToRam()
|
||||
{
|
||||
if (!g_SWVideoConfig.bHwRasterizer)
|
||||
{
|
||||
u8 *dest_ptr = Memory::GetPointer(bpmem.copyTexDest << 5);
|
||||
|
||||
TextureEncoder::Encode(dest_ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ClearEfb()
|
||||
{
|
||||
u32 clearColor = (bpmem.clearcolorAR & 0xff) << 24 | bpmem.clearcolorGB << 8 | (bpmem.clearcolorAR & 0xff00) >> 8;
|
||||
void ClearEfb()
|
||||
{
|
||||
u32 clearColor = (bpmem.clearcolorAR & 0xff) << 24 | bpmem.clearcolorGB << 8 | (bpmem.clearcolorAR & 0xff00) >> 8;
|
||||
|
||||
int left = bpmem.copyTexSrcXY.x;
|
||||
int top = bpmem.copyTexSrcXY.y;
|
||||
int right = left + bpmem.copyTexSrcWH.x;
|
||||
int bottom = top + bpmem.copyTexSrcWH.y;
|
||||
int left = bpmem.copyTexSrcXY.x;
|
||||
int top = bpmem.copyTexSrcXY.y;
|
||||
int right = left + bpmem.copyTexSrcWH.x;
|
||||
int bottom = top + bpmem.copyTexSrcWH.y;
|
||||
|
||||
for (u16 y = top; y <= bottom; y++)
|
||||
{
|
||||
for (u16 x = left; x <= right; x++)
|
||||
{
|
||||
EfbInterface::SetColor(x, y, (u8*)(&clearColor));
|
||||
EfbInterface::SetDepth(x, y, bpmem.clearZValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (u16 y = top; y <= bottom; y++)
|
||||
{
|
||||
for (u16 x = left; x <= right; x++)
|
||||
{
|
||||
EfbInterface::SetColor(x, y, (u8*)(&clearColor));
|
||||
EfbInterface::SetDepth(x, y, bpmem.clearZValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CopyEfb()
|
||||
{
|
||||
if (bpmem.triggerEFBCopy.copy_to_xfb)
|
||||
DebugUtil::OnFrameEnd();
|
||||
void CopyEfb()
|
||||
{
|
||||
if (bpmem.triggerEFBCopy.copy_to_xfb)
|
||||
DebugUtil::OnFrameEnd();
|
||||
|
||||
if (!g_bSkipCurrentFrame)
|
||||
{
|
||||
if (bpmem.triggerEFBCopy.copy_to_xfb)
|
||||
{
|
||||
CopyToXfb();
|
||||
Core::Callback_VideoCopiedToXFB(true);
|
||||
if (!g_bSkipCurrentFrame)
|
||||
{
|
||||
if (bpmem.triggerEFBCopy.copy_to_xfb)
|
||||
{
|
||||
CopyToXfb();
|
||||
Core::Callback_VideoCopiedToXFB(true);
|
||||
|
||||
swstats.frameCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
CopyToRam();
|
||||
}
|
||||
swstats.frameCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
CopyToRam();
|
||||
}
|
||||
|
||||
if (bpmem.triggerEFBCopy.clear)
|
||||
{
|
||||
if (g_SWVideoConfig.bHwRasterizer)
|
||||
HwRasterizer::Clear();
|
||||
else
|
||||
ClearEfb();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (bpmem.triggerEFBCopy.copy_to_xfb)
|
||||
{
|
||||
// no frame rendered but tell that a frame has finished for frame skip counter
|
||||
Core::Callback_VideoCopiedToXFB(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (bpmem.triggerEFBCopy.clear)
|
||||
{
|
||||
if (g_SWVideoConfig.bHwRasterizer)
|
||||
HwRasterizer::Clear();
|
||||
else
|
||||
ClearEfb();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (bpmem.triggerEFBCopy.copy_to_xfb)
|
||||
{
|
||||
// no frame rendered but tell that a frame has finished for frame skip counter
|
||||
Core::Callback_VideoCopiedToXFB(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// Official Git repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _EFB_COPY_H_
|
||||
|
@ -23,9 +23,9 @@
|
|||
|
||||
namespace EfbCopy
|
||||
{
|
||||
// Copy the EFB to RAM as a texture format or XFB
|
||||
// Clear the EFB if needed
|
||||
void CopyEfb();
|
||||
// Copy the EFB to RAM as a texture format or XFB
|
||||
// Clear the EFB if needed
|
||||
void CopyEfb();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// Official Git repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "Common.h"
|
||||
|
@ -29,17 +29,17 @@ u8 efb[EFB_WIDTH*EFB_HEIGHT*6];
|
|||
namespace EfbInterface
|
||||
{
|
||||
|
||||
u8 efbColorTexture[EFB_WIDTH*EFB_HEIGHT*4];
|
||||
u8 efbColorTexture[EFB_WIDTH*EFB_HEIGHT*4];
|
||||
|
||||
inline u32 GetColorOffset(u16 x, u16 y)
|
||||
{
|
||||
return (x + y * EFB_WIDTH) * 3;
|
||||
}
|
||||
inline u32 GetColorOffset(u16 x, u16 y)
|
||||
{
|
||||
return (x + y * EFB_WIDTH) * 3;
|
||||
}
|
||||
|
||||
inline u32 GetDepthOffset(u16 x, u16 y)
|
||||
{
|
||||
return (x + y * EFB_WIDTH) * 3 + DEPTH_BUFFER_START;
|
||||
}
|
||||
inline u32 GetDepthOffset(u16 x, u16 y)
|
||||
{
|
||||
return (x + y * EFB_WIDTH) * 3 + DEPTH_BUFFER_START;
|
||||
}
|
||||
|
||||
void DoState(PointerWrap &p)
|
||||
{
|
||||
|
@ -47,45 +47,45 @@ namespace EfbInterface
|
|||
p.DoArray(efbColorTexture, EFB_WIDTH*EFB_HEIGHT*4);
|
||||
}
|
||||
|
||||
void SetPixelAlphaOnly(u32 offset, u8 a)
|
||||
{
|
||||
switch (bpmem.zcontrol.pixel_format)
|
||||
{
|
||||
case PIXELFMT_RGB8_Z24:
|
||||
case PIXELFMT_Z24:
|
||||
case PIXELFMT_RGB565_Z16:
|
||||
// do nothing
|
||||
break;
|
||||
case PIXELFMT_RGBA6_Z24:
|
||||
{
|
||||
void SetPixelAlphaOnly(u32 offset, u8 a)
|
||||
{
|
||||
switch (bpmem.zcontrol.pixel_format)
|
||||
{
|
||||
case PIXELFMT_RGB8_Z24:
|
||||
case PIXELFMT_Z24:
|
||||
case PIXELFMT_RGB565_Z16:
|
||||
// do nothing
|
||||
break;
|
||||
case PIXELFMT_RGBA6_Z24:
|
||||
{
|
||||
u32 a32 = a;
|
||||
u32 *dst = (u32*)&efb[offset];
|
||||
u32 val = *dst & 0xffffffc0;
|
||||
val |= (a32 >> 2) & 0x0000003f;
|
||||
*dst = val;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ERROR_LOG(VIDEO, "Unsupported pixel format: %i", bpmem.zcontrol.pixel_format);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ERROR_LOG(VIDEO, "Unsupported pixel format: %i", bpmem.zcontrol.pixel_format);
|
||||
}
|
||||
}
|
||||
|
||||
void SetPixelColorOnly(u32 offset, u8 *rgb)
|
||||
{
|
||||
switch (bpmem.zcontrol.pixel_format)
|
||||
{
|
||||
case PIXELFMT_RGB8_Z24:
|
||||
case PIXELFMT_Z24:
|
||||
{
|
||||
void SetPixelColorOnly(u32 offset, u8 *rgb)
|
||||
{
|
||||
switch (bpmem.zcontrol.pixel_format)
|
||||
{
|
||||
case PIXELFMT_RGB8_Z24:
|
||||
case PIXELFMT_Z24:
|
||||
{
|
||||
u32 src = *(u32*)rgb;
|
||||
u32 *dst = (u32*)&efb[offset];
|
||||
u32 val = *dst & 0xff000000;
|
||||
val |= src >> 8;
|
||||
*dst = val;
|
||||
}
|
||||
break;
|
||||
case PIXELFMT_RGBA6_Z24:
|
||||
{
|
||||
}
|
||||
break;
|
||||
case PIXELFMT_RGBA6_Z24:
|
||||
{
|
||||
u32 src = *(u32*)rgb;
|
||||
u32 *dst = (u32*)&efb[offset];
|
||||
u32 val = *dst & 0xff00003f;
|
||||
|
@ -93,39 +93,39 @@ namespace EfbInterface
|
|||
val |= (src >> 6) & 0x0003f000; // green
|
||||
val |= (src >> 8) & 0x00fc0000; // red
|
||||
*dst = val;
|
||||
}
|
||||
break;
|
||||
case PIXELFMT_RGB565_Z16:
|
||||
{
|
||||
INFO_LOG(VIDEO, "PIXELFMT_RGB565_Z16 is not supported correctly yet");
|
||||
u32 src = *(u32*)rgb;
|
||||
}
|
||||
break;
|
||||
case PIXELFMT_RGB565_Z16:
|
||||
{
|
||||
INFO_LOG(VIDEO, "PIXELFMT_RGB565_Z16 is not supported correctly yet");
|
||||
u32 src = *(u32*)rgb;
|
||||
u32 *dst = (u32*)&efb[offset];
|
||||
u32 val = *dst & 0xff000000;
|
||||
val |= src >> 8;
|
||||
*dst = val;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ERROR_LOG(VIDEO, "Unsupported pixel format: %i", bpmem.zcontrol.pixel_format);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ERROR_LOG(VIDEO, "Unsupported pixel format: %i", bpmem.zcontrol.pixel_format);
|
||||
}
|
||||
}
|
||||
|
||||
void SetPixelAlphaColor(u32 offset, u8 *color)
|
||||
{
|
||||
switch (bpmem.zcontrol.pixel_format)
|
||||
{
|
||||
case PIXELFMT_RGB8_Z24:
|
||||
case PIXELFMT_Z24:
|
||||
{
|
||||
u32 src = *(u32*)color;
|
||||
void SetPixelAlphaColor(u32 offset, u8 *color)
|
||||
{
|
||||
switch (bpmem.zcontrol.pixel_format)
|
||||
{
|
||||
case PIXELFMT_RGB8_Z24:
|
||||
case PIXELFMT_Z24:
|
||||
{
|
||||
u32 src = *(u32*)color;
|
||||
u32 *dst = (u32*)&efb[offset];
|
||||
u32 val = *dst & 0xff000000;
|
||||
val |= src >> 8;
|
||||
*dst = val;
|
||||
}
|
||||
break;
|
||||
case PIXELFMT_RGBA6_Z24:
|
||||
{
|
||||
}
|
||||
break;
|
||||
case PIXELFMT_RGBA6_Z24:
|
||||
{
|
||||
u32 src = *(u32*)color;
|
||||
u32 *dst = (u32*)&efb[offset];
|
||||
u32 val = *dst & 0xff000000;
|
||||
|
@ -134,332 +134,341 @@ namespace EfbInterface
|
|||
val |= (src >> 6) & 0x0003f000; // green
|
||||
val |= (src >> 8) & 0x00fc0000; // red
|
||||
*dst = val;
|
||||
}
|
||||
break;
|
||||
case PIXELFMT_RGB565_Z16:
|
||||
{
|
||||
INFO_LOG(VIDEO, "PIXELFMT_RGB565_Z16 is not supported correctly yet");
|
||||
}
|
||||
break;
|
||||
case PIXELFMT_RGB565_Z16:
|
||||
{
|
||||
INFO_LOG(VIDEO, "PIXELFMT_RGB565_Z16 is not supported correctly yet");
|
||||
u32 src = *(u32*)color;
|
||||
u32 *dst = (u32*)&efb[offset];
|
||||
u32 val = *dst & 0xff000000;
|
||||
val |= src >> 8;
|
||||
*dst = val;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ERROR_LOG(VIDEO, "Unsupported pixel format: %i", bpmem.zcontrol.pixel_format);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ERROR_LOG(VIDEO, "Unsupported pixel format: %i", bpmem.zcontrol.pixel_format);
|
||||
}
|
||||
}
|
||||
|
||||
void GetPixelColor(u32 offset, u8 *color)
|
||||
{
|
||||
switch (bpmem.zcontrol.pixel_format)
|
||||
{
|
||||
case PIXELFMT_RGB8_Z24:
|
||||
case PIXELFMT_Z24:
|
||||
{
|
||||
u32 src = *(u32*)&efb[offset];
|
||||
void GetPixelColor(u32 offset, u8 *color)
|
||||
{
|
||||
switch (bpmem.zcontrol.pixel_format)
|
||||
{
|
||||
case PIXELFMT_RGB8_Z24:
|
||||
case PIXELFMT_Z24:
|
||||
{
|
||||
u32 src = *(u32*)&efb[offset];
|
||||
u32 *dst = (u32*)color;
|
||||
u32 val = 0xff | ((src & 0x00ffffff) << 8);
|
||||
*dst = val;
|
||||
}
|
||||
break;
|
||||
case PIXELFMT_RGBA6_Z24:
|
||||
{
|
||||
}
|
||||
break;
|
||||
case PIXELFMT_RGBA6_Z24:
|
||||
{
|
||||
u32 src = *(u32*)&efb[offset];
|
||||
color[ALP_C] = Convert6To8(src & 0x3f);
|
||||
color[BLU_C] = Convert6To8((src >> 6) & 0x3f);
|
||||
color[GRN_C] = Convert6To8((src >> 12) & 0x3f);
|
||||
color[RED_C] = Convert6To8((src >> 18) & 0x3f);
|
||||
}
|
||||
break;
|
||||
case PIXELFMT_RGB565_Z16:
|
||||
{
|
||||
INFO_LOG(VIDEO, "PIXELFMT_RGB565_Z16 is not supported correctly yet");
|
||||
}
|
||||
break;
|
||||
case PIXELFMT_RGB565_Z16:
|
||||
{
|
||||
INFO_LOG(VIDEO, "PIXELFMT_RGB565_Z16 is not supported correctly yet");
|
||||
u32 src = *(u32*)&efb[offset];
|
||||
u32 *dst = (u32*)color;
|
||||
u32 val = 0xff | ((src & 0x00ffffff) << 8);
|
||||
*dst = val;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ERROR_LOG(VIDEO, "Unsupported pixel format: %i", bpmem.zcontrol.pixel_format);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ERROR_LOG(VIDEO, "Unsupported pixel format: %i", bpmem.zcontrol.pixel_format);
|
||||
}
|
||||
}
|
||||
|
||||
void SetPixelDepth(u32 offset, u32 depth)
|
||||
{
|
||||
switch (bpmem.zcontrol.pixel_format)
|
||||
{
|
||||
case PIXELFMT_RGB8_Z24:
|
||||
case PIXELFMT_RGBA6_Z24:
|
||||
case PIXELFMT_Z24:
|
||||
{
|
||||
u32 *dst = (u32*)&efb[offset];
|
||||
void SetPixelDepth(u32 offset, u32 depth)
|
||||
{
|
||||
switch (bpmem.zcontrol.pixel_format)
|
||||
{
|
||||
case PIXELFMT_RGB8_Z24:
|
||||
case PIXELFMT_RGBA6_Z24:
|
||||
case PIXELFMT_Z24:
|
||||
{
|
||||
u32 *dst = (u32*)&efb[offset];
|
||||
u32 val = *dst & 0xff000000;
|
||||
val |= depth & 0x00ffffff;
|
||||
*dst = val;
|
||||
}
|
||||
break;
|
||||
case PIXELFMT_RGB565_Z16:
|
||||
{
|
||||
INFO_LOG(VIDEO, "PIXELFMT_RGB565_Z16 is not supported correctly yet");
|
||||
}
|
||||
break;
|
||||
case PIXELFMT_RGB565_Z16:
|
||||
{
|
||||
INFO_LOG(VIDEO, "PIXELFMT_RGB565_Z16 is not supported correctly yet");
|
||||
u32 *dst = (u32*)&efb[offset];
|
||||
u32 val = *dst & 0xff000000;
|
||||
val |= depth & 0x00ffffff;
|
||||
*dst = val;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ERROR_LOG(VIDEO, "Unsupported pixel format: %i", bpmem.zcontrol.pixel_format);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ERROR_LOG(VIDEO, "Unsupported pixel format: %i", bpmem.zcontrol.pixel_format);
|
||||
}
|
||||
}
|
||||
|
||||
u32 GetPixelDepth(u32 offset)
|
||||
{
|
||||
u32 depth = 0;
|
||||
u32 GetPixelDepth(u32 offset)
|
||||
{
|
||||
u32 depth = 0;
|
||||
|
||||
switch (bpmem.zcontrol.pixel_format)
|
||||
{
|
||||
case PIXELFMT_RGB8_Z24:
|
||||
case PIXELFMT_RGBA6_Z24:
|
||||
case PIXELFMT_Z24:
|
||||
{
|
||||
switch (bpmem.zcontrol.pixel_format)
|
||||
{
|
||||
case PIXELFMT_RGB8_Z24:
|
||||
case PIXELFMT_RGBA6_Z24:
|
||||
case PIXELFMT_Z24:
|
||||
{
|
||||
depth = (*(u32*)&efb[offset]) & 0x00ffffff;
|
||||
}
|
||||
break;
|
||||
case PIXELFMT_RGB565_Z16:
|
||||
{
|
||||
INFO_LOG(VIDEO, "PIXELFMT_RGB565_Z16 is not supported correctly yet");
|
||||
}
|
||||
break;
|
||||
case PIXELFMT_RGB565_Z16:
|
||||
{
|
||||
INFO_LOG(VIDEO, "PIXELFMT_RGB565_Z16 is not supported correctly yet");
|
||||
depth = (*(u32*)&efb[offset]) & 0x00ffffff;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ERROR_LOG(VIDEO, "Unsupported pixel format: %i", bpmem.zcontrol.pixel_format);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ERROR_LOG(VIDEO, "Unsupported pixel format: %i", bpmem.zcontrol.pixel_format);
|
||||
}
|
||||
|
||||
return depth;
|
||||
}
|
||||
return depth;
|
||||
}
|
||||
|
||||
u32 GetSourceFactor(u8 *srcClr, u8 *dstClr, int mode)
|
||||
{
|
||||
switch (mode) {
|
||||
case 0: // zero
|
||||
return 0;
|
||||
case 1: // one
|
||||
return 0xffffffff;
|
||||
case 2: // dstclr
|
||||
return *(u32*)dstClr;
|
||||
case 3: // invdstclr
|
||||
return 0xffffffff - *(u32*)dstClr;
|
||||
case 4: // srcalpha
|
||||
{
|
||||
u8 alpha = srcClr[ALP_C];
|
||||
u32 factor = alpha << 24 | alpha << 16 | alpha << 8 | alpha;
|
||||
return factor;
|
||||
}
|
||||
case 5: // invsrcalpha
|
||||
{
|
||||
u8 alpha = 0xff - srcClr[ALP_C];
|
||||
u32 factor = alpha << 24 | alpha << 16 | alpha << 8 | alpha;
|
||||
return factor;
|
||||
}
|
||||
case 6: // dstalpha
|
||||
{
|
||||
u8 alpha = dstClr[ALP_C];
|
||||
u32 factor = alpha << 24 | alpha << 16 | alpha << 8 | alpha;
|
||||
return factor;
|
||||
}
|
||||
case 7: // invdstalpha
|
||||
{
|
||||
u8 alpha = 0xff - dstClr[ALP_C];
|
||||
u32 factor = alpha << 24 | alpha << 16 | alpha << 8 | alpha;
|
||||
return factor;
|
||||
}
|
||||
}
|
||||
u32 GetSourceFactor(u8 *srcClr, u8 *dstClr, int mode)
|
||||
{
|
||||
switch (mode) {
|
||||
case 0: // zero
|
||||
return 0;
|
||||
case 1: // one
|
||||
return 0xffffffff;
|
||||
case 2: // dstclr
|
||||
return *(u32*)dstClr;
|
||||
case 3: // invdstclr
|
||||
return 0xffffffff - *(u32*)dstClr;
|
||||
case 4: // srcalpha
|
||||
{
|
||||
u8 alpha = srcClr[ALP_C];
|
||||
u32 factor = alpha << 24 | alpha << 16 | alpha << 8 | alpha;
|
||||
return factor;
|
||||
}
|
||||
case 5: // invsrcalpha
|
||||
{
|
||||
u8 alpha = 0xff - srcClr[ALP_C];
|
||||
u32 factor = alpha << 24 | alpha << 16 | alpha << 8 | alpha;
|
||||
return factor;
|
||||
}
|
||||
case 6: // dstalpha
|
||||
{
|
||||
u8 alpha = dstClr[ALP_C];
|
||||
u32 factor = alpha << 24 | alpha << 16 | alpha << 8 | alpha;
|
||||
return factor;
|
||||
}
|
||||
case 7: // invdstalpha
|
||||
{
|
||||
u8 alpha = 0xff - dstClr[ALP_C];
|
||||
u32 factor = alpha << 24 | alpha << 16 | alpha << 8 | alpha;
|
||||
return factor;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 GetDestinationFactor(u8 *srcClr, u8 *dstClr, int mode)
|
||||
{
|
||||
switch (mode) {
|
||||
case 0: // zero
|
||||
return 0;
|
||||
case 1: // one
|
||||
return 0xffffffff;
|
||||
case 2: // srcclr
|
||||
return *(u32*)srcClr;
|
||||
case 3: // invsrcclr
|
||||
return 0xffffffff - *(u32*)srcClr;
|
||||
case 4: // srcalpha
|
||||
{
|
||||
u8 alpha = srcClr[ALP_C];
|
||||
u32 factor = alpha << 24 | alpha << 16 | alpha << 8 | alpha;
|
||||
return factor;
|
||||
}
|
||||
case 5: // invsrcalpha
|
||||
{
|
||||
u8 alpha = 0xff - srcClr[ALP_C];
|
||||
u32 factor = alpha << 24 | alpha << 16 | alpha << 8 | alpha;
|
||||
return factor;
|
||||
}
|
||||
case 6: // dstalpha
|
||||
{
|
||||
u8 alpha = dstClr[ALP_C] & 0xff;
|
||||
u32 factor = alpha << 24 | alpha << 16 | alpha << 8 | alpha;
|
||||
return factor;
|
||||
}
|
||||
case 7: // invdstalpha
|
||||
{
|
||||
u8 alpha = 0xff - dstClr[ALP_C];
|
||||
u32 factor = alpha << 24 | alpha << 16 | alpha << 8 | alpha;
|
||||
return factor;
|
||||
}
|
||||
}
|
||||
u32 GetDestinationFactor(u8 *srcClr, u8 *dstClr, int mode)
|
||||
{
|
||||
switch (mode) {
|
||||
case 0: // zero
|
||||
return 0;
|
||||
case 1: // one
|
||||
return 0xffffffff;
|
||||
case 2: // srcclr
|
||||
return *(u32*)srcClr;
|
||||
case 3: // invsrcclr
|
||||
return 0xffffffff - *(u32*)srcClr;
|
||||
case 4: // srcalpha
|
||||
{
|
||||
u8 alpha = srcClr[ALP_C];
|
||||
u32 factor = alpha << 24 | alpha << 16 | alpha << 8 | alpha;
|
||||
return factor;
|
||||
}
|
||||
case 5: // invsrcalpha
|
||||
{
|
||||
u8 alpha = 0xff - srcClr[ALP_C];
|
||||
u32 factor = alpha << 24 | alpha << 16 | alpha << 8 | alpha;
|
||||
return factor;
|
||||
}
|
||||
case 6: // dstalpha
|
||||
{
|
||||
u8 alpha = dstClr[ALP_C] & 0xff;
|
||||
u32 factor = alpha << 24 | alpha << 16 | alpha << 8 | alpha;
|
||||
return factor;
|
||||
}
|
||||
case 7: // invdstalpha
|
||||
{
|
||||
u8 alpha = 0xff - dstClr[ALP_C];
|
||||
u32 factor = alpha << 24 | alpha << 16 | alpha << 8 | alpha;
|
||||
return factor;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void BlendColor(u8 *srcClr, u8 *dstClr)
|
||||
{
|
||||
u32 srcFactor = GetSourceFactor(srcClr, dstClr, bpmem.blendmode.srcfactor);
|
||||
u32 dstFactor = GetDestinationFactor(srcClr, dstClr, bpmem.blendmode.dstfactor);
|
||||
void BlendColor(u8 *srcClr, u8 *dstClr)
|
||||
{
|
||||
u32 srcFactor = GetSourceFactor(srcClr, dstClr, bpmem.blendmode.srcfactor);
|
||||
u32 dstFactor = GetDestinationFactor(srcClr, dstClr, bpmem.blendmode.dstfactor);
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
// add MSB of factors to make their range 0 -> 256
|
||||
u32 sf = (srcFactor & 0xff);
|
||||
sf += sf >> 7;
|
||||
|
||||
u32 df = (dstFactor & 0xff);
|
||||
df += df >> 7;
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
// add MSB of factors to make their range 0 -> 256
|
||||
u32 sf = (srcFactor & 0xff);
|
||||
sf += sf >> 7;
|
||||
|
||||
u32 color = (srcClr[i] * sf + dstClr[i] * df) >> 8;
|
||||
dstClr[i] = (color>255)?255:color;
|
||||
u32 df = (dstFactor & 0xff);
|
||||
df += df >> 7;
|
||||
|
||||
dstFactor >>= 8;
|
||||
srcFactor >>= 8;
|
||||
}
|
||||
}
|
||||
u32 color = (srcClr[i] * sf + dstClr[i] * df) >> 8;
|
||||
dstClr[i] = (color>255)?255:color;
|
||||
|
||||
void LogicBlend(u32 srcClr, u32 &dstClr, int op)
|
||||
{
|
||||
switch (op) {
|
||||
case 0: // clear
|
||||
dstClr = 0;
|
||||
break;
|
||||
case 1: // and
|
||||
dstClr = srcClr & dstClr;
|
||||
break;
|
||||
case 2: // revand
|
||||
dstClr = srcClr & (~dstClr);
|
||||
break;
|
||||
case 3: // copy
|
||||
dstClr = srcClr;
|
||||
break;
|
||||
case 4: // invand
|
||||
dstClr = (~srcClr) & dstClr;
|
||||
break;
|
||||
case 5: // noop
|
||||
dstFactor >>= 8;
|
||||
srcFactor >>= 8;
|
||||
}
|
||||
}
|
||||
|
||||
void LogicBlend(u32 srcClr, u32 &dstClr, int op)
|
||||
{
|
||||
switch (op)
|
||||
{
|
||||
case 0: // clear
|
||||
dstClr = 0;
|
||||
break;
|
||||
case 1: // and
|
||||
dstClr = srcClr & dstClr;
|
||||
break;
|
||||
case 2: // revand
|
||||
dstClr = srcClr & (~dstClr);
|
||||
break;
|
||||
case 3: // copy
|
||||
dstClr = srcClr;
|
||||
break;
|
||||
case 4: // invand
|
||||
dstClr = (~srcClr) & dstClr;
|
||||
break;
|
||||
case 5: // noop
|
||||
// Do nothing
|
||||
break;
|
||||
case 6: // xor
|
||||
dstClr = srcClr ^ dstClr;
|
||||
break;
|
||||
case 7: // or
|
||||
dstClr = srcClr | dstClr;
|
||||
break;
|
||||
case 8: // nor
|
||||
dstClr = ~(srcClr | dstClr);
|
||||
break;
|
||||
case 9: // equiv
|
||||
dstClr = ~(srcClr ^ dstClr);
|
||||
break;
|
||||
case 10: // inv
|
||||
dstClr = ~dstClr;
|
||||
break;
|
||||
case 11: // revor
|
||||
dstClr = srcClr | (~dstClr);
|
||||
break;
|
||||
case 12: // invcopy
|
||||
dstClr = ~srcClr;
|
||||
break;
|
||||
case 13: // invor
|
||||
dstClr = (~srcClr) | dstClr;
|
||||
break;
|
||||
case 14: // nand
|
||||
dstClr = ~(srcClr & dstClr);
|
||||
break;
|
||||
case 15: // set
|
||||
dstClr = 0xffffffff;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 6: // xor
|
||||
dstClr = srcClr ^ dstClr;
|
||||
break;
|
||||
case 7: // or
|
||||
dstClr = srcClr | dstClr;
|
||||
break;
|
||||
case 8: // nor
|
||||
dstClr = ~(srcClr | dstClr);
|
||||
break;
|
||||
case 9: // equiv
|
||||
dstClr = ~(srcClr ^ dstClr);
|
||||
break;
|
||||
case 10: // inv
|
||||
dstClr = ~dstClr;
|
||||
break;
|
||||
case 11: // revor
|
||||
dstClr = srcClr | (~dstClr);
|
||||
break;
|
||||
case 12: // invcopy
|
||||
dstClr = ~srcClr;
|
||||
break;
|
||||
case 13: // invor
|
||||
dstClr = (~srcClr) | dstClr;
|
||||
break;
|
||||
case 14: // nand
|
||||
dstClr = ~(srcClr & dstClr);
|
||||
break;
|
||||
case 15: // set
|
||||
dstClr = 0xffffffff;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void SubtractBlend(u8 *srcClr, u8 *dstClr)
|
||||
{
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
int c = (int)dstClr[i] - (int)srcClr[i];
|
||||
dstClr[i] = (c < 0)?0:c;
|
||||
}
|
||||
}
|
||||
void SubtractBlend(u8 *srcClr, u8 *dstClr)
|
||||
{
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
int c = (int)dstClr[i] - (int)srcClr[i];
|
||||
dstClr[i] = (c < 0)?0:c;
|
||||
}
|
||||
}
|
||||
|
||||
void BlendTev(u16 x, u16 y, u8 *color)
|
||||
{
|
||||
u32 dstClr;
|
||||
u32 offset = GetColorOffset(x, y);
|
||||
void BlendTev(u16 x, u16 y, u8 *color)
|
||||
{
|
||||
u32 dstClr;
|
||||
u32 offset = GetColorOffset(x, y);
|
||||
|
||||
u8 *dstClrPtr = (u8*)&dstClr;
|
||||
u8 *dstClrPtr = (u8*)&dstClr;
|
||||
|
||||
GetPixelColor(offset, dstClrPtr);
|
||||
GetPixelColor(offset, dstClrPtr);
|
||||
|
||||
if (bpmem.blendmode.blendenable)
|
||||
{
|
||||
if (bpmem.blendmode.subtract)
|
||||
SubtractBlend(color, dstClrPtr);
|
||||
else
|
||||
BlendColor(color, dstClrPtr);
|
||||
}
|
||||
else if (bpmem.blendmode.logicopenable)
|
||||
LogicBlend(*((u32*)color), dstClr, bpmem.blendmode.logicmode);
|
||||
else
|
||||
dstClrPtr = color;
|
||||
if (bpmem.blendmode.blendenable)
|
||||
{
|
||||
if (bpmem.blendmode.subtract)
|
||||
SubtractBlend(color, dstClrPtr);
|
||||
else
|
||||
BlendColor(color, dstClrPtr);
|
||||
}
|
||||
else if (bpmem.blendmode.logicopenable)
|
||||
{
|
||||
LogicBlend(*((u32*)color), dstClr, bpmem.blendmode.logicmode);
|
||||
}
|
||||
else
|
||||
{
|
||||
dstClrPtr = color;
|
||||
}
|
||||
|
||||
if (bpmem.dstalpha.enable)
|
||||
dstClrPtr[ALP_C] = bpmem.dstalpha.alpha;
|
||||
if (bpmem.dstalpha.enable)
|
||||
dstClrPtr[ALP_C] = bpmem.dstalpha.alpha;
|
||||
|
||||
if (bpmem.blendmode.colorupdate)
|
||||
{
|
||||
if (bpmem.blendmode.alphaupdate)
|
||||
SetPixelAlphaColor(offset, dstClrPtr);
|
||||
else
|
||||
SetPixelColorOnly(offset, dstClrPtr);
|
||||
}
|
||||
else if (bpmem.blendmode.alphaupdate)
|
||||
SetPixelAlphaOnly(offset, dstClrPtr[ALP_C]);
|
||||
{
|
||||
if (bpmem.blendmode.alphaupdate)
|
||||
SetPixelAlphaColor(offset, dstClrPtr);
|
||||
else
|
||||
SetPixelColorOnly(offset, dstClrPtr);
|
||||
}
|
||||
else if (bpmem.blendmode.alphaupdate)
|
||||
{
|
||||
SetPixelAlphaOnly(offset, dstClrPtr[ALP_C]);
|
||||
}
|
||||
|
||||
// branchless bounding box update
|
||||
SWPixelEngine::pereg.boxLeft = SWPixelEngine::pereg.boxLeft>x?x:SWPixelEngine::pereg.boxLeft;
|
||||
SWPixelEngine::pereg.boxRight = SWPixelEngine::pereg.boxRight<x?x:SWPixelEngine::pereg.boxRight;
|
||||
SWPixelEngine::pereg.boxTop = SWPixelEngine::pereg.boxTop>y?y:SWPixelEngine::pereg.boxTop;
|
||||
SWPixelEngine::pereg.boxBottom = SWPixelEngine::pereg.boxBottom<y?y:SWPixelEngine::pereg.boxBottom;
|
||||
}
|
||||
// branchless bounding box update
|
||||
SWPixelEngine::pereg.boxLeft = SWPixelEngine::pereg.boxLeft>x?x:SWPixelEngine::pereg.boxLeft;
|
||||
SWPixelEngine::pereg.boxRight = SWPixelEngine::pereg.boxRight<x?x:SWPixelEngine::pereg.boxRight;
|
||||
SWPixelEngine::pereg.boxTop = SWPixelEngine::pereg.boxTop>y?y:SWPixelEngine::pereg.boxTop;
|
||||
SWPixelEngine::pereg.boxBottom = SWPixelEngine::pereg.boxBottom<y?y:SWPixelEngine::pereg.boxBottom;
|
||||
}
|
||||
|
||||
void SetColor(u16 x, u16 y, u8 *color)
|
||||
{
|
||||
u32 offset = GetColorOffset(x, y);
|
||||
if (bpmem.blendmode.colorupdate)
|
||||
{
|
||||
if (bpmem.blendmode.alphaupdate)
|
||||
SetPixelAlphaColor(offset, color);
|
||||
else
|
||||
SetPixelColorOnly(offset, color);
|
||||
}
|
||||
else if (bpmem.blendmode.alphaupdate)
|
||||
SetPixelAlphaOnly(offset, color[ALP_C]);
|
||||
}
|
||||
void SetColor(u16 x, u16 y, u8 *color)
|
||||
{
|
||||
u32 offset = GetColorOffset(x, y);
|
||||
if (bpmem.blendmode.colorupdate)
|
||||
{
|
||||
if (bpmem.blendmode.alphaupdate)
|
||||
SetPixelAlphaColor(offset, color);
|
||||
else
|
||||
SetPixelColorOnly(offset, color);
|
||||
}
|
||||
else if (bpmem.blendmode.alphaupdate)
|
||||
{
|
||||
SetPixelAlphaOnly(offset, color[ALP_C]);
|
||||
}
|
||||
}
|
||||
|
||||
void SetDepth(u16 x, u16 y, u32 depth)
|
||||
{
|
||||
|
@ -467,87 +476,87 @@ namespace EfbInterface
|
|||
SetPixelDepth(GetDepthOffset(x, y), depth);
|
||||
}
|
||||
|
||||
void GetColor(u16 x, u16 y, u8 *color)
|
||||
{
|
||||
u32 offset = GetColorOffset(x, y);
|
||||
GetPixelColor(offset, color);
|
||||
}
|
||||
void GetColor(u16 x, u16 y, u8 *color)
|
||||
{
|
||||
u32 offset = GetColorOffset(x, y);
|
||||
GetPixelColor(offset, color);
|
||||
}
|
||||
|
||||
u32 GetDepth(u16 x, u16 y)
|
||||
{
|
||||
u32 offset = GetDepthOffset(x, y);
|
||||
return GetPixelDepth(offset);
|
||||
}
|
||||
u32 GetDepth(u16 x, u16 y)
|
||||
{
|
||||
u32 offset = GetDepthOffset(x, y);
|
||||
return GetPixelDepth(offset);
|
||||
}
|
||||
|
||||
u8 *GetPixelPointer(u16 x, u16 y, bool depth)
|
||||
{
|
||||
if (depth)
|
||||
return &efb[GetDepthOffset(x, y)];
|
||||
return &efb[GetColorOffset(x, y)];
|
||||
}
|
||||
u8 *GetPixelPointer(u16 x, u16 y, bool depth)
|
||||
{
|
||||
if (depth)
|
||||
return &efb[GetDepthOffset(x, y)];
|
||||
return &efb[GetColorOffset(x, y)];
|
||||
}
|
||||
|
||||
void UpdateColorTexture()
|
||||
{
|
||||
u32 color;
|
||||
void UpdateColorTexture()
|
||||
{
|
||||
u32 color;
|
||||
u8* colorPtr = (u8*)&color;
|
||||
u32* texturePtr = (u32*)efbColorTexture;
|
||||
u32 textureAddress = 0;
|
||||
u32 efbOffset = 0;
|
||||
|
||||
for (u16 y = 0; y < EFB_HEIGHT; y++)
|
||||
{
|
||||
for (u16 x = 0; x < EFB_WIDTH; x++)
|
||||
{
|
||||
GetPixelColor(efbOffset, colorPtr);
|
||||
efbOffset += 3;
|
||||
u32 textureAddress = 0;
|
||||
u32 efbOffset = 0;
|
||||
|
||||
for (u16 y = 0; y < EFB_HEIGHT; y++)
|
||||
{
|
||||
for (u16 x = 0; x < EFB_WIDTH; x++)
|
||||
{
|
||||
GetPixelColor(efbOffset, colorPtr);
|
||||
efbOffset += 3;
|
||||
texturePtr[textureAddress++] = Common::swap32(color); // ABGR->RGBA
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ZCompare(u16 x, u16 y, u32 z)
|
||||
{
|
||||
u32 offset = GetDepthOffset(x, y);
|
||||
u32 depth = GetPixelDepth(offset);
|
||||
bool ZCompare(u16 x, u16 y, u32 z)
|
||||
{
|
||||
u32 offset = GetDepthOffset(x, y);
|
||||
u32 depth = GetPixelDepth(offset);
|
||||
|
||||
bool pass;
|
||||
bool pass;
|
||||
|
||||
switch (bpmem.zmode.func)
|
||||
{
|
||||
case COMPARE_NEVER:
|
||||
pass = false;
|
||||
break;
|
||||
case COMPARE_LESS:
|
||||
pass = z < depth;
|
||||
break;
|
||||
case COMPARE_EQUAL:
|
||||
pass = z == depth;
|
||||
break;
|
||||
case COMPARE_LEQUAL:
|
||||
pass = z <= depth;
|
||||
break;
|
||||
case COMPARE_GREATER:
|
||||
pass = z > depth;
|
||||
break;
|
||||
case COMPARE_NEQUAL:
|
||||
pass = z != depth;
|
||||
break;
|
||||
case COMPARE_GEQUAL:
|
||||
pass = z >= depth;
|
||||
break;
|
||||
case COMPARE_ALWAYS:
|
||||
pass = true;
|
||||
break;
|
||||
default:
|
||||
pass = false;
|
||||
ERROR_LOG(VIDEO, "Bad Z compare mode %i", bpmem.zmode.func);
|
||||
}
|
||||
switch (bpmem.zmode.func)
|
||||
{
|
||||
case COMPARE_NEVER:
|
||||
pass = false;
|
||||
break;
|
||||
case COMPARE_LESS:
|
||||
pass = z < depth;
|
||||
break;
|
||||
case COMPARE_EQUAL:
|
||||
pass = z == depth;
|
||||
break;
|
||||
case COMPARE_LEQUAL:
|
||||
pass = z <= depth;
|
||||
break;
|
||||
case COMPARE_GREATER:
|
||||
pass = z > depth;
|
||||
break;
|
||||
case COMPARE_NEQUAL:
|
||||
pass = z != depth;
|
||||
break;
|
||||
case COMPARE_GEQUAL:
|
||||
pass = z >= depth;
|
||||
break;
|
||||
case COMPARE_ALWAYS:
|
||||
pass = true;
|
||||
break;
|
||||
default:
|
||||
pass = false;
|
||||
ERROR_LOG(VIDEO, "Bad Z compare mode %i", bpmem.zmode.func);
|
||||
}
|
||||
|
||||
if (pass && bpmem.zmode.updateenable)
|
||||
{
|
||||
SetPixelDepth(offset, z);
|
||||
}
|
||||
|
||||
return pass;
|
||||
}
|
||||
if (pass && bpmem.zmode.updateenable)
|
||||
{
|
||||
SetPixelDepth(offset, z);
|
||||
}
|
||||
|
||||
return pass;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// Official Git repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _EFB_INTERFACE_H_
|
||||
|
@ -22,32 +22,32 @@
|
|||
|
||||
namespace EfbInterface
|
||||
{
|
||||
const int DEPTH_BUFFER_START = EFB_WIDTH * EFB_HEIGHT * 3;
|
||||
const int DEPTH_BUFFER_START = EFB_WIDTH * EFB_HEIGHT * 3;
|
||||
|
||||
enum { ALP_C, BLU_C, GRN_C, RED_C };
|
||||
|
||||
// color order is ABGR in order to emulate RGBA on little-endian hardware
|
||||
// color order is ABGR in order to emulate RGBA on little-endian hardware
|
||||
|
||||
// does full blending of an incoming pixel
|
||||
void BlendTev(u16 x, u16 y, u8 *color);
|
||||
// does full blending of an incoming pixel
|
||||
void BlendTev(u16 x, u16 y, u8 *color);
|
||||
|
||||
// compare z at location x,y
|
||||
// writes it if it passes
|
||||
// returns result of compare.
|
||||
bool ZCompare(u16 x, u16 y, u32 z);
|
||||
// compare z at location x,y
|
||||
// writes it if it passes
|
||||
// returns result of compare.
|
||||
bool ZCompare(u16 x, u16 y, u32 z);
|
||||
|
||||
// sets the color and alpha
|
||||
void SetColor(u16 x, u16 y, u8 *color);
|
||||
void SetDepth(u16 x, u16 y, u32 depth);
|
||||
// sets the color and alpha
|
||||
void SetColor(u16 x, u16 y, u8 *color);
|
||||
void SetDepth(u16 x, u16 y, u32 depth);
|
||||
|
||||
void GetColor(u16 x, u16 y, u8 *color);
|
||||
u32 GetDepth(u16 x, u16 y);
|
||||
void GetColor(u16 x, u16 y, u8 *color);
|
||||
u32 GetDepth(u16 x, u16 y);
|
||||
|
||||
u8* GetPixelPointer(u16 x, u16 y, bool depth);
|
||||
u8* GetPixelPointer(u16 x, u16 y, bool depth);
|
||||
|
||||
void UpdateColorTexture();
|
||||
extern u8 efbColorTexture[EFB_WIDTH*EFB_HEIGHT*4]; // RGBA format
|
||||
void UpdateColorTexture();
|
||||
extern u8 efbColorTexture[EFB_WIDTH*EFB_HEIGHT*4]; // RGBA format
|
||||
void DoState(PointerWrap &p);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// Official Git repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "Common.h"
|
||||
|
@ -369,10 +369,10 @@ namespace HwRasterizer
|
|||
|
||||
// extra checks cause textures to be reloaded much more
|
||||
if (texUnit.texImage0[0].hex != texImage0.hex ||
|
||||
//texUnit.texImage1[0].hex != texImage1.hex ||
|
||||
//texUnit.texImage2[0].hex != texImage2.hex ||
|
||||
texUnit.texImage3[0].hex != texImage3.hex ||
|
||||
texUnit.texTlut[0].hex != texTlut.hex)
|
||||
// texUnit.texImage1[0].hex != texImage1.hex ||
|
||||
// texUnit.texImage2[0].hex != texImage2.hex ||
|
||||
texUnit.texImage3[0].hex != texImage3.hex ||
|
||||
texUnit.texTlut[0].hex != texTlut.hex)
|
||||
{
|
||||
Destroy();
|
||||
Create();
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// Official Git repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _HW_RASTERIZER_H
|
||||
|
@ -27,37 +27,37 @@ struct OutputVertexData;
|
|||
|
||||
namespace HwRasterizer
|
||||
{
|
||||
void Init();
|
||||
void Init();
|
||||
void Shutdown();
|
||||
|
||||
|
||||
void Prepare();
|
||||
|
||||
void BeginTriangles();
|
||||
void EndTriangles();
|
||||
void BeginTriangles();
|
||||
void EndTriangles();
|
||||
|
||||
void DrawTriangleFrontFace(OutputVertexData *v0, OutputVertexData *v1, OutputVertexData *v2);
|
||||
void DrawTriangleFrontFace(OutputVertexData *v0, OutputVertexData *v1, OutputVertexData *v2);
|
||||
|
||||
void Clear();
|
||||
void Clear();
|
||||
|
||||
struct TexCacheEntry
|
||||
{
|
||||
TexImage0 texImage0;
|
||||
TexImage1 texImage1;
|
||||
TexImage2 texImage2;
|
||||
TexImage3 texImage3;
|
||||
TexTLUT texTlut;
|
||||
struct TexCacheEntry
|
||||
{
|
||||
TexImage0 texImage0;
|
||||
TexImage1 texImage1;
|
||||
TexImage2 texImage2;
|
||||
TexImage3 texImage3;
|
||||
TexTLUT texTlut;
|
||||
|
||||
GLuint texture;
|
||||
GLuint texture;
|
||||
|
||||
TexCacheEntry();
|
||||
TexCacheEntry();
|
||||
|
||||
void Create();
|
||||
void Destroy();
|
||||
void Update();
|
||||
};
|
||||
void Create();
|
||||
void Destroy();
|
||||
void Update();
|
||||
};
|
||||
|
||||
typedef std::map<u32, TexCacheEntry> TextureCache;
|
||||
static TextureCache textures;
|
||||
typedef std::map<u32, TexCacheEntry> TextureCache;
|
||||
static TextureCache textures;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// Official Git repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _NATIVEVERTEXFORMAT_H
|
||||
|
@ -39,13 +39,13 @@ struct Vec4
|
|||
|
||||
struct InputVertexData
|
||||
{
|
||||
u8 posMtx;
|
||||
u8 texMtx[8];
|
||||
u8 posMtx;
|
||||
u8 texMtx[8];
|
||||
|
||||
Vec3 position;
|
||||
Vec3 normal[3];
|
||||
u8 color[2][4];
|
||||
float texCoords[8][2];
|
||||
Vec3 position;
|
||||
Vec3 normal[3];
|
||||
u8 color[2][4];
|
||||
float texCoords[8][2];
|
||||
};
|
||||
|
||||
struct OutputVertexData
|
||||
|
@ -54,45 +54,45 @@ struct OutputVertexData
|
|||
enum { RED_C, GRN_C, BLU_C, ALP_C };
|
||||
|
||||
Vec3 mvPosition;
|
||||
Vec4 projectedPosition;
|
||||
Vec3 screenPosition;
|
||||
Vec3 normal[3];
|
||||
u8 color[2][4];
|
||||
Vec3 texCoords[8];
|
||||
Vec4 projectedPosition;
|
||||
Vec3 screenPosition;
|
||||
Vec3 normal[3];
|
||||
u8 color[2][4];
|
||||
Vec3 texCoords[8];
|
||||
|
||||
void Lerp(float t, OutputVertexData *a, OutputVertexData *b)
|
||||
{
|
||||
#define LINTERP(T, OUT, IN) (OUT) + ((IN - OUT) * T)
|
||||
void Lerp(float t, OutputVertexData *a, OutputVertexData *b)
|
||||
{
|
||||
#define LINTERP(T, OUT, IN) (OUT) + ((IN - OUT) * T)
|
||||
|
||||
#define LINTERP_INT(T, OUT, IN) (OUT) + (((IN - OUT) * T) >> 8)
|
||||
#define LINTERP_INT(T, OUT, IN) (OUT) + (((IN - OUT) * T) >> 8)
|
||||
|
||||
mvPosition = LINTERP(t, a->mvPosition, b->mvPosition);
|
||||
mvPosition = LINTERP(t, a->mvPosition, b->mvPosition);
|
||||
|
||||
projectedPosition.x = LINTERP(t, a->projectedPosition.x, b->projectedPosition.x);
|
||||
projectedPosition.x = LINTERP(t, a->projectedPosition.x, b->projectedPosition.x);
|
||||
projectedPosition.y = LINTERP(t, a->projectedPosition.y, b->projectedPosition.y);
|
||||
projectedPosition.z = LINTERP(t, a->projectedPosition.z, b->projectedPosition.z);
|
||||
projectedPosition.w = LINTERP(t, a->projectedPosition.w, b->projectedPosition.w);
|
||||
|
||||
for (int i = 0; i < 3; ++i)
|
||||
{
|
||||
normal[i] = LINTERP(t, a->normal[i], b->normal[i]);
|
||||
}
|
||||
for (int i = 0; i < 3; ++i)
|
||||
{
|
||||
normal[i] = LINTERP(t, a->normal[i], b->normal[i]);
|
||||
}
|
||||
|
||||
u16 t_int = (u16)(t * 256);
|
||||
for (int i = 0; i < 4; ++i)
|
||||
{
|
||||
color[0][i] = LINTERP_INT(t_int, a->color[0][i], b->color[0][i]);
|
||||
color[1][i] = LINTERP_INT(t_int, a->color[1][i], b->color[1][i]);
|
||||
}
|
||||
u16 t_int = (u16)(t * 256);
|
||||
for (int i = 0; i < 4; ++i)
|
||||
{
|
||||
color[0][i] = LINTERP_INT(t_int, a->color[0][i], b->color[0][i]);
|
||||
color[1][i] = LINTERP_INT(t_int, a->color[1][i], b->color[1][i]);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 8; ++i)
|
||||
{
|
||||
texCoords[i] = LINTERP(t, a->texCoords[i], b->texCoords[i]);
|
||||
}
|
||||
for (int i = 0; i < 8; ++i)
|
||||
{
|
||||
texCoords[i] = LINTERP(t, a->texCoords[i], b->texCoords[i]);
|
||||
}
|
||||
|
||||
#undef LINTERP
|
||||
#undef LINTERP_INT
|
||||
}
|
||||
#undef LINTERP
|
||||
#undef LINTERP_INT
|
||||
}
|
||||
void DoState(PointerWrap &p)
|
||||
{
|
||||
mvPosition.DoState(p);
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// Official Git repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "Common.h"
|
||||
|
@ -61,258 +61,258 @@ void DoState(PointerWrap &p)
|
|||
|
||||
void DecodePrimitiveStream(u32 iBufferSize)
|
||||
{
|
||||
u32 vertexSize = vertexLoader.GetVertexSize();
|
||||
u32 vertexSize = vertexLoader.GetVertexSize();
|
||||
|
||||
bool skipPrimitives = g_bSkipCurrentFrame ||
|
||||
swstats.thisFrame.numDrawnObjects < g_SWVideoConfig.drawStart ||
|
||||
swstats.thisFrame.numDrawnObjects >= g_SWVideoConfig.drawEnd;
|
||||
|
||||
if (skipPrimitives)
|
||||
{
|
||||
while (streamSize > 0 && iBufferSize >= vertexSize)
|
||||
{
|
||||
g_pVideoData += vertexSize;
|
||||
iBufferSize -= vertexSize;
|
||||
streamSize--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (streamSize > 0 && iBufferSize >= vertexSize)
|
||||
{
|
||||
vertexLoader.LoadVertex();
|
||||
iBufferSize -= vertexSize;
|
||||
streamSize--;
|
||||
}
|
||||
}
|
||||
if (skipPrimitives)
|
||||
{
|
||||
while (streamSize > 0 && iBufferSize >= vertexSize)
|
||||
{
|
||||
g_pVideoData += vertexSize;
|
||||
iBufferSize -= vertexSize;
|
||||
streamSize--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (streamSize > 0 && iBufferSize >= vertexSize)
|
||||
{
|
||||
vertexLoader.LoadVertex();
|
||||
iBufferSize -= vertexSize;
|
||||
streamSize--;
|
||||
}
|
||||
}
|
||||
|
||||
if (streamSize == 0)
|
||||
{
|
||||
// return to normal command processing
|
||||
ResetDecoding();
|
||||
}
|
||||
if (streamSize == 0)
|
||||
{
|
||||
// return to normal command processing
|
||||
ResetDecoding();
|
||||
}
|
||||
}
|
||||
|
||||
void ReadXFData(u32 iBufferSize)
|
||||
{
|
||||
_assert_msg_(VIDEO, iBufferSize >= (u32)(streamSize * 4), "Underflow during standard opcode decoding");
|
||||
_assert_msg_(VIDEO, iBufferSize >= (u32)(streamSize * 4), "Underflow during standard opcode decoding");
|
||||
|
||||
u32 pData[16];
|
||||
for (int i = 0; i < streamSize; i++)
|
||||
pData[i] = DataReadU32();
|
||||
SWLoadXFReg(streamSize, streamAddress, pData);
|
||||
u32 pData[16];
|
||||
for (int i = 0; i < streamSize; i++)
|
||||
pData[i] = DataReadU32();
|
||||
SWLoadXFReg(streamSize, streamAddress, pData);
|
||||
|
||||
// return to normal command processing
|
||||
ResetDecoding();
|
||||
// return to normal command processing
|
||||
ResetDecoding();
|
||||
}
|
||||
|
||||
void ExecuteDisplayList(u32 addr, u32 count)
|
||||
{
|
||||
u8 *videoDataSave = g_pVideoData;
|
||||
u8 *videoDataSave = g_pVideoData;
|
||||
|
||||
u8 *dlStart = Memory::GetPointer(addr);
|
||||
u8 *dlStart = Memory::GetPointer(addr);
|
||||
|
||||
g_pVideoData = dlStart;
|
||||
g_pVideoData = dlStart;
|
||||
|
||||
while (OpcodeDecoder::CommandRunnable(count))
|
||||
{
|
||||
OpcodeDecoder::Run(count);
|
||||
while (OpcodeDecoder::CommandRunnable(count))
|
||||
{
|
||||
OpcodeDecoder::Run(count);
|
||||
|
||||
// if data was read by the opcode decoder then the video data pointer changed
|
||||
u32 readCount = (u32)(g_pVideoData - dlStart);
|
||||
dlStart = g_pVideoData;
|
||||
// if data was read by the opcode decoder then the video data pointer changed
|
||||
u32 readCount = (u32)(g_pVideoData - dlStart);
|
||||
dlStart = g_pVideoData;
|
||||
|
||||
_assert_msg_(VIDEO, count >= readCount, "Display list underrun");
|
||||
_assert_msg_(VIDEO, count >= readCount, "Display list underrun");
|
||||
|
||||
count -= readCount;
|
||||
}
|
||||
count -= readCount;
|
||||
}
|
||||
|
||||
g_pVideoData = videoDataSave;
|
||||
g_pVideoData = videoDataSave;
|
||||
}
|
||||
|
||||
void DecodeStandard(u32 bufferSize)
|
||||
{
|
||||
_assert_msg_(VIDEO, CommandRunnable(bufferSize), "Underflow during standard opcode decoding");
|
||||
_assert_msg_(VIDEO, CommandRunnable(bufferSize), "Underflow during standard opcode decoding");
|
||||
|
||||
int Cmd = DataReadU8();
|
||||
int Cmd = DataReadU8();
|
||||
|
||||
if (Cmd == GX_NOP)
|
||||
return;
|
||||
// Causes a SIGBUS error on Android
|
||||
// XXX: Investigate
|
||||
if (Cmd == GX_NOP)
|
||||
return;
|
||||
// Causes a SIGBUS error on Android
|
||||
// XXX: Investigate
|
||||
#ifndef ANDROID
|
||||
// check if switching in or out of an object
|
||||
// only used for debuggging
|
||||
if (inObjectStream && (Cmd & 0x87) != lastPrimCmd)
|
||||
{
|
||||
inObjectStream = false;
|
||||
DebugUtil::OnObjectEnd();
|
||||
}
|
||||
if (Cmd & 0x80 && !inObjectStream)
|
||||
{
|
||||
inObjectStream = true;
|
||||
lastPrimCmd = Cmd & 0x87;
|
||||
DebugUtil::OnObjectBegin();
|
||||
}
|
||||
// check if switching in or out of an object
|
||||
// only used for debuggging
|
||||
if (inObjectStream && (Cmd & 0x87) != lastPrimCmd)
|
||||
{
|
||||
inObjectStream = false;
|
||||
DebugUtil::OnObjectEnd();
|
||||
}
|
||||
if (Cmd & 0x80 && !inObjectStream)
|
||||
{
|
||||
inObjectStream = true;
|
||||
lastPrimCmd = Cmd & 0x87;
|
||||
DebugUtil::OnObjectBegin();
|
||||
}
|
||||
#endif
|
||||
switch(Cmd)
|
||||
{
|
||||
case GX_NOP:
|
||||
break;
|
||||
switch(Cmd)
|
||||
{
|
||||
case GX_NOP:
|
||||
break;
|
||||
|
||||
case GX_LOAD_CP_REG: //0x08
|
||||
{
|
||||
u32 SubCmd = DataReadU8();
|
||||
u32 Value = DataReadU32();
|
||||
SWLoadCPReg(SubCmd, Value);
|
||||
}
|
||||
break;
|
||||
case GX_LOAD_CP_REG: //0x08
|
||||
{
|
||||
u32 SubCmd = DataReadU8();
|
||||
u32 Value = DataReadU32();
|
||||
SWLoadCPReg(SubCmd, Value);
|
||||
}
|
||||
break;
|
||||
|
||||
case GX_LOAD_XF_REG:
|
||||
{
|
||||
u32 Cmd2 = DataReadU32();
|
||||
streamSize = ((Cmd2 >> 16) & 15) + 1;
|
||||
streamAddress = Cmd2 & 0xFFFF;
|
||||
currentFunction = ReadXFData;
|
||||
minCommandSize = streamSize * 4;
|
||||
readOpcode = false;
|
||||
}
|
||||
break;
|
||||
case GX_LOAD_XF_REG:
|
||||
{
|
||||
u32 Cmd2 = DataReadU32();
|
||||
streamSize = ((Cmd2 >> 16) & 15) + 1;
|
||||
streamAddress = Cmd2 & 0xFFFF;
|
||||
currentFunction = ReadXFData;
|
||||
minCommandSize = streamSize * 4;
|
||||
readOpcode = false;
|
||||
}
|
||||
break;
|
||||
|
||||
case GX_LOAD_INDX_A: //used for position matrices
|
||||
SWLoadIndexedXF(DataReadU32(), 0xC);
|
||||
break;
|
||||
case GX_LOAD_INDX_B: //used for normal matrices
|
||||
SWLoadIndexedXF(DataReadU32(), 0xD);
|
||||
break;
|
||||
case GX_LOAD_INDX_C: //used for postmatrices
|
||||
SWLoadIndexedXF(DataReadU32(), 0xE);
|
||||
break;
|
||||
case GX_LOAD_INDX_D: //used for lights
|
||||
SWLoadIndexedXF(DataReadU32(), 0xF);
|
||||
break;
|
||||
case GX_LOAD_INDX_A: //used for position matrices
|
||||
SWLoadIndexedXF(DataReadU32(), 0xC);
|
||||
break;
|
||||
case GX_LOAD_INDX_B: //used for normal matrices
|
||||
SWLoadIndexedXF(DataReadU32(), 0xD);
|
||||
break;
|
||||
case GX_LOAD_INDX_C: //used for postmatrices
|
||||
SWLoadIndexedXF(DataReadU32(), 0xE);
|
||||
break;
|
||||
case GX_LOAD_INDX_D: //used for lights
|
||||
SWLoadIndexedXF(DataReadU32(), 0xF);
|
||||
break;
|
||||
|
||||
case GX_CMD_CALL_DL:
|
||||
{
|
||||
u32 dwAddr = DataReadU32();
|
||||
u32 dwCount = DataReadU32();
|
||||
ExecuteDisplayList(dwAddr, dwCount);
|
||||
}
|
||||
break;
|
||||
case GX_CMD_CALL_DL:
|
||||
{
|
||||
u32 dwAddr = DataReadU32();
|
||||
u32 dwCount = DataReadU32();
|
||||
ExecuteDisplayList(dwAddr, dwCount);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x44:
|
||||
// zelda 4 swords calls it and checks the metrics registers after that
|
||||
break;
|
||||
case 0x44:
|
||||
// zelda 4 swords calls it and checks the metrics registers after that
|
||||
break;
|
||||
|
||||
case GX_CMD_INVL_VC:// Invalidate (vertex cache?)
|
||||
DEBUG_LOG(VIDEO, "Invalidate (vertex cache?)");
|
||||
break;
|
||||
case GX_CMD_INVL_VC:// Invalidate (vertex cache?)
|
||||
DEBUG_LOG(VIDEO, "Invalidate (vertex cache?)");
|
||||
break;
|
||||
|
||||
case GX_LOAD_BP_REG: //0x61
|
||||
{
|
||||
case GX_LOAD_BP_REG: //0x61
|
||||
{
|
||||
u32 cmd = DataReadU32();
|
||||
SWLoadBPReg(cmd);
|
||||
}
|
||||
break;
|
||||
SWLoadBPReg(cmd);
|
||||
}
|
||||
break;
|
||||
|
||||
// draw primitives
|
||||
default:
|
||||
if (Cmd & 0x80)
|
||||
{
|
||||
// draw primitives
|
||||
default:
|
||||
if (Cmd & 0x80)
|
||||
{
|
||||
u8 vatIndex = Cmd & GX_VAT_MASK;
|
||||
u8 primitiveType = (Cmd & GX_PRIMITIVE_MASK) >> GX_PRIMITIVE_SHIFT;
|
||||
vertexLoader.SetFormat(vatIndex, primitiveType);
|
||||
|
||||
// switch to primitive processing
|
||||
streamSize = DataReadU16();
|
||||
currentFunction = DecodePrimitiveStream;
|
||||
minCommandSize = vertexLoader.GetVertexSize();
|
||||
readOpcode = false;
|
||||
u8 primitiveType = (Cmd & GX_PRIMITIVE_MASK) >> GX_PRIMITIVE_SHIFT;
|
||||
vertexLoader.SetFormat(vatIndex, primitiveType);
|
||||
|
||||
INCSTAT(swstats.thisFrame.numPrimatives);
|
||||
DEBUG_LOG(VIDEO, "Draw begin");
|
||||
}
|
||||
else
|
||||
{
|
||||
PanicAlert("GFX: Unknown Opcode (0x%x).\n", Cmd);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
// switch to primitive processing
|
||||
streamSize = DataReadU16();
|
||||
currentFunction = DecodePrimitiveStream;
|
||||
minCommandSize = vertexLoader.GetVertexSize();
|
||||
readOpcode = false;
|
||||
|
||||
INCSTAT(swstats.thisFrame.numPrimatives);
|
||||
DEBUG_LOG(VIDEO, "Draw begin");
|
||||
}
|
||||
else
|
||||
{
|
||||
PanicAlert("GFX: Unknown Opcode (0x%x).\n", Cmd);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Init()
|
||||
{
|
||||
inObjectStream = false;
|
||||
lastPrimCmd = 0;
|
||||
ResetDecoding();
|
||||
inObjectStream = false;
|
||||
lastPrimCmd = 0;
|
||||
ResetDecoding();
|
||||
}
|
||||
|
||||
void ResetDecoding()
|
||||
{
|
||||
currentFunction = DecodeStandard;
|
||||
minCommandSize = 1;
|
||||
readOpcode = true;
|
||||
currentFunction = DecodeStandard;
|
||||
minCommandSize = 1;
|
||||
readOpcode = true;
|
||||
}
|
||||
|
||||
bool CommandRunnable(u32 iBufferSize)
|
||||
{
|
||||
if (iBufferSize < minCommandSize)
|
||||
return false;
|
||||
if (iBufferSize < minCommandSize)
|
||||
return false;
|
||||
|
||||
if (readOpcode)
|
||||
{
|
||||
u8 Cmd = DataPeek8(0);
|
||||
u32 minSize = 1;
|
||||
if (readOpcode)
|
||||
{
|
||||
u8 Cmd = DataPeek8(0);
|
||||
u32 minSize = 1;
|
||||
|
||||
switch(Cmd)
|
||||
{
|
||||
case GX_LOAD_CP_REG: //0x08
|
||||
minSize = 6;
|
||||
break;
|
||||
switch(Cmd)
|
||||
{
|
||||
case GX_LOAD_CP_REG: //0x08
|
||||
minSize = 6;
|
||||
break;
|
||||
|
||||
case GX_LOAD_XF_REG:
|
||||
minSize = 5;
|
||||
break;
|
||||
case GX_LOAD_XF_REG:
|
||||
minSize = 5;
|
||||
break;
|
||||
|
||||
case GX_LOAD_INDX_A: //used for position matrices
|
||||
minSize = 5;
|
||||
break;
|
||||
case GX_LOAD_INDX_B: //used for normal matrices
|
||||
minSize = 5;
|
||||
break;
|
||||
case GX_LOAD_INDX_C: //used for postmatrices
|
||||
minSize = 5;
|
||||
break;
|
||||
case GX_LOAD_INDX_D: //used for lights
|
||||
minSize = 5;
|
||||
break;
|
||||
case GX_LOAD_INDX_A: //used for position matrices
|
||||
minSize = 5;
|
||||
break;
|
||||
case GX_LOAD_INDX_B: //used for normal matrices
|
||||
minSize = 5;
|
||||
break;
|
||||
case GX_LOAD_INDX_C: //used for postmatrices
|
||||
minSize = 5;
|
||||
break;
|
||||
case GX_LOAD_INDX_D: //used for lights
|
||||
minSize = 5;
|
||||
break;
|
||||
|
||||
case GX_CMD_CALL_DL:
|
||||
minSize = 9;
|
||||
break;
|
||||
case GX_CMD_CALL_DL:
|
||||
minSize = 9;
|
||||
break;
|
||||
|
||||
case GX_LOAD_BP_REG: //0x61
|
||||
minSize = 5;
|
||||
break;
|
||||
case GX_LOAD_BP_REG: //0x61
|
||||
minSize = 5;
|
||||
break;
|
||||
|
||||
// draw primitives
|
||||
default:
|
||||
if (Cmd & 0x80)
|
||||
minSize = 3;
|
||||
break;
|
||||
}
|
||||
// draw primitives
|
||||
default:
|
||||
if (Cmd & 0x80)
|
||||
minSize = 3;
|
||||
break;
|
||||
}
|
||||
|
||||
return (iBufferSize >= minSize);
|
||||
}
|
||||
|
||||
return true;
|
||||
return (iBufferSize >= minSize);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Run(u32 iBufferSize)
|
||||
{
|
||||
currentFunction(iBufferSize);
|
||||
currentFunction(iBufferSize);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// Official Git repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
|
||||
|
@ -25,39 +25,39 @@
|
|||
namespace OpcodeDecoder
|
||||
{
|
||||
|
||||
#define GX_NOP 0x00
|
||||
#define GX_NOP 0x00
|
||||
|
||||
#define GX_LOAD_BP_REG 0x61
|
||||
#define GX_LOAD_CP_REG 0x08
|
||||
#define GX_LOAD_XF_REG 0x10
|
||||
#define GX_LOAD_INDX_A 0x20
|
||||
#define GX_LOAD_INDX_B 0x28
|
||||
#define GX_LOAD_INDX_C 0x30
|
||||
#define GX_LOAD_INDX_D 0x38
|
||||
#define GX_LOAD_BP_REG 0x61
|
||||
#define GX_LOAD_CP_REG 0x08
|
||||
#define GX_LOAD_XF_REG 0x10
|
||||
#define GX_LOAD_INDX_A 0x20
|
||||
#define GX_LOAD_INDX_B 0x28
|
||||
#define GX_LOAD_INDX_C 0x30
|
||||
#define GX_LOAD_INDX_D 0x38
|
||||
|
||||
#define GX_CMD_CALL_DL 0x40
|
||||
#define GX_CMD_INVL_VC 0x48
|
||||
#define GX_CMD_CALL_DL 0x40
|
||||
#define GX_CMD_INVL_VC 0x48
|
||||
|
||||
#define GX_PRIMITIVE_MASK 0x78
|
||||
#define GX_PRIMITIVE_SHIFT 3
|
||||
#define GX_VAT_MASK 0x07
|
||||
#define GX_PRIMITIVE_MASK 0x78
|
||||
#define GX_PRIMITIVE_SHIFT 3
|
||||
#define GX_VAT_MASK 0x07
|
||||
|
||||
//these are defined 1/8th of their real values and without their top bit
|
||||
#define GX_DRAW_QUADS 0x0 //0x80
|
||||
#define GX_DRAW_TRIANGLES 0x2 //0x90
|
||||
#define GX_DRAW_TRIANGLE_STRIP 0x3 //0x98
|
||||
#define GX_DRAW_TRIANGLE_FAN 0x4 //0xA0
|
||||
#define GX_DRAW_LINES 0x5 //0xA8
|
||||
#define GX_DRAW_LINE_STRIP 0x6 //0xB0
|
||||
#define GX_DRAW_POINTS 0x7 //0xB8
|
||||
//these are defined 1/8th of their real values and without their top bit
|
||||
#define GX_DRAW_QUADS 0x0 //0x80
|
||||
#define GX_DRAW_TRIANGLES 0x2 //0x90
|
||||
#define GX_DRAW_TRIANGLE_STRIP 0x3 //0x98
|
||||
#define GX_DRAW_TRIANGLE_FAN 0x4 //0xA0
|
||||
#define GX_DRAW_LINES 0x5 //0xA8
|
||||
#define GX_DRAW_LINE_STRIP 0x6 //0xB0
|
||||
#define GX_DRAW_POINTS 0x7 //0xB8
|
||||
|
||||
void Init();
|
||||
void Init();
|
||||
|
||||
void ResetDecoding();
|
||||
void ResetDecoding();
|
||||
|
||||
bool CommandRunnable(u32 iBufferSize);
|
||||
bool CommandRunnable(u32 iBufferSize);
|
||||
|
||||
void Run(u32 iBufferSize);
|
||||
void Run(u32 iBufferSize);
|
||||
|
||||
void DoState(PointerWrap &p);
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// Official Git repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "../../Plugin_VideoOGL/Src/GLUtil.h"
|
||||
|
@ -23,110 +23,112 @@
|
|||
// globals
|
||||
|
||||
const GLubyte rasters[][13] = {
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36},
|
||||
{0x00, 0x00, 0x00, 0x66, 0x66, 0xff, 0x66, 0x66, 0xff, 0x66, 0x66, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x18, 0x7e, 0xff, 0x1b, 0x1f, 0x7e, 0xf8, 0xd8, 0xff, 0x7e, 0x18},
|
||||
{0x00, 0x00, 0x0e, 0x1b, 0xdb, 0x6e, 0x30, 0x18, 0x0c, 0x76, 0xdb, 0xd8, 0x70},
|
||||
{0x00, 0x00, 0x7f, 0xc6, 0xcf, 0xd8, 0x70, 0x70, 0xd8, 0xcc, 0xcc, 0x6c, 0x38},
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x1c, 0x0c, 0x0e},
|
||||
{0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x18, 0x0c},
|
||||
{0x00, 0x00, 0x30, 0x18, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x30},
|
||||
{0x00, 0x00, 0x00, 0x00, 0x99, 0x5a, 0x3c, 0xff, 0x3c, 0x5a, 0x99, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0xff, 0xff, 0x18, 0x18, 0x18, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x30, 0x18, 0x1c, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x60, 0x60, 0x30, 0x30, 0x18, 0x18, 0x0c, 0x0c, 0x06, 0x06, 0x03, 0x03},
|
||||
{0x00, 0x00, 0x3c, 0x66, 0xc3, 0xe3, 0xf3, 0xdb, 0xcf, 0xc7, 0xc3, 0x66, 0x3c},
|
||||
{0x00, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78, 0x38, 0x18},
|
||||
{0x00, 0x00, 0xff, 0xc0, 0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x03, 0xe7, 0x7e},
|
||||
{0x00, 0x00, 0x7e, 0xe7, 0x03, 0x03, 0x07, 0x7e, 0x07, 0x03, 0x03, 0xe7, 0x7e},
|
||||
{0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xff, 0xcc, 0x6c, 0x3c, 0x1c, 0x0c},
|
||||
{0x00, 0x00, 0x7e, 0xe7, 0x03, 0x03, 0x07, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0, 0xff},
|
||||
{0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xc7, 0xfe, 0xc0, 0xc0, 0xc0, 0xe7, 0x7e},
|
||||
{0x00, 0x00, 0x30, 0x30, 0x30, 0x30, 0x18, 0x0c, 0x06, 0x03, 0x03, 0x03, 0xff},
|
||||
{0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xe7, 0x7e, 0xe7, 0xc3, 0xc3, 0xe7, 0x7e},
|
||||
{0x00, 0x00, 0x7e, 0xe7, 0x03, 0x03, 0x03, 0x7f, 0xe7, 0xc3, 0xc3, 0xe7, 0x7e},
|
||||
{0x00, 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x30, 0x18, 0x1c, 0x1c, 0x00, 0x00, 0x1c, 0x1c, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06},
|
||||
{0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x03, 0x06, 0x0c, 0x18, 0x30, 0x60},
|
||||
{0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x18, 0x0c, 0x06, 0x03, 0xc3, 0xc3, 0x7e},
|
||||
{0x00, 0x00, 0x3f, 0x60, 0xcf, 0xdb, 0xd3, 0xdd, 0xc3, 0x7e, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xff, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x18},
|
||||
{0x00, 0x00, 0xfe, 0xc7, 0xc3, 0xc3, 0xc7, 0xfe, 0xc7, 0xc3, 0xc3, 0xc7, 0xfe},
|
||||
{0x00, 0x00, 0x7e, 0xe7, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xe7, 0x7e},
|
||||
{0x00, 0x00, 0xfc, 0xce, 0xc7, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc7, 0xce, 0xfc},
|
||||
{0x00, 0x00, 0xff, 0xc0, 0xc0, 0xc0, 0xc0, 0xfc, 0xc0, 0xc0, 0xc0, 0xc0, 0xff},
|
||||
{0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xfc, 0xc0, 0xc0, 0xc0, 0xff},
|
||||
{0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xcf, 0xc0, 0xc0, 0xc0, 0xc0, 0xe7, 0x7e},
|
||||
{0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xff, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3},
|
||||
{0x00, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e},
|
||||
{0x00, 0x00, 0x7c, 0xee, 0xc6, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06},
|
||||
{0x00, 0x00, 0xc3, 0xc6, 0xcc, 0xd8, 0xf0, 0xe0, 0xf0, 0xd8, 0xcc, 0xc6, 0xc3},
|
||||
{0x00, 0x00, 0xff, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0},
|
||||
{0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xdb, 0xff, 0xff, 0xe7, 0xc3},
|
||||
{0x00, 0x00, 0xc7, 0xc7, 0xcf, 0xcf, 0xdf, 0xdb, 0xfb, 0xf3, 0xf3, 0xe3, 0xe3},
|
||||
{0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xe7, 0x7e},
|
||||
{0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xfe, 0xc7, 0xc3, 0xc3, 0xc7, 0xfe},
|
||||
{0x00, 0x00, 0x3f, 0x6e, 0xdf, 0xdb, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x3c},
|
||||
{0x00, 0x00, 0xc3, 0xc6, 0xcc, 0xd8, 0xf0, 0xfe, 0xc7, 0xc3, 0xc3, 0xc7, 0xfe},
|
||||
{0x00, 0x00, 0x7e, 0xe7, 0x03, 0x03, 0x07, 0x7e, 0xe0, 0xc0, 0xc0, 0xe7, 0x7e},
|
||||
{0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff},
|
||||
{0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3},
|
||||
{0x00, 0x00, 0x18, 0x3c, 0x3c, 0x66, 0x66, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3},
|
||||
{0x00, 0x00, 0xc3, 0xe7, 0xff, 0xff, 0xdb, 0xdb, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3},
|
||||
{0x00, 0x00, 0xc3, 0x66, 0x66, 0x3c, 0x3c, 0x18, 0x3c, 0x3c, 0x66, 0x66, 0xc3},
|
||||
{0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x3c, 0x66, 0x66, 0xc3},
|
||||
{0x00, 0x00, 0xff, 0xc0, 0xc0, 0x60, 0x30, 0x7e, 0x0c, 0x06, 0x03, 0x03, 0xff},
|
||||
{0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3c},
|
||||
{0x00, 0x03, 0x03, 0x06, 0x06, 0x0c, 0x0c, 0x18, 0x18, 0x30, 0x30, 0x60, 0x60},
|
||||
{0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c},
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18},
|
||||
{0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x38, 0x30, 0x70},
|
||||
{0x00, 0x00, 0x7f, 0xc3, 0xc3, 0x7f, 0x03, 0xc3, 0x7e, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0xfe, 0xc3, 0xc3, 0xc3, 0xc3, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0},
|
||||
{0x00, 0x00, 0x7e, 0xc3, 0xc0, 0xc0, 0xc0, 0xc3, 0x7e, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x7f, 0xc3, 0xc3, 0xc3, 0xc3, 0x7f, 0x03, 0x03, 0x03, 0x03, 0x03},
|
||||
{0x00, 0x00, 0x7f, 0xc0, 0xc0, 0xfe, 0xc3, 0xc3, 0x7e, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x33, 0x1e},
|
||||
{0x7e, 0xc3, 0x03, 0x03, 0x7f, 0xc3, 0xc3, 0xc3, 0x7e, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0},
|
||||
{0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x18, 0x00},
|
||||
{0x38, 0x6c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00, 0x0c, 0x00},
|
||||
{0x00, 0x00, 0xc6, 0xcc, 0xf8, 0xf0, 0xd8, 0xcc, 0xc6, 0xc0, 0xc0, 0xc0, 0xc0},
|
||||
{0x00, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78},
|
||||
{0x00, 0x00, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xfe, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xfc, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
|
||||
{0xc0, 0xc0, 0xc0, 0xfe, 0xc3, 0xc3, 0xc3, 0xc3, 0xfe, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x03, 0x03, 0x03, 0x7f, 0xc3, 0xc3, 0xc3, 0xc3, 0x7f, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xe0, 0xfe, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0xfe, 0x03, 0x03, 0x7e, 0xc0, 0xc0, 0x7f, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x1c, 0x36, 0x30, 0x30, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x00},
|
||||
{0x00, 0x00, 0x7e, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x18, 0x3c, 0x3c, 0x66, 0x66, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0xc3, 0xe7, 0xff, 0xdb, 0xc3, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0xc3, 0x00, 0x00, 0x00, 0x00},
|
||||
{0xc0, 0x60, 0x60, 0x30, 0x18, 0x3c, 0x66, 0x66, 0xc3, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0xff, 0x60, 0x30, 0x18, 0x0c, 0x06, 0xff, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x0f, 0x18, 0x18, 0x18, 0x38, 0xf0, 0x38, 0x18, 0x18, 0x18, 0x0f},
|
||||
{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
|
||||
{0x00, 0x00, 0xf0, 0x18, 0x18, 0x18, 0x1c, 0x0f, 0x1c, 0x18, 0x18, 0x18, 0xf0},
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x8f, 0xf1, 0x60, 0x00, 0x00, 0x00}
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36},
|
||||
{0x00, 0x00, 0x00, 0x66, 0x66, 0xff, 0x66, 0x66, 0xff, 0x66, 0x66, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x18, 0x7e, 0xff, 0x1b, 0x1f, 0x7e, 0xf8, 0xd8, 0xff, 0x7e, 0x18},
|
||||
{0x00, 0x00, 0x0e, 0x1b, 0xdb, 0x6e, 0x30, 0x18, 0x0c, 0x76, 0xdb, 0xd8, 0x70},
|
||||
{0x00, 0x00, 0x7f, 0xc6, 0xcf, 0xd8, 0x70, 0x70, 0xd8, 0xcc, 0xcc, 0x6c, 0x38},
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x1c, 0x0c, 0x0e},
|
||||
{0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x18, 0x0c},
|
||||
{0x00, 0x00, 0x30, 0x18, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x30},
|
||||
{0x00, 0x00, 0x00, 0x00, 0x99, 0x5a, 0x3c, 0xff, 0x3c, 0x5a, 0x99, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0xff, 0xff, 0x18, 0x18, 0x18, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x30, 0x18, 0x1c, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x60, 0x60, 0x30, 0x30, 0x18, 0x18, 0x0c, 0x0c, 0x06, 0x06, 0x03, 0x03},
|
||||
{0x00, 0x00, 0x3c, 0x66, 0xc3, 0xe3, 0xf3, 0xdb, 0xcf, 0xc7, 0xc3, 0x66, 0x3c},
|
||||
{0x00, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78, 0x38, 0x18},
|
||||
{0x00, 0x00, 0xff, 0xc0, 0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x03, 0xe7, 0x7e},
|
||||
{0x00, 0x00, 0x7e, 0xe7, 0x03, 0x03, 0x07, 0x7e, 0x07, 0x03, 0x03, 0xe7, 0x7e},
|
||||
{0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xff, 0xcc, 0x6c, 0x3c, 0x1c, 0x0c},
|
||||
{0x00, 0x00, 0x7e, 0xe7, 0x03, 0x03, 0x07, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0, 0xff},
|
||||
{0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xc7, 0xfe, 0xc0, 0xc0, 0xc0, 0xe7, 0x7e},
|
||||
{0x00, 0x00, 0x30, 0x30, 0x30, 0x30, 0x18, 0x0c, 0x06, 0x03, 0x03, 0x03, 0xff},
|
||||
{0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xe7, 0x7e, 0xe7, 0xc3, 0xc3, 0xe7, 0x7e},
|
||||
{0x00, 0x00, 0x7e, 0xe7, 0x03, 0x03, 0x03, 0x7f, 0xe7, 0xc3, 0xc3, 0xe7, 0x7e},
|
||||
{0x00, 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x30, 0x18, 0x1c, 0x1c, 0x00, 0x00, 0x1c, 0x1c, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06},
|
||||
{0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x03, 0x06, 0x0c, 0x18, 0x30, 0x60},
|
||||
{0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x18, 0x0c, 0x06, 0x03, 0xc3, 0xc3, 0x7e},
|
||||
{0x00, 0x00, 0x3f, 0x60, 0xcf, 0xdb, 0xd3, 0xdd, 0xc3, 0x7e, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xff, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x18},
|
||||
{0x00, 0x00, 0xfe, 0xc7, 0xc3, 0xc3, 0xc7, 0xfe, 0xc7, 0xc3, 0xc3, 0xc7, 0xfe},
|
||||
{0x00, 0x00, 0x7e, 0xe7, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xe7, 0x7e},
|
||||
{0x00, 0x00, 0xfc, 0xce, 0xc7, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc7, 0xce, 0xfc},
|
||||
{0x00, 0x00, 0xff, 0xc0, 0xc0, 0xc0, 0xc0, 0xfc, 0xc0, 0xc0, 0xc0, 0xc0, 0xff},
|
||||
{0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xfc, 0xc0, 0xc0, 0xc0, 0xff},
|
||||
{0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xcf, 0xc0, 0xc0, 0xc0, 0xc0, 0xe7, 0x7e},
|
||||
{0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xff, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3},
|
||||
{0x00, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e},
|
||||
{0x00, 0x00, 0x7c, 0xee, 0xc6, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06},
|
||||
{0x00, 0x00, 0xc3, 0xc6, 0xcc, 0xd8, 0xf0, 0xe0, 0xf0, 0xd8, 0xcc, 0xc6, 0xc3},
|
||||
{0x00, 0x00, 0xff, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0},
|
||||
{0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xdb, 0xff, 0xff, 0xe7, 0xc3},
|
||||
{0x00, 0x00, 0xc7, 0xc7, 0xcf, 0xcf, 0xdf, 0xdb, 0xfb, 0xf3, 0xf3, 0xe3, 0xe3},
|
||||
{0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xe7, 0x7e},
|
||||
{0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xfe, 0xc7, 0xc3, 0xc3, 0xc7, 0xfe},
|
||||
{0x00, 0x00, 0x3f, 0x6e, 0xdf, 0xdb, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x3c},
|
||||
{0x00, 0x00, 0xc3, 0xc6, 0xcc, 0xd8, 0xf0, 0xfe, 0xc7, 0xc3, 0xc3, 0xc7, 0xfe},
|
||||
{0x00, 0x00, 0x7e, 0xe7, 0x03, 0x03, 0x07, 0x7e, 0xe0, 0xc0, 0xc0, 0xe7, 0x7e},
|
||||
{0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff},
|
||||
{0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3},
|
||||
{0x00, 0x00, 0x18, 0x3c, 0x3c, 0x66, 0x66, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3},
|
||||
{0x00, 0x00, 0xc3, 0xe7, 0xff, 0xff, 0xdb, 0xdb, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3},
|
||||
{0x00, 0x00, 0xc3, 0x66, 0x66, 0x3c, 0x3c, 0x18, 0x3c, 0x3c, 0x66, 0x66, 0xc3},
|
||||
{0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x3c, 0x66, 0x66, 0xc3},
|
||||
{0x00, 0x00, 0xff, 0xc0, 0xc0, 0x60, 0x30, 0x7e, 0x0c, 0x06, 0x03, 0x03, 0xff},
|
||||
{0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3c},
|
||||
{0x00, 0x03, 0x03, 0x06, 0x06, 0x0c, 0x0c, 0x18, 0x18, 0x30, 0x30, 0x60, 0x60},
|
||||
{0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c},
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18},
|
||||
{0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x38, 0x30, 0x70},
|
||||
{0x00, 0x00, 0x7f, 0xc3, 0xc3, 0x7f, 0x03, 0xc3, 0x7e, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0xfe, 0xc3, 0xc3, 0xc3, 0xc3, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0},
|
||||
{0x00, 0x00, 0x7e, 0xc3, 0xc0, 0xc0, 0xc0, 0xc3, 0x7e, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x7f, 0xc3, 0xc3, 0xc3, 0xc3, 0x7f, 0x03, 0x03, 0x03, 0x03, 0x03},
|
||||
{0x00, 0x00, 0x7f, 0xc0, 0xc0, 0xfe, 0xc3, 0xc3, 0x7e, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x33, 0x1e},
|
||||
{0x7e, 0xc3, 0x03, 0x03, 0x7f, 0xc3, 0xc3, 0xc3, 0x7e, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0},
|
||||
{0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x18, 0x00},
|
||||
{0x38, 0x6c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00, 0x0c, 0x00},
|
||||
{0x00, 0x00, 0xc6, 0xcc, 0xf8, 0xf0, 0xd8, 0xcc, 0xc6, 0xc0, 0xc0, 0xc0, 0xc0},
|
||||
{0x00, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78},
|
||||
{0x00, 0x00, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xfe, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xfc, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
|
||||
{0xc0, 0xc0, 0xc0, 0xfe, 0xc3, 0xc3, 0xc3, 0xc3, 0xfe, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x03, 0x03, 0x03, 0x7f, 0xc3, 0xc3, 0xc3, 0xc3, 0x7f, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xe0, 0xfe, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0xfe, 0x03, 0x03, 0x7e, 0xc0, 0xc0, 0x7f, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x1c, 0x36, 0x30, 0x30, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x00},
|
||||
{0x00, 0x00, 0x7e, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x18, 0x3c, 0x3c, 0x66, 0x66, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0xc3, 0xe7, 0xff, 0xdb, 0xc3, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0xc3, 0x00, 0x00, 0x00, 0x00},
|
||||
{0xc0, 0x60, 0x60, 0x30, 0x18, 0x3c, 0x66, 0x66, 0xc3, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0xff, 0x60, 0x30, 0x18, 0x0c, 0x06, 0xff, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x0f, 0x18, 0x18, 0x18, 0x38, 0xf0, 0x38, 0x18, 0x18, 0x18, 0x0f},
|
||||
{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
|
||||
{0x00, 0x00, 0xf0, 0x18, 0x18, 0x18, 0x1c, 0x0f, 0x1c, 0x18, 0x18, 0x18, 0xf0},
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x8f, 0xf1, 0x60, 0x00, 0x00, 0x00}
|
||||
};
|
||||
|
||||
RasterFont::RasterFont()
|
||||
{
|
||||
// set GL modes
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
|
||||
// create the raster font
|
||||
fontOffset = glGenLists(128);
|
||||
for (int i = 32; i < 127; i++) {
|
||||
for (int i = 32; i < 127; i++)
|
||||
{
|
||||
glNewList(i + fontOffset, GL_COMPILE);
|
||||
glBitmap(8, 13, 0.0f, 2.0f, 10.0f, 0.0f, rasters[i - 32]);
|
||||
glEndList();
|
||||
|
@ -153,7 +155,8 @@ void RasterFont::printString(const char *s, double x, double y, double z)
|
|||
char *s2 = temp_buffer;
|
||||
memcpy(s2, s, length);
|
||||
s2[length] = 0;
|
||||
for (int i = 0; i < length; i++) {
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
if (s2[i] < 32 || s2[i] > 126)
|
||||
s2[i] = '!';
|
||||
}
|
||||
|
@ -209,7 +212,9 @@ void RasterFont::printMultilineText(const char *text, double start_x, double sta
|
|||
*t++ = ' ';
|
||||
}
|
||||
else
|
||||
{
|
||||
*t++ = *text;
|
||||
}
|
||||
|
||||
text++;
|
||||
}
|
||||
|
|
|
@ -12,30 +12,31 @@
|
|||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// Official Git repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _RASTERFONT_H_
|
||||
#define _RASTERFONT_H_
|
||||
|
||||
class RasterFont {
|
||||
class RasterFont
|
||||
{
|
||||
public:
|
||||
RasterFont();
|
||||
~RasterFont(void);
|
||||
static int debug;
|
||||
|
||||
// some useful constants
|
||||
enum {char_width = 10};
|
||||
enum {char_height = 15};
|
||||
|
||||
// and the happy helper functions
|
||||
void printString(const char *s, double x, double y, double z=0.0);
|
||||
void printCenteredString(const char *s, double y, int screen_width, double z=0.0);
|
||||
RasterFont();
|
||||
~RasterFont(void);
|
||||
static int debug;
|
||||
|
||||
// some useful constants
|
||||
enum {char_width = 10};
|
||||
enum {char_height = 15};
|
||||
|
||||
// and the happy helper functions
|
||||
void printString(const char *s, double x, double y, double z=0.0);
|
||||
void printCenteredString(const char *s, double y, int screen_width, double z=0.0);
|
||||
|
||||
void printMultilineText(const char *text, double x, double y, double z, int bbWidth, int bbHeight);
|
||||
private:
|
||||
int fontOffset;
|
||||
char *temp_buffer;
|
||||
int fontOffset;
|
||||
char *temp_buffer;
|
||||
enum {TEMP_BUFFER_SIZE = 64 * 1024};
|
||||
};
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// Official Git repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "Common.h"
|
||||
|
@ -97,34 +97,34 @@ void Init()
|
|||
|
||||
inline int iround(float x)
|
||||
{
|
||||
int t;
|
||||
int t;
|
||||
|
||||
#if defined(_WIN32) && !defined(_M_X64)
|
||||
__asm
|
||||
{
|
||||
fld x
|
||||
fistp t
|
||||
}
|
||||
__asm
|
||||
{
|
||||
fld x
|
||||
fistp t
|
||||
}
|
||||
#else
|
||||
t = (int)x;
|
||||
if((x - t) >= 0.5)
|
||||
return t + 1;
|
||||
#endif
|
||||
|
||||
return t;
|
||||
return t;
|
||||
}
|
||||
|
||||
void SetScissor()
|
||||
{
|
||||
int xoff = bpmem.scissorOffset.x * 2 - 342;
|
||||
int yoff = bpmem.scissorOffset.y * 2 - 342;
|
||||
int xoff = bpmem.scissorOffset.x * 2 - 342;
|
||||
int yoff = bpmem.scissorOffset.y * 2 - 342;
|
||||
|
||||
scissorLeft = bpmem.scissorTL.x - xoff - 342;
|
||||
if (scissorLeft < 0) scissorLeft = 0;
|
||||
|
||||
scissorTop = bpmem.scissorTL.y - yoff - 342;
|
||||
if (scissorTop < 0) scissorTop = 0;
|
||||
|
||||
|
||||
scissorRight = bpmem.scissorBR.x - xoff - 341;
|
||||
if (scissorRight > EFB_WIDTH) scissorRight = EFB_WIDTH;
|
||||
|
||||
|
@ -134,12 +134,12 @@ void SetScissor()
|
|||
|
||||
void SetTevReg(int reg, int comp, bool konst, s16 color)
|
||||
{
|
||||
tev.SetRegColor(reg, comp, konst, color);
|
||||
tev.SetRegColor(reg, comp, konst, color);
|
||||
}
|
||||
|
||||
inline void Draw(s32 x, s32 y, s32 xi, s32 yi)
|
||||
{
|
||||
INCSTAT(swstats.thisFrame.rasterizedPixels);
|
||||
INCSTAT(swstats.thisFrame.rasterizedPixels);
|
||||
|
||||
float dx = vertexOffsetX + (float)(x - vertex0X);
|
||||
float dy = vertexOffsetY + (float)(y - vertex0Y);
|
||||
|
@ -200,14 +200,14 @@ inline void Draw(s32 x, s32 y, s32 xi, s32 yi)
|
|||
tev.TextureLod[i] = rasterBlock.TextureLod[i];
|
||||
tev.TextureLinear[i] = rasterBlock.TextureLinear[i];
|
||||
}
|
||||
|
||||
tev.Draw();
|
||||
|
||||
tev.Draw();
|
||||
}
|
||||
|
||||
void InitTriangle(float X1, float Y1, s32 xi, s32 yi)
|
||||
{
|
||||
vertex0X = xi;
|
||||
vertex0Y = yi;
|
||||
vertex0Y = yi;
|
||||
|
||||
// adjust a little less than 0.5
|
||||
const float adjust = 0.495f;
|
||||
|
@ -219,13 +219,13 @@ void InitTriangle(float X1, float Y1, s32 xi, s32 yi)
|
|||
void InitSlope(Slope *slope, float f1, float f2, float f3, float DX31, float DX12, float DY12, float DY31)
|
||||
{
|
||||
float DF31 = f3 - f1;
|
||||
float DF21 = f2 - f1;
|
||||
float a = DF31 * -DY12 - DF21 * DY31;
|
||||
float b = DX31 * DF21 + DX12 * DF31;
|
||||
float c = -DX12 * DY31 - DX31 * -DY12;
|
||||
slope->dfdx = -a / c;
|
||||
slope->dfdy = -b / c;
|
||||
slope->f0 = f1;
|
||||
float DF21 = f2 - f1;
|
||||
float a = DF31 * -DY12 - DF21 * DY31;
|
||||
float b = DX31 * DF21 + DX12 * DF31;
|
||||
float c = -DX12 * DY31 - DX31 * -DY12;
|
||||
slope->dfdx = -a / c;
|
||||
slope->dfdy = -b / c;
|
||||
slope->f0 = f1;
|
||||
}
|
||||
|
||||
inline void CalculateLOD(s32 &lod, bool &linear, u32 texmap, u32 texcoord)
|
||||
|
@ -332,17 +332,17 @@ void BuildBlock(s32 blockX, s32 blockY)
|
|||
|
||||
void DrawTriangleFrontFace(OutputVertexData *v0, OutputVertexData *v1, OutputVertexData *v2)
|
||||
{
|
||||
INCSTAT(swstats.thisFrame.numTrianglesDrawn);
|
||||
INCSTAT(swstats.thisFrame.numTrianglesDrawn);
|
||||
|
||||
if (g_SWVideoConfig.bHwRasterizer)
|
||||
{
|
||||
HwRasterizer::DrawTriangleFrontFace(v0, v1, v2);
|
||||
return;
|
||||
}
|
||||
if (g_SWVideoConfig.bHwRasterizer)
|
||||
{
|
||||
HwRasterizer::DrawTriangleFrontFace(v0, v1, v2);
|
||||
return;
|
||||
}
|
||||
|
||||
// adapted from http://www.devmaster.net/forums/showthread.php?t=1884
|
||||
// adapted from http://www.devmaster.net/forums/showthread.php?t=1884
|
||||
|
||||
// 28.4 fixed-pou32 coordinates. rounded to nearest and adjusted to match hardware output
|
||||
// 28.4 fixed-pou32 coordinates. rounded to nearest and adjusted to match hardware output
|
||||
// could also take floor and adjust -8
|
||||
const s32 Y1 = iround(16.0f * v0->screenPosition[1]) - 9;
|
||||
const s32 Y2 = iround(16.0f * v1->screenPosition[1]) - 9;
|
||||
|
@ -352,161 +352,160 @@ void DrawTriangleFrontFace(OutputVertexData *v0, OutputVertexData *v1, OutputVer
|
|||
const s32 X2 = iround(16.0f * v1->screenPosition[0]) - 9;
|
||||
const s32 X3 = iround(16.0f * v2->screenPosition[0]) - 9;
|
||||
|
||||
// Deltas
|
||||
const s32 DX12 = X1 - X2;
|
||||
const s32 DX23 = X2 - X3;
|
||||
const s32 DX31 = X3 - X1;
|
||||
// Deltas
|
||||
const s32 DX12 = X1 - X2;
|
||||
const s32 DX23 = X2 - X3;
|
||||
const s32 DX31 = X3 - X1;
|
||||
|
||||
const s32 DY12 = Y1 - Y2;
|
||||
const s32 DY23 = Y2 - Y3;
|
||||
const s32 DY31 = Y3 - Y1;
|
||||
const s32 DY12 = Y1 - Y2;
|
||||
const s32 DY23 = Y2 - Y3;
|
||||
const s32 DY31 = Y3 - Y1;
|
||||
|
||||
// Fixed-pos32 deltas
|
||||
const s32 FDX12 = DX12 << 4;
|
||||
const s32 FDX23 = DX23 << 4;
|
||||
const s32 FDX31 = DX31 << 4;
|
||||
// Fixed-pos32 deltas
|
||||
const s32 FDX12 = DX12 << 4;
|
||||
const s32 FDX23 = DX23 << 4;
|
||||
const s32 FDX31 = DX31 << 4;
|
||||
|
||||
const s32 FDY12 = DY12 << 4;
|
||||
const s32 FDY23 = DY23 << 4;
|
||||
const s32 FDY31 = DY31 << 4;
|
||||
const s32 FDY12 = DY12 << 4;
|
||||
const s32 FDY23 = DY23 << 4;
|
||||
const s32 FDY31 = DY31 << 4;
|
||||
|
||||
// Bounding rectangle
|
||||
s32 minx = (min(min(X1, X2), X3) + 0xF) >> 4;
|
||||
s32 maxx = (max(max(X1, X2), X3) + 0xF) >> 4;
|
||||
s32 miny = (min(min(Y1, Y2), Y3) + 0xF) >> 4;
|
||||
s32 maxy = (max(max(Y1, Y2), Y3) + 0xF) >> 4;
|
||||
// Bounding rectangle
|
||||
s32 minx = (min(min(X1, X2), X3) + 0xF) >> 4;
|
||||
s32 maxx = (max(max(X1, X2), X3) + 0xF) >> 4;
|
||||
s32 miny = (min(min(Y1, Y2), Y3) + 0xF) >> 4;
|
||||
s32 maxy = (max(max(Y1, Y2), Y3) + 0xF) >> 4;
|
||||
|
||||
// scissor
|
||||
minx = max(minx, scissorLeft);
|
||||
maxx = min(maxx, scissorRight);
|
||||
miny = max(miny, scissorTop);
|
||||
maxy = min(maxy, scissorBottom);
|
||||
// scissor
|
||||
minx = max(minx, scissorLeft);
|
||||
maxx = min(maxx, scissorRight);
|
||||
miny = max(miny, scissorTop);
|
||||
maxy = min(maxy, scissorBottom);
|
||||
|
||||
if (minx >= maxx || miny >= maxy)
|
||||
return;
|
||||
if (minx >= maxx || miny >= maxy)
|
||||
return;
|
||||
|
||||
// Setup slopes
|
||||
float fltx1 = v0->screenPosition.x;
|
||||
float flty1 = v0->screenPosition.y;
|
||||
float fltdx31 = v2->screenPosition.x - fltx1;
|
||||
float fltdx12 = fltx1 - v1->screenPosition.x;
|
||||
float fltdy12 = flty1 - v1->screenPosition.y;
|
||||
float fltdy31 = v2->screenPosition.y - flty1;
|
||||
// Setup slopes
|
||||
float fltx1 = v0->screenPosition.x;
|
||||
float flty1 = v0->screenPosition.y;
|
||||
float fltdx31 = v2->screenPosition.x - fltx1;
|
||||
float fltdx12 = fltx1 - v1->screenPosition.x;
|
||||
float fltdy12 = flty1 - v1->screenPosition.y;
|
||||
float fltdy31 = v2->screenPosition.y - flty1;
|
||||
|
||||
InitTriangle(fltx1, flty1, (X1 + 0xF) >> 4, (Y1 + 0xF) >> 4);
|
||||
|
||||
float w[3] = { 1.0f / v0->projectedPosition.w, 1.0f / v1->projectedPosition.w, 1.0f / v2->projectedPosition.w };
|
||||
InitSlope(&WSlope, w[0], w[1], w[2], fltdx31, fltdx12, fltdy12, fltdy31);
|
||||
float w[3] = { 1.0f / v0->projectedPosition.w, 1.0f / v1->projectedPosition.w, 1.0f / v2->projectedPosition.w };
|
||||
InitSlope(&WSlope, w[0], w[1], w[2], fltdx31, fltdx12, fltdy12, fltdy31);
|
||||
|
||||
if (!bpmem.genMode.zfreeze || !g_SWVideoConfig.bZFreeze)
|
||||
InitSlope(&ZSlope, v0->screenPosition[2], v1->screenPosition[2], v2->screenPosition[2], fltdx31, fltdx12, fltdy12, fltdy31);
|
||||
InitSlope(&ZSlope, v0->screenPosition[2], v1->screenPosition[2], v2->screenPosition[2], fltdx31, fltdx12, fltdy12, fltdy31);
|
||||
|
||||
for(unsigned int i = 0; i < bpmem.genMode.numcolchans; i++)
|
||||
{
|
||||
for(int comp = 0; comp < 4; comp++)
|
||||
InitSlope(&ColorSlopes[i][comp], v0->color[i][comp], v1->color[i][comp], v2->color[i][comp], fltdx31, fltdx12, fltdy12, fltdy31);
|
||||
}
|
||||
for(unsigned int i = 0; i < bpmem.genMode.numcolchans; i++)
|
||||
{
|
||||
for(int comp = 0; comp < 4; comp++)
|
||||
InitSlope(&ColorSlopes[i][comp], v0->color[i][comp], v1->color[i][comp], v2->color[i][comp], fltdx31, fltdx12, fltdy12, fltdy31);
|
||||
}
|
||||
|
||||
for(unsigned int i = 0; i < bpmem.genMode.numtexgens; i++)
|
||||
{
|
||||
for(int comp = 0; comp < 3; comp++)
|
||||
InitSlope(&TexSlopes[i][comp], v0->texCoords[i][comp] * w[0], v1->texCoords[i][comp] * w[1], v2->texCoords[i][comp] * w[2], fltdx31, fltdx12, fltdy12, fltdy31);
|
||||
}
|
||||
for(unsigned int i = 0; i < bpmem.genMode.numtexgens; i++)
|
||||
{
|
||||
for(int comp = 0; comp < 3; comp++)
|
||||
InitSlope(&TexSlopes[i][comp], v0->texCoords[i][comp] * w[0], v1->texCoords[i][comp] * w[1], v2->texCoords[i][comp] * w[2], fltdx31, fltdx12, fltdy12, fltdy31);
|
||||
}
|
||||
|
||||
// Start in corner of 8x8 block
|
||||
minx &= ~(BLOCK_SIZE - 1);
|
||||
miny &= ~(BLOCK_SIZE - 1);
|
||||
|
||||
// Half-edge constants
|
||||
s32 C1 = DY12 * X1 - DX12 * Y1;
|
||||
s32 C2 = DY23 * X2 - DX23 * Y2;
|
||||
s32 C3 = DY31 * X3 - DX31 * Y3;
|
||||
// Start in corner of 8x8 block
|
||||
minx &= ~(BLOCK_SIZE - 1);
|
||||
miny &= ~(BLOCK_SIZE - 1);
|
||||
|
||||
// Correct for fill convention
|
||||
if(DY12 < 0 || (DY12 == 0 && DX12 > 0)) C1++;
|
||||
if(DY23 < 0 || (DY23 == 0 && DX23 > 0)) C2++;
|
||||
if(DY31 < 0 || (DY31 == 0 && DX31 > 0)) C3++;
|
||||
// Half-edge constants
|
||||
s32 C1 = DY12 * X1 - DX12 * Y1;
|
||||
s32 C2 = DY23 * X2 - DX23 * Y2;
|
||||
s32 C3 = DY31 * X3 - DX31 * Y3;
|
||||
|
||||
// Loop through blocks
|
||||
for(s32 y = miny; y < maxy; y += BLOCK_SIZE)
|
||||
{
|
||||
for(s32 x = minx; x < maxx; x += BLOCK_SIZE)
|
||||
{
|
||||
// Corners of block
|
||||
s32 x0 = x << 4;
|
||||
s32 x1 = (x + BLOCK_SIZE - 1) << 4;
|
||||
s32 y0 = y << 4;
|
||||
s32 y1 = (y + BLOCK_SIZE - 1) << 4;
|
||||
// Correct for fill convention
|
||||
if(DY12 < 0 || (DY12 == 0 && DX12 > 0)) C1++;
|
||||
if(DY23 < 0 || (DY23 == 0 && DX23 > 0)) C2++;
|
||||
if(DY31 < 0 || (DY31 == 0 && DX31 > 0)) C3++;
|
||||
|
||||
// Evaluate half-space functions
|
||||
bool a00 = C1 + DX12 * y0 - DY12 * x0 > 0;
|
||||
bool a10 = C1 + DX12 * y0 - DY12 * x1 > 0;
|
||||
bool a01 = C1 + DX12 * y1 - DY12 * x0 > 0;
|
||||
bool a11 = C1 + DX12 * y1 - DY12 * x1 > 0;
|
||||
int a = (a00 << 0) | (a10 << 1) | (a01 << 2) | (a11 << 3);
|
||||
|
||||
bool b00 = C2 + DX23 * y0 - DY23 * x0 > 0;
|
||||
bool b10 = C2 + DX23 * y0 - DY23 * x1 > 0;
|
||||
bool b01 = C2 + DX23 * y1 - DY23 * x0 > 0;
|
||||
bool b11 = C2 + DX23 * y1 - DY23 * x1 > 0;
|
||||
int b = (b00 << 0) | (b10 << 1) | (b01 << 2) | (b11 << 3);
|
||||
|
||||
bool c00 = C3 + DX31 * y0 - DY31 * x0 > 0;
|
||||
bool c10 = C3 + DX31 * y0 - DY31 * x1 > 0;
|
||||
bool c01 = C3 + DX31 * y1 - DY31 * x0 > 0;
|
||||
bool c11 = C3 + DX31 * y1 - DY31 * x1 > 0;
|
||||
int c = (c00 << 0) | (c10 << 1) | (c01 << 2) | (c11 << 3);
|
||||
// Loop through blocks
|
||||
for(s32 y = miny; y < maxy; y += BLOCK_SIZE)
|
||||
{
|
||||
for(s32 x = minx; x < maxx; x += BLOCK_SIZE)
|
||||
{
|
||||
// Corners of block
|
||||
s32 x0 = x << 4;
|
||||
s32 x1 = (x + BLOCK_SIZE - 1) << 4;
|
||||
s32 y0 = y << 4;
|
||||
s32 y1 = (y + BLOCK_SIZE - 1) << 4;
|
||||
|
||||
// Skip block when outside an edge
|
||||
if(a == 0x0 || b == 0x0 || c == 0x0) continue;
|
||||
// Evaluate half-space functions
|
||||
bool a00 = C1 + DX12 * y0 - DY12 * x0 > 0;
|
||||
bool a10 = C1 + DX12 * y0 - DY12 * x1 > 0;
|
||||
bool a01 = C1 + DX12 * y1 - DY12 * x0 > 0;
|
||||
bool a11 = C1 + DX12 * y1 - DY12 * x1 > 0;
|
||||
int a = (a00 << 0) | (a10 << 1) | (a01 << 2) | (a11 << 3);
|
||||
|
||||
bool b00 = C2 + DX23 * y0 - DY23 * x0 > 0;
|
||||
bool b10 = C2 + DX23 * y0 - DY23 * x1 > 0;
|
||||
bool b01 = C2 + DX23 * y1 - DY23 * x0 > 0;
|
||||
bool b11 = C2 + DX23 * y1 - DY23 * x1 > 0;
|
||||
int b = (b00 << 0) | (b10 << 1) | (b01 << 2) | (b11 << 3);
|
||||
|
||||
bool c00 = C3 + DX31 * y0 - DY31 * x0 > 0;
|
||||
bool c10 = C3 + DX31 * y0 - DY31 * x1 > 0;
|
||||
bool c01 = C3 + DX31 * y1 - DY31 * x0 > 0;
|
||||
bool c11 = C3 + DX31 * y1 - DY31 * x1 > 0;
|
||||
int c = (c00 << 0) | (c10 << 1) | (c01 << 2) | (c11 << 3);
|
||||
|
||||
// Skip block when outside an edge
|
||||
if(a == 0x0 || b == 0x0 || c == 0x0)
|
||||
continue;
|
||||
|
||||
BuildBlock(x, y);
|
||||
|
||||
// Accept whole block when totally covered
|
||||
if(a == 0xF && b == 0xF && c == 0xF)
|
||||
{
|
||||
for(s32 iy = 0; iy < BLOCK_SIZE; iy++)
|
||||
{
|
||||
for(s32 ix = 0; ix < BLOCK_SIZE; ix++)
|
||||
{
|
||||
Draw(x + ix, y + iy, ix, iy);
|
||||
}
|
||||
}
|
||||
}
|
||||
else // Partially covered block
|
||||
{
|
||||
s32 CY1 = C1 + DX12 * y0 - DY12 * x0;
|
||||
s32 CY2 = C2 + DX23 * y0 - DY23 * x0;
|
||||
s32 CY3 = C3 + DX31 * y0 - DY31 * x0;
|
||||
// Accept whole block when totally covered
|
||||
if(a == 0xF && b == 0xF && c == 0xF)
|
||||
{
|
||||
for(s32 iy = 0; iy < BLOCK_SIZE; iy++)
|
||||
{
|
||||
for(s32 ix = 0; ix < BLOCK_SIZE; ix++)
|
||||
{
|
||||
Draw(x + ix, y + iy, ix, iy);
|
||||
}
|
||||
}
|
||||
}
|
||||
else // Partially covered block
|
||||
{
|
||||
s32 CY1 = C1 + DX12 * y0 - DY12 * x0;
|
||||
s32 CY2 = C2 + DX23 * y0 - DY23 * x0;
|
||||
s32 CY3 = C3 + DX31 * y0 - DY31 * x0;
|
||||
|
||||
for(s32 iy = 0; iy < BLOCK_SIZE; iy++)
|
||||
{
|
||||
s32 CX1 = CY1;
|
||||
s32 CX2 = CY2;
|
||||
s32 CX3 = CY3;
|
||||
for(s32 iy = 0; iy < BLOCK_SIZE; iy++)
|
||||
{
|
||||
s32 CX1 = CY1;
|
||||
s32 CX2 = CY2;
|
||||
s32 CX3 = CY3;
|
||||
|
||||
for(s32 ix = 0; ix < BLOCK_SIZE; ix++)
|
||||
{
|
||||
if(CX1 > 0 && CX2 > 0 && CX3 > 0)
|
||||
{
|
||||
Draw(x + ix, y + iy, ix, iy);
|
||||
}
|
||||
for(s32 ix = 0; ix < BLOCK_SIZE; ix++)
|
||||
{
|
||||
if(CX1 > 0 && CX2 > 0 && CX3 > 0)
|
||||
{
|
||||
Draw(x + ix, y + iy, ix, iy);
|
||||
}
|
||||
|
||||
CX1 -= FDY12;
|
||||
CX2 -= FDY23;
|
||||
CX3 -= FDY31;
|
||||
}
|
||||
|
||||
CY1 += FDX12;
|
||||
CY2 += FDX23;
|
||||
CY3 += FDX31;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
CX1 -= FDY12;
|
||||
CX2 -= FDY23;
|
||||
CX3 -= FDY31;
|
||||
}
|
||||
|
||||
CY1 += FDX12;
|
||||
CY2 += FDX23;
|
||||
CY3 += FDX31;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// Official Git repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _RASTERIZER_H_
|
||||
|
@ -23,19 +23,19 @@
|
|||
|
||||
namespace Rasterizer
|
||||
{
|
||||
void Init();
|
||||
void Init();
|
||||
|
||||
void DrawTriangleFrontFace(OutputVertexData *v0, OutputVertexData *v1, OutputVertexData *v2);
|
||||
void DrawTriangleFrontFace(OutputVertexData *v0, OutputVertexData *v1, OutputVertexData *v2);
|
||||
|
||||
void SetScissor();
|
||||
void SetScissor();
|
||||
|
||||
void SetTevReg(int reg, int comp, bool konst, s16 color);
|
||||
void SetTevReg(int reg, int comp, bool konst, s16 color);
|
||||
|
||||
struct Slope
|
||||
{
|
||||
float dfdx;
|
||||
float dfdy;
|
||||
float f0;
|
||||
struct Slope
|
||||
{
|
||||
float dfdx;
|
||||
float dfdy;
|
||||
float f0;
|
||||
|
||||
float GetValue(float dx, float dy) { return f0 + (dfdx * dx) + (dfdy * dy); }
|
||||
void DoState(PointerWrap &p)
|
||||
|
@ -44,7 +44,7 @@ namespace Rasterizer
|
|||
p.Do(dfdy);
|
||||
p.Do(f0);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
struct RasterBlockPixel
|
||||
{
|
||||
|
@ -62,7 +62,6 @@ namespace Rasterizer
|
|||
};
|
||||
|
||||
void DoState(PointerWrap &p);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// Official Git repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "Common.h"
|
||||
|
@ -37,7 +37,7 @@ namespace SWCommandProcessor
|
|||
enum
|
||||
{
|
||||
GATHER_PIPE_SIZE = 32,
|
||||
INT_CAUSE_CP = 0x800
|
||||
INT_CAUSE_CP = 0x800
|
||||
};
|
||||
|
||||
// STATE_TO_SAVE
|
||||
|
@ -83,17 +83,17 @@ void UpdateInterrupts_Wrapper(u64 userdata, int cyclesLate)
|
|||
|
||||
inline bool AtBreakpoint()
|
||||
{
|
||||
return cpreg.ctrl.BPEnable && (cpreg.readptr == cpreg.breakpt);
|
||||
return cpreg.ctrl.BPEnable && (cpreg.readptr == cpreg.breakpt);
|
||||
}
|
||||
|
||||
void Init()
|
||||
{
|
||||
cpreg.status.Hex = 0;
|
||||
cpreg.status.Hex = 0;
|
||||
cpreg.status.CommandIdle = 1;
|
||||
cpreg.status.ReadIdle = 1;
|
||||
|
||||
cpreg.ctrl.Hex = 0;
|
||||
cpreg.clear.Hex = 0;
|
||||
cpreg.ctrl.Hex = 0;
|
||||
cpreg.clear.Hex = 0;
|
||||
|
||||
cpreg.bboxleft = 0;
|
||||
cpreg.bboxtop = 0;
|
||||
|
@ -104,15 +104,15 @@ void Init()
|
|||
|
||||
et_UpdateInterrupts = CoreTiming::RegisterEvent("UpdateInterrupts", UpdateInterrupts_Wrapper);
|
||||
|
||||
// internal buffer position
|
||||
readPos = 0;
|
||||
writePos = 0;
|
||||
// internal buffer position
|
||||
readPos = 0;
|
||||
writePos = 0;
|
||||
|
||||
interruptSet = false;
|
||||
interruptWaiting = false;
|
||||
interruptSet = false;
|
||||
interruptWaiting = false;
|
||||
|
||||
g_pVideoData = 0;
|
||||
g_bSkipCurrentFrame = false;
|
||||
g_pVideoData = 0;
|
||||
g_bSkipCurrentFrame = false;
|
||||
}
|
||||
|
||||
void Shutdown()
|
||||
|
@ -121,31 +121,32 @@ void Shutdown()
|
|||
|
||||
void RunGpu()
|
||||
{
|
||||
if (!SConfig::GetInstance().m_LocalCoreStartupParameter.bCPUThread)
|
||||
{
|
||||
// We are going to do FP math on the main thread so have to save the current state
|
||||
FPURoundMode::SaveSIMDState();
|
||||
FPURoundMode::LoadDefaultSIMDState();
|
||||
|
||||
// run the opcode decoder
|
||||
do {
|
||||
RunBuffer();
|
||||
} while (cpreg.ctrl.GPReadEnable && !AtBreakpoint() && cpreg.readptr != cpreg.writeptr);
|
||||
if (!SConfig::GetInstance().m_LocalCoreStartupParameter.bCPUThread)
|
||||
{
|
||||
// We are going to do FP math on the main thread so have to save the current state
|
||||
FPURoundMode::SaveSIMDState();
|
||||
FPURoundMode::LoadDefaultSIMDState();
|
||||
|
||||
FPURoundMode::LoadSIMDState();
|
||||
}
|
||||
// run the opcode decoder
|
||||
do
|
||||
{
|
||||
RunBuffer();
|
||||
} while (cpreg.ctrl.GPReadEnable && !AtBreakpoint() && cpreg.readptr != cpreg.writeptr);
|
||||
|
||||
FPURoundMode::LoadSIMDState();
|
||||
}
|
||||
}
|
||||
|
||||
void Read16(u16& _rReturnValue, const u32 _Address)
|
||||
{
|
||||
u32 regAddr = (_Address & 0xFFF) >> 1;
|
||||
u32 regAddr = (_Address & 0xFFF) >> 1;
|
||||
|
||||
DEBUG_LOG(COMMANDPROCESSOR, "(r): 0x%08x : 0x%08x", _Address, ((u16*)&cpreg)[regAddr]);
|
||||
|
||||
if (regAddr < 0x20)
|
||||
_rReturnValue = ((u16*)&cpreg)[regAddr];
|
||||
else
|
||||
_rReturnValue = 0;
|
||||
DEBUG_LOG(COMMANDPROCESSOR, "(r): 0x%08x : 0x%08x", _Address, ((u16*)&cpreg)[regAddr]);
|
||||
|
||||
if (regAddr < 0x20)
|
||||
_rReturnValue = ((u16*)&cpreg)[regAddr];
|
||||
else
|
||||
_rReturnValue = 0;
|
||||
}
|
||||
|
||||
void Write16(const u16 _Value, const u32 _Address)
|
||||
|
@ -162,14 +163,14 @@ void Write16(const u16 _Value, const u32 _Address)
|
|||
|
||||
case CTRL_REGISTER:
|
||||
{
|
||||
cpreg.ctrl.Hex = _Value;
|
||||
cpreg.ctrl.Hex = _Value;
|
||||
|
||||
DEBUG_LOG(COMMANDPROCESSOR,"\t write to CTRL_REGISTER : %04x", _Value);
|
||||
DEBUG_LOG(COMMANDPROCESSOR, "\t GPREAD %s | CPULINK %s | BP %s || BPIntEnable %s | OvF %s | UndF %s"
|
||||
, cpreg.ctrl.GPReadEnable ? "ON" : "OFF"
|
||||
, cpreg.ctrl.GPLinkEnable ? "ON" : "OFF"
|
||||
, cpreg.ctrl.BPEnable ? "ON" : "OFF"
|
||||
, cpreg.ctrl.BreakPointIntEnable ? "ON" : "OFF"
|
||||
, cpreg.ctrl.GPReadEnable ? "ON" : "OFF"
|
||||
, cpreg.ctrl.GPLinkEnable ? "ON" : "OFF"
|
||||
, cpreg.ctrl.BPEnable ? "ON" : "OFF"
|
||||
, cpreg.ctrl.BreakPointIntEnable ? "ON" : "OFF"
|
||||
, cpreg.ctrl.FifoOverflowIntEnable ? "ON" : "OFF"
|
||||
, cpreg.ctrl.FifoUnderflowIntEnable ? "ON" : "OFF"
|
||||
);
|
||||
|
@ -178,14 +179,14 @@ void Write16(const u16 _Value, const u32 _Address)
|
|||
|
||||
case CLEAR_REGISTER:
|
||||
{
|
||||
UCPClearReg tmpClear(_Value);
|
||||
UCPClearReg tmpClear(_Value);
|
||||
|
||||
if (tmpClear.ClearFifoOverflow)
|
||||
cpreg.status.OverflowHiWatermark = 0;
|
||||
if (tmpClear.ClearFifoUnderflow)
|
||||
cpreg.status.UnderflowLoWatermark = 0;
|
||||
if (tmpClear.ClearFifoOverflow)
|
||||
cpreg.status.OverflowHiWatermark = 0;
|
||||
if (tmpClear.ClearFifoUnderflow)
|
||||
cpreg.status.UnderflowLoWatermark = 0;
|
||||
|
||||
INFO_LOG(COMMANDPROCESSOR,"\t write to CLEAR_REGISTER : %04x",_Value);
|
||||
INFO_LOG(COMMANDPROCESSOR,"\t write to CLEAR_REGISTER : %04x",_Value);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -195,77 +196,77 @@ void Write16(const u16 _Value, const u32 _Address)
|
|||
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_TOKEN_REGISTER : %04x", _Value);
|
||||
break;
|
||||
|
||||
case FIFO_BASE_LO:
|
||||
WriteLow ((u32 &)cpreg.fifobase, _Value & 0xFFE0);
|
||||
case FIFO_BASE_LO:
|
||||
WriteLow ((u32 &)cpreg.fifobase, _Value & 0xFFE0);
|
||||
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_BASE_LO. FIFO base is : %08x", cpreg.fifobase);
|
||||
break;
|
||||
case FIFO_BASE_HI:
|
||||
WriteHigh((u32 &)cpreg.fifobase, _Value);
|
||||
case FIFO_BASE_HI:
|
||||
WriteHigh((u32 &)cpreg.fifobase, _Value);
|
||||
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_BASE_HI. FIFO base is : %08x", cpreg.fifobase);
|
||||
break;
|
||||
case FIFO_END_LO:
|
||||
WriteLow ((u32 &)cpreg.fifoend, _Value & 0xFFE0);
|
||||
case FIFO_END_LO:
|
||||
WriteLow ((u32 &)cpreg.fifoend, _Value & 0xFFE0);
|
||||
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_END_LO. FIFO end is : %08x", cpreg.fifoend);
|
||||
break;
|
||||
case FIFO_END_HI:
|
||||
WriteHigh((u32 &)cpreg.fifoend, _Value);
|
||||
WriteHigh((u32 &)cpreg.fifoend, _Value);
|
||||
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_END_HI. FIFO end is : %08x", cpreg.fifoend);
|
||||
break;
|
||||
|
||||
case FIFO_WRITE_POINTER_LO:
|
||||
WriteLow ((u32 &)cpreg.writeptr, _Value & 0xFFE0);
|
||||
WriteLow ((u32 &)cpreg.writeptr, _Value & 0xFFE0);
|
||||
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_WRITE_POINTER_LO. write ptr is : %08x", cpreg.writeptr);
|
||||
break;
|
||||
case FIFO_WRITE_POINTER_HI:
|
||||
WriteHigh ((u32 &)cpreg.writeptr, _Value);
|
||||
WriteHigh ((u32 &)cpreg.writeptr, _Value);
|
||||
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_WRITE_POINTER_HI. write ptr is : %08x", cpreg.writeptr);
|
||||
break;
|
||||
case FIFO_READ_POINTER_LO:
|
||||
WriteLow ((u32 &)cpreg.readptr, _Value & 0xFFE0);
|
||||
WriteLow ((u32 &)cpreg.readptr, _Value & 0xFFE0);
|
||||
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_READ_POINTER_LO. read ptr is : %08x", cpreg.readptr);
|
||||
break;
|
||||
case FIFO_READ_POINTER_HI:
|
||||
WriteHigh ((u32 &)cpreg.readptr, _Value);
|
||||
WriteHigh ((u32 &)cpreg.readptr, _Value);
|
||||
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_READ_POINTER_HI. read ptr is : %08x", cpreg.readptr);
|
||||
break;
|
||||
|
||||
case FIFO_HI_WATERMARK_LO:
|
||||
WriteLow ((u32 &)cpreg.hiwatermark, _Value);
|
||||
case FIFO_HI_WATERMARK_LO:
|
||||
WriteLow ((u32 &)cpreg.hiwatermark, _Value);
|
||||
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_HI_WATERMARK_LO. hiwatermark is : %08x", cpreg.hiwatermark);
|
||||
break;
|
||||
case FIFO_HI_WATERMARK_HI:
|
||||
WriteHigh ((u32 &)cpreg.hiwatermark, _Value);
|
||||
WriteHigh ((u32 &)cpreg.hiwatermark, _Value);
|
||||
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_HI_WATERMARK_HI. hiwatermark is : %08x", cpreg.hiwatermark);
|
||||
break;
|
||||
case FIFO_LO_WATERMARK_LO:
|
||||
WriteLow ((u32 &)cpreg.lowatermark, _Value);
|
||||
WriteLow ((u32 &)cpreg.lowatermark, _Value);
|
||||
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_LO_WATERMARK_LO. lowatermark is : %08x", cpreg.lowatermark);
|
||||
break;
|
||||
case FIFO_LO_WATERMARK_HI:
|
||||
WriteHigh ((u32 &)cpreg.lowatermark, _Value);
|
||||
WriteHigh ((u32 &)cpreg.lowatermark, _Value);
|
||||
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_LO_WATERMARK_HI. lowatermark is : %08x", cpreg.lowatermark);
|
||||
break;
|
||||
|
||||
case FIFO_BP_LO:
|
||||
WriteLow ((u32 &)cpreg.breakpt, _Value & 0xFFE0);
|
||||
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_BP_LO. breakpt is : %08x", cpreg.breakpt);
|
||||
case FIFO_BP_LO:
|
||||
WriteLow ((u32 &)cpreg.breakpt, _Value & 0xFFE0);
|
||||
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_BP_LO. breakpoint is : %08x", cpreg.breakpt);
|
||||
break;
|
||||
case FIFO_BP_HI:
|
||||
WriteHigh ((u32 &)cpreg.breakpt, _Value);
|
||||
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_BP_HI. breakpt is : %08x", cpreg.breakpt);
|
||||
WriteHigh ((u32 &)cpreg.breakpt, _Value);
|
||||
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_BP_HI. breakpoint is : %08x", cpreg.breakpt);
|
||||
break;
|
||||
|
||||
case FIFO_RW_DISTANCE_LO:
|
||||
WriteLow ((u32 &)cpreg.rwdistance, _Value & 0xFFE0);
|
||||
case FIFO_RW_DISTANCE_LO:
|
||||
WriteLow ((u32 &)cpreg.rwdistance, _Value & 0xFFE0);
|
||||
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_RW_DISTANCE_LO. rwdistance is : %08x", cpreg.rwdistance);
|
||||
break;
|
||||
case FIFO_RW_DISTANCE_HI:
|
||||
WriteHigh ((u32 &)cpreg.rwdistance, _Value);
|
||||
WriteHigh ((u32 &)cpreg.rwdistance, _Value);
|
||||
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_RW_DISTANCE_HI. rwdistance is : %08x", cpreg.rwdistance);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
RunGpu();
|
||||
RunGpu();
|
||||
}
|
||||
|
||||
void Read32(u32& _rReturnValue, const u32 _Address)
|
||||
|
@ -282,35 +283,35 @@ void Write32(const u32 _Data, const u32 _Address)
|
|||
void STACKALIGN GatherPipeBursted()
|
||||
{
|
||||
if (cpreg.ctrl.GPLinkEnable)
|
||||
{
|
||||
DEBUG_LOG(COMMANDPROCESSOR,"\t WGP burst. write thru : %08x", cpreg.writeptr);
|
||||
{
|
||||
DEBUG_LOG(COMMANDPROCESSOR,"\t WGP burst. write thru : %08x", cpreg.writeptr);
|
||||
|
||||
if (cpreg.writeptr == cpreg.fifoend)
|
||||
cpreg.writeptr = cpreg.fifobase;
|
||||
else
|
||||
cpreg.writeptr += GATHER_PIPE_SIZE;
|
||||
if (cpreg.writeptr == cpreg.fifoend)
|
||||
cpreg.writeptr = cpreg.fifobase;
|
||||
else
|
||||
cpreg.writeptr += GATHER_PIPE_SIZE;
|
||||
|
||||
Common::AtomicAdd(cpreg.rwdistance, GATHER_PIPE_SIZE);
|
||||
}
|
||||
Common::AtomicAdd(cpreg.rwdistance, GATHER_PIPE_SIZE);
|
||||
}
|
||||
|
||||
RunGpu();
|
||||
RunGpu();
|
||||
}
|
||||
|
||||
void UpdateInterrupts(u64 userdata)
|
||||
{
|
||||
if (userdata)
|
||||
if (userdata)
|
||||
{
|
||||
interruptSet = true;
|
||||
INFO_LOG(COMMANDPROCESSOR,"Interrupt set");
|
||||
ProcessorInterface::SetInterrupt(INT_CAUSE_CP, true);
|
||||
INFO_LOG(COMMANDPROCESSOR,"Interrupt set");
|
||||
ProcessorInterface::SetInterrupt(INT_CAUSE_CP, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
interruptSet = false;
|
||||
interruptSet = false;
|
||||
INFO_LOG(COMMANDPROCESSOR,"Interrupt cleared");
|
||||
ProcessorInterface::SetInterrupt(INT_CAUSE_CP, false);
|
||||
ProcessorInterface::SetInterrupt(INT_CAUSE_CP, false);
|
||||
}
|
||||
interruptWaiting = false;
|
||||
interruptWaiting = false;
|
||||
}
|
||||
|
||||
void UpdateInterruptsFromVideoBackend(u64 userdata)
|
||||
|
@ -320,136 +321,138 @@ void UpdateInterruptsFromVideoBackend(u64 userdata)
|
|||
|
||||
void ReadFifo()
|
||||
{
|
||||
bool canRead = cpreg.readptr != cpreg.writeptr && writePos < (int)maxCommandBufferWrite;
|
||||
bool atBreakpoint = AtBreakpoint();
|
||||
bool canRead = cpreg.readptr != cpreg.writeptr && writePos < (int)maxCommandBufferWrite;
|
||||
bool atBreakpoint = AtBreakpoint();
|
||||
|
||||
if (canRead && !atBreakpoint)
|
||||
{
|
||||
// read from fifo
|
||||
u8 *ptr = Memory::GetPointer(cpreg.readptr);
|
||||
int bytesRead = 0;
|
||||
if (canRead && !atBreakpoint)
|
||||
{
|
||||
// read from fifo
|
||||
u8 *ptr = Memory::GetPointer(cpreg.readptr);
|
||||
int bytesRead = 0;
|
||||
|
||||
do
|
||||
{
|
||||
// copy to buffer
|
||||
memcpy(&commandBuffer[writePos], ptr, GATHER_PIPE_SIZE);
|
||||
writePos += GATHER_PIPE_SIZE;
|
||||
bytesRead += GATHER_PIPE_SIZE;
|
||||
do
|
||||
{
|
||||
// copy to buffer
|
||||
memcpy(&commandBuffer[writePos], ptr, GATHER_PIPE_SIZE);
|
||||
writePos += GATHER_PIPE_SIZE;
|
||||
bytesRead += GATHER_PIPE_SIZE;
|
||||
|
||||
if (cpreg.readptr == cpreg.fifoend)
|
||||
{
|
||||
cpreg.readptr = cpreg.fifobase;
|
||||
ptr = Memory::GetPointer(cpreg.readptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
cpreg.readptr += GATHER_PIPE_SIZE;
|
||||
ptr += GATHER_PIPE_SIZE;
|
||||
}
|
||||
if (cpreg.readptr == cpreg.fifoend)
|
||||
{
|
||||
cpreg.readptr = cpreg.fifobase;
|
||||
ptr = Memory::GetPointer(cpreg.readptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
cpreg.readptr += GATHER_PIPE_SIZE;
|
||||
ptr += GATHER_PIPE_SIZE;
|
||||
}
|
||||
|
||||
canRead = cpreg.readptr != cpreg.writeptr && writePos < (int)maxCommandBufferWrite;
|
||||
atBreakpoint = AtBreakpoint();
|
||||
} while (canRead && !atBreakpoint);
|
||||
canRead = cpreg.readptr != cpreg.writeptr && writePos < (int)maxCommandBufferWrite;
|
||||
atBreakpoint = AtBreakpoint();
|
||||
} while (canRead && !atBreakpoint);
|
||||
|
||||
Common::AtomicAdd(cpreg.rwdistance, -bytesRead);
|
||||
}
|
||||
Common::AtomicAdd(cpreg.rwdistance, -bytesRead);
|
||||
}
|
||||
}
|
||||
|
||||
void SetStatus()
|
||||
{
|
||||
// overflow check
|
||||
if (cpreg.rwdistance > cpreg.hiwatermark)
|
||||
cpreg.status.OverflowHiWatermark = 1;
|
||||
// overflow check
|
||||
if (cpreg.rwdistance > cpreg.hiwatermark)
|
||||
cpreg.status.OverflowHiWatermark = 1;
|
||||
|
||||
// underflow check
|
||||
if (cpreg.rwdistance < cpreg.lowatermark)
|
||||
cpreg.status.UnderflowLoWatermark = 1;
|
||||
// underflow check
|
||||
if (cpreg.rwdistance < cpreg.lowatermark)
|
||||
cpreg.status.UnderflowLoWatermark = 1;
|
||||
|
||||
// breakpoint
|
||||
if (cpreg.ctrl.BPEnable)
|
||||
{
|
||||
if (cpreg.breakpt == cpreg.readptr)
|
||||
{
|
||||
if (!cpreg.status.Breakpoint)
|
||||
INFO_LOG(COMMANDPROCESSOR, "Hit breakpoint at %x", cpreg.readptr);
|
||||
cpreg.status.Breakpoint = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cpreg.status.Breakpoint)
|
||||
INFO_LOG(COMMANDPROCESSOR, "Cleared breakpoint at %x", cpreg.readptr);
|
||||
cpreg.status.Breakpoint = 0;
|
||||
}
|
||||
// breakpoint
|
||||
if (cpreg.ctrl.BPEnable)
|
||||
{
|
||||
if (cpreg.breakpt == cpreg.readptr)
|
||||
{
|
||||
if (!cpreg.status.Breakpoint)
|
||||
INFO_LOG(COMMANDPROCESSOR, "Hit breakpoint at %x", cpreg.readptr);
|
||||
cpreg.status.Breakpoint = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cpreg.status.Breakpoint)
|
||||
INFO_LOG(COMMANDPROCESSOR, "Cleared breakpoint at %x", cpreg.readptr);
|
||||
cpreg.status.Breakpoint = 0;
|
||||
}
|
||||
|
||||
cpreg.status.ReadIdle = cpreg.readptr == cpreg.writeptr;
|
||||
cpreg.status.ReadIdle = cpreg.readptr == cpreg.writeptr;
|
||||
|
||||
bool bpInt = cpreg.status.Breakpoint && cpreg.ctrl.BreakPointIntEnable;
|
||||
bool ovfInt = cpreg.status.OverflowHiWatermark && cpreg.ctrl.FifoOverflowIntEnable;
|
||||
bool undfInt = cpreg.status.UnderflowLoWatermark && cpreg.ctrl.FifoUnderflowIntEnable;
|
||||
bool bpInt = cpreg.status.Breakpoint && cpreg.ctrl.BreakPointIntEnable;
|
||||
bool ovfInt = cpreg.status.OverflowHiWatermark && cpreg.ctrl.FifoOverflowIntEnable;
|
||||
bool undfInt = cpreg.status.UnderflowLoWatermark && cpreg.ctrl.FifoUnderflowIntEnable;
|
||||
|
||||
bool interrupt = bpInt || ovfInt || undfInt;
|
||||
bool interrupt = bpInt || ovfInt || undfInt;
|
||||
|
||||
if (interrupt != interruptSet && !interruptWaiting)
|
||||
{
|
||||
u64 userdata = interrupt?1:0;
|
||||
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bCPUThread)
|
||||
{
|
||||
interruptWaiting = true;
|
||||
SWCommandProcessor::UpdateInterruptsFromVideoBackend(userdata);
|
||||
}
|
||||
else
|
||||
SWCommandProcessor::UpdateInterrupts(userdata);
|
||||
}
|
||||
if (interrupt != interruptSet && !interruptWaiting)
|
||||
{
|
||||
u64 userdata = interrupt?1:0;
|
||||
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bCPUThread)
|
||||
{
|
||||
interruptWaiting = true;
|
||||
SWCommandProcessor::UpdateInterruptsFromVideoBackend(userdata);
|
||||
}
|
||||
else
|
||||
{
|
||||
SWCommandProcessor::UpdateInterrupts(userdata);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool RunBuffer()
|
||||
{
|
||||
// fifo is read 32 bytes at a time
|
||||
// read fifo data to internal buffer
|
||||
if (cpreg.ctrl.GPReadEnable)
|
||||
ReadFifo();
|
||||
// fifo is read 32 bytes at a time
|
||||
// read fifo data to internal buffer
|
||||
if (cpreg.ctrl.GPReadEnable)
|
||||
ReadFifo();
|
||||
|
||||
SetStatus();
|
||||
|
||||
_dbg_assert_(COMMANDPROCESSOR, writePos >= readPos);
|
||||
|
||||
g_pVideoData = &commandBuffer[readPos];
|
||||
SetStatus();
|
||||
|
||||
u32 availableBytes = writePos - readPos;
|
||||
_dbg_assert_(COMMANDPROCESSOR, writePos >= readPos);
|
||||
|
||||
while (OpcodeDecoder::CommandRunnable(availableBytes))
|
||||
{
|
||||
cpreg.status.CommandIdle = 0;
|
||||
g_pVideoData = &commandBuffer[readPos];
|
||||
|
||||
OpcodeDecoder::Run(availableBytes);
|
||||
u32 availableBytes = writePos - readPos;
|
||||
|
||||
// if data was read by the opcode decoder then the video data pointer changed
|
||||
readPos = (u32)(g_pVideoData - &commandBuffer[0]);
|
||||
_dbg_assert_(VIDEO, writePos >= readPos);
|
||||
availableBytes = writePos - readPos;
|
||||
}
|
||||
while (OpcodeDecoder::CommandRunnable(availableBytes))
|
||||
{
|
||||
cpreg.status.CommandIdle = 0;
|
||||
|
||||
cpreg.status.CommandIdle = 1;
|
||||
OpcodeDecoder::Run(availableBytes);
|
||||
|
||||
bool ranDecoder = false;
|
||||
|
||||
// move data remaing in command buffer
|
||||
if (readPos > 0)
|
||||
{
|
||||
memmove(&commandBuffer[0], &commandBuffer[readPos], availableBytes);
|
||||
writePos -= readPos;
|
||||
readPos = 0;
|
||||
// if data was read by the opcode decoder then the video data pointer changed
|
||||
readPos = (u32)(g_pVideoData - &commandBuffer[0]);
|
||||
_dbg_assert_(VIDEO, writePos >= readPos);
|
||||
availableBytes = writePos - readPos;
|
||||
}
|
||||
|
||||
ranDecoder = true;
|
||||
}
|
||||
cpreg.status.CommandIdle = 1;
|
||||
|
||||
return ranDecoder;
|
||||
bool ranDecoder = false;
|
||||
|
||||
// move data remaing in command buffer
|
||||
if (readPos > 0)
|
||||
{
|
||||
memmove(&commandBuffer[0], &commandBuffer[readPos], availableBytes);
|
||||
writePos -= readPos;
|
||||
readPos = 0;
|
||||
|
||||
ranDecoder = true;
|
||||
}
|
||||
|
||||
return ranDecoder;
|
||||
}
|
||||
|
||||
void SetRendering(bool enabled)
|
||||
{
|
||||
g_bSkipCurrentFrame = !enabled;
|
||||
g_bSkipCurrentFrame = !enabled;
|
||||
}
|
||||
|
||||
} // end of namespace SWCommandProcessor
|
||||
|
|
|
@ -12,12 +12,12 @@
|
|||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// Official Git repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _COMMANDPROCESSOR_H_
|
||||
#define _COMMANDPROCESSOR_H_
|
||||
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
class PointerWrap;
|
||||
|
@ -27,128 +27,128 @@ extern u8* g_pVideoData;
|
|||
|
||||
namespace SWCommandProcessor
|
||||
{
|
||||
// internal hardware addresses
|
||||
enum
|
||||
{
|
||||
STATUS_REGISTER = 0x00,
|
||||
CTRL_REGISTER = 0x02,
|
||||
CLEAR_REGISTER = 0x04,
|
||||
FIFO_TOKEN_REGISTER = 0x0E,
|
||||
FIFO_BOUNDING_BOX_LEFT = 0x10,
|
||||
FIFO_BOUNDING_BOX_RIGHT = 0x12,
|
||||
FIFO_BOUNDING_BOX_TOP = 0x14,
|
||||
FIFO_BOUNDING_BOX_BOTTOM = 0x16,
|
||||
FIFO_BASE_LO = 0x20,
|
||||
FIFO_BASE_HI = 0x22,
|
||||
FIFO_END_LO = 0x24,
|
||||
FIFO_END_HI = 0x26,
|
||||
FIFO_HI_WATERMARK_LO = 0x28,
|
||||
FIFO_HI_WATERMARK_HI = 0x2a,
|
||||
FIFO_LO_WATERMARK_LO = 0x2c,
|
||||
FIFO_LO_WATERMARK_HI = 0x2e,
|
||||
FIFO_RW_DISTANCE_LO = 0x30,
|
||||
FIFO_RW_DISTANCE_HI = 0x32,
|
||||
FIFO_WRITE_POINTER_LO = 0x34,
|
||||
FIFO_WRITE_POINTER_HI = 0x36,
|
||||
FIFO_READ_POINTER_LO = 0x38,
|
||||
FIFO_READ_POINTER_HI = 0x3A,
|
||||
FIFO_BP_LO = 0x3C,
|
||||
FIFO_BP_HI = 0x3E
|
||||
};
|
||||
// internal hardware addresses
|
||||
enum
|
||||
{
|
||||
STATUS_REGISTER = 0x00,
|
||||
CTRL_REGISTER = 0x02,
|
||||
CLEAR_REGISTER = 0x04,
|
||||
FIFO_TOKEN_REGISTER = 0x0E,
|
||||
FIFO_BOUNDING_BOX_LEFT = 0x10,
|
||||
FIFO_BOUNDING_BOX_RIGHT = 0x12,
|
||||
FIFO_BOUNDING_BOX_TOP = 0x14,
|
||||
FIFO_BOUNDING_BOX_BOTTOM = 0x16,
|
||||
FIFO_BASE_LO = 0x20,
|
||||
FIFO_BASE_HI = 0x22,
|
||||
FIFO_END_LO = 0x24,
|
||||
FIFO_END_HI = 0x26,
|
||||
FIFO_HI_WATERMARK_LO = 0x28,
|
||||
FIFO_HI_WATERMARK_HI = 0x2a,
|
||||
FIFO_LO_WATERMARK_LO = 0x2c,
|
||||
FIFO_LO_WATERMARK_HI = 0x2e,
|
||||
FIFO_RW_DISTANCE_LO = 0x30,
|
||||
FIFO_RW_DISTANCE_HI = 0x32,
|
||||
FIFO_WRITE_POINTER_LO = 0x34,
|
||||
FIFO_WRITE_POINTER_HI = 0x36,
|
||||
FIFO_READ_POINTER_LO = 0x38,
|
||||
FIFO_READ_POINTER_HI = 0x3A,
|
||||
FIFO_BP_LO = 0x3C,
|
||||
FIFO_BP_HI = 0x3E
|
||||
};
|
||||
|
||||
// Fifo Status Register
|
||||
union UCPStatusReg
|
||||
{
|
||||
struct
|
||||
{
|
||||
u16 OverflowHiWatermark : 1;
|
||||
u16 UnderflowLoWatermark: 1;
|
||||
u16 ReadIdle : 1; // done reading
|
||||
u16 CommandIdle : 1; // done processing commands
|
||||
u16 Breakpoint : 1;
|
||||
u16 : 11;
|
||||
};
|
||||
u16 Hex;
|
||||
UCPStatusReg() {Hex = 0; }
|
||||
UCPStatusReg(u16 _hex) {Hex = _hex; }
|
||||
};
|
||||
// Fifo Status Register
|
||||
union UCPStatusReg
|
||||
{
|
||||
struct
|
||||
{
|
||||
u16 OverflowHiWatermark : 1;
|
||||
u16 UnderflowLoWatermark: 1;
|
||||
u16 ReadIdle : 1; // done reading
|
||||
u16 CommandIdle : 1; // done processing commands
|
||||
u16 Breakpoint : 1;
|
||||
u16 : 11;
|
||||
};
|
||||
u16 Hex;
|
||||
UCPStatusReg() {Hex = 0; }
|
||||
UCPStatusReg(u16 _hex) {Hex = _hex; }
|
||||
};
|
||||
|
||||
// Fifo Control Register
|
||||
union UCPCtrlReg
|
||||
{
|
||||
struct
|
||||
{
|
||||
u16 GPReadEnable : 1;
|
||||
u16 BPEnable : 1;
|
||||
u16 FifoOverflowIntEnable : 1;
|
||||
u16 FifoUnderflowIntEnable : 1;
|
||||
u16 GPLinkEnable : 1;
|
||||
u16 BreakPointIntEnable : 1;
|
||||
u16 : 10;
|
||||
};
|
||||
u16 Hex;
|
||||
UCPCtrlReg() {Hex = 0; }
|
||||
UCPCtrlReg(u16 _hex) {Hex = _hex; }
|
||||
};
|
||||
// Fifo Control Register
|
||||
union UCPCtrlReg
|
||||
{
|
||||
struct
|
||||
{
|
||||
u16 GPReadEnable : 1;
|
||||
u16 BPEnable : 1;
|
||||
u16 FifoOverflowIntEnable : 1;
|
||||
u16 FifoUnderflowIntEnable : 1;
|
||||
u16 GPLinkEnable : 1;
|
||||
u16 BreakPointIntEnable : 1;
|
||||
u16 : 10;
|
||||
};
|
||||
u16 Hex;
|
||||
UCPCtrlReg() {Hex = 0; }
|
||||
UCPCtrlReg(u16 _hex) {Hex = _hex; }
|
||||
};
|
||||
|
||||
// Fifo Control Register
|
||||
union UCPClearReg
|
||||
{
|
||||
struct
|
||||
{
|
||||
u16 ClearFifoOverflow : 1;
|
||||
u16 ClearFifoUnderflow : 1;
|
||||
u16 ClearMetrices : 1;
|
||||
u16 : 13;
|
||||
};
|
||||
u16 Hex;
|
||||
UCPClearReg() {Hex = 0; }
|
||||
UCPClearReg(u16 _hex) {Hex = _hex; }
|
||||
};
|
||||
// Fifo Control Register
|
||||
union UCPClearReg
|
||||
{
|
||||
struct
|
||||
{
|
||||
u16 ClearFifoOverflow : 1;
|
||||
u16 ClearFifoUnderflow : 1;
|
||||
u16 ClearMetrices : 1;
|
||||
u16 : 13;
|
||||
};
|
||||
u16 Hex;
|
||||
UCPClearReg() {Hex = 0; }
|
||||
UCPClearReg(u16 _hex) {Hex = _hex; }
|
||||
};
|
||||
|
||||
struct CPReg
|
||||
{
|
||||
UCPStatusReg status; // 0x00
|
||||
UCPCtrlReg ctrl; // 0x02
|
||||
UCPClearReg clear; // 0x04
|
||||
u32 unk0; // 0x06
|
||||
u32 unk1; // 0x0a
|
||||
u16 token; // 0x0e
|
||||
u16 bboxleft; // 0x10
|
||||
u16 bboxtop; // 0x12
|
||||
u16 bboxright; // 0x14
|
||||
u16 bboxbottom; // 0x16
|
||||
u16 unk2; // 0x18
|
||||
u32 fifobase; // 0x20
|
||||
u32 fifoend; // 0x24
|
||||
u32 hiwatermark; // 0x28
|
||||
u32 lowatermark; // 0x2c
|
||||
u32 rwdistance; // 0x30
|
||||
u32 writeptr; // 0x34
|
||||
u32 readptr; // 0x38
|
||||
u32 breakpt; // 0x3c
|
||||
};
|
||||
struct CPReg
|
||||
{
|
||||
UCPStatusReg status; // 0x00
|
||||
UCPCtrlReg ctrl; // 0x02
|
||||
UCPClearReg clear; // 0x04
|
||||
u32 unk0; // 0x06
|
||||
u32 unk1; // 0x0a
|
||||
u16 token; // 0x0e
|
||||
u16 bboxleft; // 0x10
|
||||
u16 bboxtop; // 0x12
|
||||
u16 bboxright; // 0x14
|
||||
u16 bboxbottom; // 0x16
|
||||
u16 unk2; // 0x18
|
||||
u32 fifobase; // 0x20
|
||||
u32 fifoend; // 0x24
|
||||
u32 hiwatermark; // 0x28
|
||||
u32 lowatermark; // 0x2c
|
||||
u32 rwdistance; // 0x30
|
||||
u32 writeptr; // 0x34
|
||||
u32 readptr; // 0x38
|
||||
u32 breakpt; // 0x3c
|
||||
};
|
||||
|
||||
extern CPReg cpreg;
|
||||
extern CPReg cpreg;
|
||||
|
||||
// Init
|
||||
void Init();
|
||||
void Shutdown();
|
||||
void DoState(PointerWrap &p);
|
||||
// Init
|
||||
void Init();
|
||||
void Shutdown();
|
||||
void DoState(PointerWrap &p);
|
||||
|
||||
bool RunBuffer();
|
||||
void RunGpu();
|
||||
bool RunBuffer();
|
||||
void RunGpu();
|
||||
|
||||
// Read
|
||||
void Read16(u16& _rReturnValue, const u32 _Address);
|
||||
void Write16(const u16 _Data, const u32 _Address);
|
||||
void Read32(u32& _rReturnValue, const u32 _Address);
|
||||
void Write32(const u32 _Data, const u32 _Address);
|
||||
// Read
|
||||
void Read16(u16& _rReturnValue, const u32 _Address);
|
||||
void Write16(const u16 _Data, const u32 _Address);
|
||||
void Read32(u32& _rReturnValue, const u32 _Address);
|
||||
void Write32(const u32 _Data, const u32 _Address);
|
||||
|
||||
// for CGPFIFO
|
||||
void GatherPipeBursted();
|
||||
void UpdateInterrupts(u64 userdata);
|
||||
void UpdateInterruptsFromVideoBackend(u64 userdata);
|
||||
// for CGPFIFO
|
||||
void GatherPipeBursted();
|
||||
void UpdateInterrupts(u64 userdata);
|
||||
void UpdateInterruptsFromVideoBackend(u64 userdata);
|
||||
|
||||
void SetRendering(bool enabled);
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// Official Git repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
|
||||
|
@ -35,8 +35,8 @@ namespace SWPixelEngine
|
|||
|
||||
enum
|
||||
{
|
||||
INT_CAUSE_PE_TOKEN = 0x200, // GP Token
|
||||
INT_CAUSE_PE_FINISH = 0x400, // GP Finished
|
||||
INT_CAUSE_PE_TOKEN = 0x200, // GP Token
|
||||
INT_CAUSE_PE_FINISH = 0x400, // GP Finished
|
||||
};
|
||||
|
||||
// STATE_TO_SAVE
|
||||
|
@ -50,7 +50,7 @@ static int et_SetFinishOnMainThread;
|
|||
|
||||
void DoState(PointerWrap &p)
|
||||
{
|
||||
p.DoPOD(pereg);
|
||||
p.DoPOD(pereg);
|
||||
p.Do(g_bSignalTokenInterrupt);
|
||||
p.Do(g_bSignalFinishInterrupt);
|
||||
p.Do(et_SetTokenOnMainThread);
|
||||
|
@ -64,10 +64,10 @@ void SetFinish_OnMainThread(u64 userdata, int cyclesLate);
|
|||
|
||||
void Init()
|
||||
{
|
||||
memset(&pereg, 0, sizeof(pereg));
|
||||
memset(&pereg, 0, sizeof(pereg));
|
||||
|
||||
et_SetTokenOnMainThread = false;
|
||||
g_bSignalFinishInterrupt = false;
|
||||
et_SetTokenOnMainThread = false;
|
||||
g_bSignalFinishInterrupt = false;
|
||||
|
||||
et_SetTokenOnMainThread = CoreTiming::RegisterEvent("SetToken", SetToken_OnMainThread);
|
||||
et_SetFinishOnMainThread = CoreTiming::RegisterEvent("SetFinish", SetFinish_OnMainThread);
|
||||
|
@ -77,10 +77,10 @@ void Read16(u16& _uReturnValue, const u32 _iAddress)
|
|||
{
|
||||
DEBUG_LOG(PIXELENGINE, "(r16): 0x%08x", _iAddress);
|
||||
|
||||
u16 address = _iAddress & 0xFFF;
|
||||
u16 address = _iAddress & 0xFFF;
|
||||
|
||||
if (address <= 0x2e)
|
||||
_uReturnValue = ((u16*)&pereg)[address >> 1];
|
||||
if (address <= 0x2e)
|
||||
_uReturnValue = ((u16*)&pereg)[address >> 1];
|
||||
}
|
||||
|
||||
void Write32(const u32 _iValue, const u32 _iAddress)
|
||||
|
@ -92,7 +92,7 @@ void Write16(const u16 _iValue, const u32 _iAddress)
|
|||
{
|
||||
u16 address = _iAddress & 0xFFF;
|
||||
|
||||
switch (address)
|
||||
switch (address)
|
||||
{
|
||||
case PE_CTRL_REGISTER:
|
||||
{
|
||||
|
@ -101,7 +101,7 @@ void Write16(const u16 _iValue, const u32 _iAddress)
|
|||
if (tmpCtrl.PEToken) g_bSignalTokenInterrupt = false;
|
||||
if (tmpCtrl.PEFinish) g_bSignalFinishInterrupt = false;
|
||||
|
||||
pereg.ctrl.PETokenEnable = tmpCtrl.PETokenEnable;
|
||||
pereg.ctrl.PETokenEnable = tmpCtrl.PETokenEnable;
|
||||
pereg.ctrl.PEFinishEnable = tmpCtrl.PEFinishEnable;
|
||||
pereg.ctrl.PEToken = 0; // this flag is write only
|
||||
pereg.ctrl.PEFinish = 0; // this flag is write only
|
||||
|
@ -112,7 +112,7 @@ void Write16(const u16 _iValue, const u32 _iAddress)
|
|||
break;
|
||||
default:
|
||||
if (address <= 0x2e)
|
||||
((u16*)&pereg)[address >> 1] = _iValue;
|
||||
((u16*)&pereg)[address >> 1] = _iValue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -125,13 +125,13 @@ bool AllowIdleSkipping()
|
|||
void UpdateInterrupts()
|
||||
{
|
||||
// check if there is a token-interrupt
|
||||
if (g_bSignalTokenInterrupt & pereg.ctrl.PETokenEnable)
|
||||
ProcessorInterface::SetInterrupt(INT_CAUSE_PE_TOKEN, true);
|
||||
if (g_bSignalTokenInterrupt & pereg.ctrl.PETokenEnable)
|
||||
ProcessorInterface::SetInterrupt(INT_CAUSE_PE_TOKEN, true);
|
||||
else
|
||||
ProcessorInterface::SetInterrupt(INT_CAUSE_PE_TOKEN, false);
|
||||
|
||||
// check if there is a finish-interrupt
|
||||
if (g_bSignalFinishInterrupt & pereg.ctrl.PEFinishEnable)
|
||||
if (g_bSignalFinishInterrupt & pereg.ctrl.PEFinishEnable)
|
||||
ProcessorInterface::SetInterrupt(INT_CAUSE_PE_FINISH, true);
|
||||
else
|
||||
ProcessorInterface::SetInterrupt(INT_CAUSE_PE_FINISH, false);
|
||||
|
@ -142,7 +142,7 @@ void UpdateInterrupts()
|
|||
void SetToken_OnMainThread(u64 userdata, int cyclesLate)
|
||||
{
|
||||
g_bSignalTokenInterrupt = true;
|
||||
INFO_LOG(PIXELENGINE, "VIDEO Backend raises INT_CAUSE_PE_TOKEN (btw, token: %04x)", pereg.token);
|
||||
INFO_LOG(PIXELENGINE, "VIDEO Backend raises INT_CAUSE_PE_TOKEN (btw, token: %04x)", pereg.token);
|
||||
UpdateInterrupts();
|
||||
}
|
||||
|
||||
|
@ -157,7 +157,7 @@ void SetFinish_OnMainThread(u64 userdata, int cyclesLate)
|
|||
void SetToken(const u16 _token, const int _bSetTokenAcknowledge)
|
||||
{
|
||||
pereg.token = _token;
|
||||
if (_bSetTokenAcknowledge) // set token INT
|
||||
if (_bSetTokenAcknowledge) // set token INT
|
||||
{
|
||||
CoreTiming::ScheduleEvent_Threadsafe(0, et_SetTokenOnMainThread,
|
||||
_token | (_bSetTokenAcknowledge << 16));
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// Official Git repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
#ifndef _PIXELENGINE_H
|
||||
#define _PIXELENGINE_H
|
||||
|
@ -24,20 +24,20 @@ class PointerWrap;
|
|||
|
||||
namespace SWPixelEngine
|
||||
{
|
||||
// internal hardware addresses
|
||||
enum
|
||||
{
|
||||
PE_ZCONF = 0x000, // Z Config
|
||||
PE_ALPHACONF = 0x002, // Alpha Config
|
||||
PE_DSTALPHACONF = 0x004, // Destination Alpha Config
|
||||
PE_ALPHAMODE = 0x006, // Alpha Mode Config
|
||||
PE_ALPHAREAD = 0x008, // Alpha Read
|
||||
PE_CTRL_REGISTER = 0x00a, // Control
|
||||
PE_TOKEN_REG = 0x00e, // Token
|
||||
PE_BBOX_LEFT = 0x010, // Flip Left
|
||||
PE_BBOX_RIGHT = 0x012, // Flip Right
|
||||
PE_BBOX_TOP = 0x014, // Flip Top
|
||||
PE_BBOX_BOTTOM = 0x016, // Flip Bottom
|
||||
// internal hardware addresses
|
||||
enum
|
||||
{
|
||||
PE_ZCONF = 0x000, // Z Config
|
||||
PE_ALPHACONF = 0x002, // Alpha Config
|
||||
PE_DSTALPHACONF = 0x004, // Destination Alpha Config
|
||||
PE_ALPHAMODE = 0x006, // Alpha Mode Config
|
||||
PE_ALPHAREAD = 0x008, // Alpha Read
|
||||
PE_CTRL_REGISTER = 0x00a, // Control
|
||||
PE_TOKEN_REG = 0x00e, // Token
|
||||
PE_BBOX_LEFT = 0x010, // Flip Left
|
||||
PE_BBOX_RIGHT = 0x012, // Flip Right
|
||||
PE_BBOX_TOP = 0x014, // Flip Top
|
||||
PE_BBOX_BOTTOM = 0x016, // Flip Bottom
|
||||
|
||||
// NOTE: Order not verified
|
||||
// These indicate the number of quads that are being used as input/output for each particular stage
|
||||
|
@ -53,98 +53,98 @@ namespace SWPixelEngine
|
|||
PE_PERF_BLEND_INPUT_H = 0x2a,
|
||||
PE_PERF_EFB_COPY_CLOCKS_L = 0x2c,
|
||||
PE_PERF_EFB_COPY_CLOCKS_H = 0x2e,
|
||||
};
|
||||
};
|
||||
|
||||
union UPEZConfReg
|
||||
{
|
||||
u16 Hex;
|
||||
struct
|
||||
{
|
||||
u16 ZCompEnable : 1; // Z Comparator Enable
|
||||
u16 Function : 3;
|
||||
u16 ZUpdEnable : 1;
|
||||
u16 : 11;
|
||||
};
|
||||
};
|
||||
union UPEZConfReg
|
||||
{
|
||||
u16 Hex;
|
||||
struct
|
||||
{
|
||||
u16 ZCompEnable : 1; // Z Comparator Enable
|
||||
u16 Function : 3;
|
||||
u16 ZUpdEnable : 1;
|
||||
u16 : 11;
|
||||
};
|
||||
};
|
||||
|
||||
union UPEAlphaConfReg
|
||||
{
|
||||
u16 Hex;
|
||||
struct
|
||||
{
|
||||
u16 BMMath : 1; // GX_BM_BLEND || GX_BM_SUBSTRACT
|
||||
u16 BMLogic : 1; // GX_BM_LOGIC
|
||||
u16 Dither : 1;
|
||||
u16 ColorUpdEnable : 1;
|
||||
u16 AlphaUpdEnable : 1;
|
||||
u16 DstFactor : 3;
|
||||
u16 SrcFactor : 3;
|
||||
u16 Substract : 1; // Additive mode by default
|
||||
u16 BlendOperator : 4;
|
||||
};
|
||||
};
|
||||
union UPEAlphaConfReg
|
||||
{
|
||||
u16 Hex;
|
||||
struct
|
||||
{
|
||||
u16 BMMath : 1; // GX_BM_BLEND || GX_BM_SUBSTRACT
|
||||
u16 BMLogic : 1; // GX_BM_LOGIC
|
||||
u16 Dither : 1;
|
||||
u16 ColorUpdEnable : 1;
|
||||
u16 AlphaUpdEnable : 1;
|
||||
u16 DstFactor : 3;
|
||||
u16 SrcFactor : 3;
|
||||
u16 Substract : 1; // Additive mode by default
|
||||
u16 BlendOperator : 4;
|
||||
};
|
||||
};
|
||||
|
||||
union UPEDstAlphaConfReg
|
||||
{
|
||||
u16 Hex;
|
||||
struct
|
||||
{
|
||||
u16 DstAlpha : 8;
|
||||
u16 Enable : 1;
|
||||
u16 : 7;
|
||||
};
|
||||
};
|
||||
union UPEDstAlphaConfReg
|
||||
{
|
||||
u16 Hex;
|
||||
struct
|
||||
{
|
||||
u16 DstAlpha : 8;
|
||||
u16 Enable : 1;
|
||||
u16 : 7;
|
||||
};
|
||||
};
|
||||
|
||||
union UPEAlphaModeConfReg
|
||||
{
|
||||
u16 Hex;
|
||||
struct
|
||||
{
|
||||
u16 Threshold : 8;
|
||||
u16 CompareMode : 8;
|
||||
};
|
||||
};
|
||||
union UPEAlphaModeConfReg
|
||||
{
|
||||
u16 Hex;
|
||||
struct
|
||||
{
|
||||
u16 Threshold : 8;
|
||||
u16 CompareMode : 8;
|
||||
};
|
||||
};
|
||||
|
||||
union UPEAlphaReadReg
|
||||
{
|
||||
u16 Hex;
|
||||
struct
|
||||
{
|
||||
u16 ReadMode : 3;
|
||||
u16 : 13;
|
||||
};
|
||||
};
|
||||
union UPEAlphaReadReg
|
||||
{
|
||||
u16 Hex;
|
||||
struct
|
||||
{
|
||||
u16 ReadMode : 3;
|
||||
u16 : 13;
|
||||
};
|
||||
};
|
||||
|
||||
union UPECtrlReg
|
||||
{
|
||||
struct
|
||||
{
|
||||
u16 PETokenEnable : 1;
|
||||
u16 PEFinishEnable : 1;
|
||||
u16 PEToken : 1; // write only
|
||||
u16 PEFinish : 1; // write only
|
||||
u16 : 12;
|
||||
};
|
||||
u16 Hex;
|
||||
UPECtrlReg() {Hex = 0; }
|
||||
UPECtrlReg(u16 _hex) {Hex = _hex; }
|
||||
};
|
||||
union UPECtrlReg
|
||||
{
|
||||
struct
|
||||
{
|
||||
u16 PETokenEnable : 1;
|
||||
u16 PEFinishEnable : 1;
|
||||
u16 PEToken : 1; // write only
|
||||
u16 PEFinish : 1; // write only
|
||||
u16 : 12;
|
||||
};
|
||||
u16 Hex;
|
||||
UPECtrlReg() {Hex = 0; }
|
||||
UPECtrlReg(u16 _hex) {Hex = _hex; }
|
||||
};
|
||||
|
||||
struct PEReg
|
||||
{
|
||||
UPEZConfReg zconf;
|
||||
UPEAlphaConfReg alphaConf;
|
||||
UPEDstAlphaConfReg dstAlpha;
|
||||
UPEAlphaModeConfReg alphaMode;
|
||||
UPEAlphaReadReg alphaRead;
|
||||
UPECtrlReg ctrl;
|
||||
u16 unk0;
|
||||
u16 token;
|
||||
struct PEReg
|
||||
{
|
||||
UPEZConfReg zconf;
|
||||
UPEAlphaConfReg alphaConf;
|
||||
UPEDstAlphaConfReg dstAlpha;
|
||||
UPEAlphaModeConfReg alphaMode;
|
||||
UPEAlphaReadReg alphaRead;
|
||||
UPECtrlReg ctrl;
|
||||
u16 unk0;
|
||||
u16 token;
|
||||
|
||||
u16 boxLeft;
|
||||
u16 boxRight;
|
||||
u16 boxTop;
|
||||
u16 boxBottom;
|
||||
u16 boxLeft;
|
||||
u16 boxRight;
|
||||
u16 boxTop;
|
||||
u16 boxBottom;
|
||||
|
||||
u16 perfZcompInputZcomplocLo;
|
||||
u16 perfZcompInputZcomplocHi;
|
||||
|
@ -206,24 +206,24 @@ namespace SWPixelEngine
|
|||
if (++perfBlendInputLo == 0)
|
||||
perfBlendInputHi++;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
extern PEReg pereg;
|
||||
extern PEReg pereg;
|
||||
|
||||
void Init();
|
||||
void DoState(PointerWrap &p);
|
||||
void Init();
|
||||
void DoState(PointerWrap &p);
|
||||
|
||||
// Read
|
||||
void Read16(u16& _uReturnValue, const u32 _iAddress);
|
||||
// Read
|
||||
void Read16(u16& _uReturnValue, const u32 _iAddress);
|
||||
|
||||
// Write
|
||||
void Write16(const u16 _iValue, const u32 _iAddress);
|
||||
void Write32(const u32 _iValue, const u32 _iAddress);
|
||||
// Write
|
||||
void Write16(const u16 _iValue, const u32 _iAddress);
|
||||
void Write32(const u32 _iValue, const u32 _iAddress);
|
||||
|
||||
// gfx backend support
|
||||
void SetToken(const u16 _token, const int _bSetTokenAcknowledge);
|
||||
void SetFinish(void);
|
||||
bool AllowIdleSkipping();
|
||||
// gfx backend support
|
||||
void SetToken(const u16 _token, const int _bSetTokenAcknowledge);
|
||||
void SetFinish(void);
|
||||
bool AllowIdleSkipping();
|
||||
|
||||
} // end of namespace SWPixelEngine
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// Official Git repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "Common.h"
|
||||
|
@ -116,20 +116,20 @@ void SWRenderer::DrawDebugText()
|
|||
|
||||
if (g_SWVideoConfig.bShowStats)
|
||||
{
|
||||
p+=sprintf(p,"Objects: %i\n",swstats.thisFrame.numDrawnObjects);
|
||||
p+=sprintf(p,"Primitives: %i\n",swstats.thisFrame.numPrimatives);
|
||||
p+=sprintf(p,"Vertices Loaded: %i\n",swstats.thisFrame.numVerticesLoaded);
|
||||
p+=sprintf(p,"Objects: %i\n",swstats.thisFrame.numDrawnObjects);
|
||||
p+=sprintf(p,"Primitives: %i\n",swstats.thisFrame.numPrimatives);
|
||||
p+=sprintf(p,"Vertices Loaded: %i\n",swstats.thisFrame.numVerticesLoaded);
|
||||
|
||||
p+=sprintf(p,"Triangles Input: %i\n",swstats.thisFrame.numTrianglesIn);
|
||||
p+=sprintf(p,"Triangles Rejected: %i\n",swstats.thisFrame.numTrianglesRejected);
|
||||
p+=sprintf(p,"Triangles Culled: %i\n",swstats.thisFrame.numTrianglesCulled);
|
||||
p+=sprintf(p,"Triangles Clipped: %i\n",swstats.thisFrame.numTrianglesClipped);
|
||||
p+=sprintf(p,"Triangles Drawn: %i\n",swstats.thisFrame.numTrianglesDrawn);
|
||||
p+=sprintf(p,"Triangles Input: %i\n",swstats.thisFrame.numTrianglesIn);
|
||||
p+=sprintf(p,"Triangles Rejected: %i\n",swstats.thisFrame.numTrianglesRejected);
|
||||
p+=sprintf(p,"Triangles Culled: %i\n",swstats.thisFrame.numTrianglesCulled);
|
||||
p+=sprintf(p,"Triangles Clipped: %i\n",swstats.thisFrame.numTrianglesClipped);
|
||||
p+=sprintf(p,"Triangles Drawn: %i\n",swstats.thisFrame.numTrianglesDrawn);
|
||||
|
||||
p+=sprintf(p,"Rasterized Pix: %i\n",swstats.thisFrame.rasterizedPixels);
|
||||
p+=sprintf(p,"TEV Pix In: %i\n",swstats.thisFrame.tevPixelsIn);
|
||||
p+=sprintf(p,"TEV Pix Out: %i\n",swstats.thisFrame.tevPixelsOut);
|
||||
}
|
||||
p+=sprintf(p,"Rasterized Pix: %i\n",swstats.thisFrame.rasterizedPixels);
|
||||
p+=sprintf(p,"TEV Pix In: %i\n",swstats.thisFrame.tevPixelsIn);
|
||||
p+=sprintf(p,"TEV Pix Out: %i\n",swstats.thisFrame.tevPixelsOut);
|
||||
}
|
||||
|
||||
// Render a shadow, and then the text.
|
||||
SWRenderer::RenderText(debugtext_buffer, 21, 21, 0xDD000000);
|
||||
|
@ -206,9 +206,9 @@ void SWRenderer::DrawTexture(u8 *texture, int width, int height)
|
|||
glVertexAttribPointer(attr_tex, 2, GL_FLOAT, GL_FALSE, 0, texverts);
|
||||
glEnableVertexAttribArray(attr_pos);
|
||||
glEnableVertexAttribArray(attr_tex);
|
||||
glUniform1i(uni_tex, 0);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||
glUniform1i(uni_tex, 0);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||
glDisableVertexAttribArray(attr_pos);
|
||||
glDisableVertexAttribArray(attr_tex);
|
||||
|
||||
|
@ -226,7 +226,7 @@ void SWRenderer::SwapBuffer()
|
|||
glFlush();
|
||||
|
||||
GLInterface->Swap();
|
||||
|
||||
|
||||
swstats.ResetFrame();
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// Official Git repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _RENDERER_H_
|
||||
|
@ -22,16 +22,16 @@
|
|||
|
||||
namespace SWRenderer
|
||||
{
|
||||
void Init();
|
||||
void Prepare();
|
||||
void Shutdown();
|
||||
void Init();
|
||||
void Prepare();
|
||||
void Shutdown();
|
||||
|
||||
void RenderText(const char* pstr, int left, int top, u32 color);
|
||||
void DrawDebugText();
|
||||
void RenderText(const char* pstr, int left, int top, u32 color);
|
||||
void DrawDebugText();
|
||||
|
||||
void DrawTexture(u8 *texture, int width, int height);
|
||||
void DrawTexture(u8 *texture, int width, int height);
|
||||
|
||||
void SwapBuffer();
|
||||
void SwapBuffer();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// Official Git repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "SWStatistics.h"
|
||||
|
@ -29,7 +29,7 @@ void Xchg(T& a, T&b)
|
|||
|
||||
SWStatistics::SWStatistics()
|
||||
{
|
||||
frameCount = 0;
|
||||
frameCount = 0;
|
||||
}
|
||||
|
||||
void SWStatistics::ResetFrame()
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// Official Git repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "CommonTypes.h"
|
||||
|
@ -23,29 +23,29 @@
|
|||
|
||||
struct SWStatistics
|
||||
{
|
||||
struct ThisFrame
|
||||
{
|
||||
u32 numDrawnObjects;
|
||||
u32 numPrimatives;
|
||||
u32 numVerticesLoaded;
|
||||
u32 numVerticesOut;
|
||||
struct ThisFrame
|
||||
{
|
||||
u32 numDrawnObjects;
|
||||
u32 numPrimatives;
|
||||
u32 numVerticesLoaded;
|
||||
u32 numVerticesOut;
|
||||
|
||||
u32 numTrianglesIn;
|
||||
u32 numTrianglesRejected;
|
||||
u32 numTrianglesCulled;
|
||||
u32 numTrianglesClipped;
|
||||
u32 numTrianglesDrawn;
|
||||
u32 numTrianglesIn;
|
||||
u32 numTrianglesRejected;
|
||||
u32 numTrianglesCulled;
|
||||
u32 numTrianglesClipped;
|
||||
u32 numTrianglesDrawn;
|
||||
|
||||
u32 rasterizedPixels;
|
||||
u32 tevPixelsIn;
|
||||
u32 tevPixelsOut;
|
||||
};
|
||||
u32 rasterizedPixels;
|
||||
u32 tevPixelsIn;
|
||||
u32 tevPixelsOut;
|
||||
};
|
||||
|
||||
u32 frameCount;
|
||||
SWStatistics();
|
||||
u32 frameCount;
|
||||
SWStatistics();
|
||||
|
||||
ThisFrame thisFrame;
|
||||
void ResetFrame();
|
||||
ThisFrame thisFrame;
|
||||
void ResetFrame();
|
||||
};
|
||||
|
||||
extern SWStatistics swstats;
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// Official Git repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "Common.h"
|
||||
|
@ -41,72 +41,74 @@ extern float tcScale[8];
|
|||
|
||||
|
||||
SWVertexLoader::SWVertexLoader() :
|
||||
m_VertexSize(0),
|
||||
m_NumAttributeLoaders(0)
|
||||
m_VertexSize(0),
|
||||
m_NumAttributeLoaders(0)
|
||||
{
|
||||
VertexLoader_Normal::Init();
|
||||
VertexLoader_Position::Init();
|
||||
VertexLoader_TextCoord::Init();
|
||||
VertexLoader_Normal::Init();
|
||||
VertexLoader_Position::Init();
|
||||
VertexLoader_TextCoord::Init();
|
||||
|
||||
m_SetupUnit = new SetupUnit;
|
||||
m_SetupUnit = new SetupUnit;
|
||||
}
|
||||
|
||||
SWVertexLoader::~SWVertexLoader()
|
||||
{
|
||||
delete m_SetupUnit;
|
||||
m_SetupUnit = NULL;
|
||||
delete m_SetupUnit;
|
||||
m_SetupUnit = NULL;
|
||||
}
|
||||
|
||||
void SWVertexLoader::SetFormat(u8 attributeIndex, u8 primitiveType)
|
||||
{
|
||||
m_CurrentVat = &g_VtxAttr[attributeIndex];
|
||||
m_CurrentVat = &g_VtxAttr[attributeIndex];
|
||||
|
||||
posScale = 1.0f / float(1 << m_CurrentVat->g0.PosFrac);
|
||||
tcScale[0] = 1.0f / float(1 << m_CurrentVat->g0.Tex0Frac);
|
||||
tcScale[1] = 1.0f / float(1 << m_CurrentVat->g1.Tex1Frac);
|
||||
tcScale[2] = 1.0f / float(1 << m_CurrentVat->g1.Tex2Frac);
|
||||
tcScale[3] = 1.0f / float(1 << m_CurrentVat->g1.Tex3Frac);
|
||||
tcScale[4] = 1.0f / float(1 << m_CurrentVat->g2.Tex4Frac);
|
||||
tcScale[5] = 1.0f / float(1 << m_CurrentVat->g2.Tex5Frac);
|
||||
tcScale[6] = 1.0f / float(1 << m_CurrentVat->g2.Tex6Frac);
|
||||
tcScale[7] = 1.0f / float(1 << m_CurrentVat->g2.Tex7Frac);
|
||||
posScale = 1.0f / float(1 << m_CurrentVat->g0.PosFrac);
|
||||
tcScale[0] = 1.0f / float(1 << m_CurrentVat->g0.Tex0Frac);
|
||||
tcScale[1] = 1.0f / float(1 << m_CurrentVat->g1.Tex1Frac);
|
||||
tcScale[2] = 1.0f / float(1 << m_CurrentVat->g1.Tex2Frac);
|
||||
tcScale[3] = 1.0f / float(1 << m_CurrentVat->g1.Tex3Frac);
|
||||
tcScale[4] = 1.0f / float(1 << m_CurrentVat->g2.Tex4Frac);
|
||||
tcScale[5] = 1.0f / float(1 << m_CurrentVat->g2.Tex5Frac);
|
||||
tcScale[6] = 1.0f / float(1 << m_CurrentVat->g2.Tex6Frac);
|
||||
tcScale[7] = 1.0f / float(1 << m_CurrentVat->g2.Tex7Frac);
|
||||
|
||||
//TexMtx
|
||||
const u32 tmDesc[8] = {
|
||||
g_VtxDesc.Tex0MatIdx, g_VtxDesc.Tex1MatIdx, g_VtxDesc.Tex2MatIdx, g_VtxDesc.Tex3MatIdx,
|
||||
//TexMtx
|
||||
const u32 tmDesc[8] = {
|
||||
g_VtxDesc.Tex0MatIdx, g_VtxDesc.Tex1MatIdx, g_VtxDesc.Tex2MatIdx, g_VtxDesc.Tex3MatIdx,
|
||||
g_VtxDesc.Tex4MatIdx, g_VtxDesc.Tex5MatIdx, g_VtxDesc.Tex6MatIdx, g_VtxDesc.Tex7MatIdx
|
||||
};
|
||||
// Colors
|
||||
|
||||
// Colors
|
||||
const u32 colDesc[2] = {g_VtxDesc.Color0, g_VtxDesc.Color1};
|
||||
colElements[0] = m_CurrentVat->g0.Color0Elements;
|
||||
colElements[1] = m_CurrentVat->g0.Color1Elements;
|
||||
const u32 colComp[2] = {m_CurrentVat->g0.Color0Comp, m_CurrentVat->g0.Color1Comp};
|
||||
colElements[0] = m_CurrentVat->g0.Color0Elements;
|
||||
colElements[1] = m_CurrentVat->g0.Color1Elements;
|
||||
const u32 colComp[2] = {m_CurrentVat->g0.Color0Comp, m_CurrentVat->g0.Color1Comp};
|
||||
|
||||
// TextureCoord
|
||||
const u32 tcDesc[8] = {
|
||||
g_VtxDesc.Tex0Coord, g_VtxDesc.Tex1Coord, g_VtxDesc.Tex2Coord, g_VtxDesc.Tex3Coord,
|
||||
g_VtxDesc.Tex4Coord, g_VtxDesc.Tex5Coord, g_VtxDesc.Tex6Coord, (const u32)((g_VtxDesc.Hex >> 31) & 3)
|
||||
};
|
||||
const u32 tcElements[8] = {
|
||||
m_CurrentVat->g0.Tex0CoordElements, m_CurrentVat->g1.Tex1CoordElements, m_CurrentVat->g1.Tex2CoordElements,
|
||||
m_CurrentVat->g1.Tex3CoordElements, m_CurrentVat->g1.Tex4CoordElements, m_CurrentVat->g2.Tex5CoordElements,
|
||||
m_CurrentVat->g2.Tex6CoordElements, m_CurrentVat->g2.Tex7CoordElements
|
||||
};
|
||||
const u32 tcElements[8] = {
|
||||
m_CurrentVat->g0.Tex0CoordElements, m_CurrentVat->g1.Tex1CoordElements, m_CurrentVat->g1.Tex2CoordElements,
|
||||
m_CurrentVat->g1.Tex3CoordElements, m_CurrentVat->g1.Tex4CoordElements, m_CurrentVat->g2.Tex5CoordElements,
|
||||
m_CurrentVat->g2.Tex6CoordElements, m_CurrentVat->g2.Tex7CoordElements
|
||||
};
|
||||
|
||||
const u32 tcFormat[8] = {
|
||||
m_CurrentVat->g0.Tex0CoordFormat, m_CurrentVat->g1.Tex1CoordFormat, m_CurrentVat->g1.Tex2CoordFormat,
|
||||
m_CurrentVat->g1.Tex3CoordFormat, m_CurrentVat->g1.Tex4CoordFormat, m_CurrentVat->g2.Tex5CoordFormat,
|
||||
m_CurrentVat->g2.Tex6CoordFormat, m_CurrentVat->g2.Tex7CoordFormat
|
||||
};
|
||||
const u32 tcFormat[8] = {
|
||||
m_CurrentVat->g0.Tex0CoordFormat, m_CurrentVat->g1.Tex1CoordFormat, m_CurrentVat->g1.Tex2CoordFormat,
|
||||
m_CurrentVat->g1.Tex3CoordFormat, m_CurrentVat->g1.Tex4CoordFormat, m_CurrentVat->g2.Tex5CoordFormat,
|
||||
m_CurrentVat->g2.Tex6CoordFormat, m_CurrentVat->g2.Tex7CoordFormat
|
||||
};
|
||||
|
||||
m_VertexSize = 0;
|
||||
|
||||
m_VertexSize = 0;
|
||||
|
||||
// Reset pipeline
|
||||
m_positionLoader = NULL;
|
||||
m_normalLoader = NULL;
|
||||
m_NumAttributeLoaders = 0;
|
||||
m_normalLoader = NULL;
|
||||
m_NumAttributeLoaders = 0;
|
||||
|
||||
// Reset vertex
|
||||
// matrix index from xf regs or cp memory?
|
||||
// Reset vertex
|
||||
// matrix index from xf regs or cp memory?
|
||||
if (swxfregs.MatrixIndexA.PosNormalMtxIdx != MatrixIndexA.PosNormalMtxIdx ||
|
||||
swxfregs.MatrixIndexA.Tex0MtxIdx != MatrixIndexA.Tex0MtxIdx ||
|
||||
swxfregs.MatrixIndexA.Tex1MtxIdx != MatrixIndexA.Tex1MtxIdx ||
|
||||
|
@ -126,39 +128,41 @@ void SWVertexLoader::SetFormat(u8 attributeIndex, u8 primitiveType)
|
|||
}
|
||||
|
||||
#if(1)
|
||||
m_Vertex.posMtx = swxfregs.MatrixIndexA.PosNormalMtxIdx;
|
||||
m_Vertex.texMtx[0] = swxfregs.MatrixIndexA.Tex0MtxIdx;
|
||||
m_Vertex.texMtx[1] = swxfregs.MatrixIndexA.Tex1MtxIdx;
|
||||
m_Vertex.texMtx[2] = swxfregs.MatrixIndexA.Tex2MtxIdx;
|
||||
m_Vertex.texMtx[3] = swxfregs.MatrixIndexA.Tex3MtxIdx;
|
||||
m_Vertex.texMtx[4] = swxfregs.MatrixIndexB.Tex4MtxIdx;
|
||||
m_Vertex.texMtx[5] = swxfregs.MatrixIndexB.Tex5MtxIdx;
|
||||
m_Vertex.texMtx[6] = swxfregs.MatrixIndexB.Tex6MtxIdx;
|
||||
m_Vertex.texMtx[7] = swxfregs.MatrixIndexB.Tex7MtxIdx;
|
||||
m_Vertex.posMtx = swxfregs.MatrixIndexA.PosNormalMtxIdx;
|
||||
m_Vertex.texMtx[0] = swxfregs.MatrixIndexA.Tex0MtxIdx;
|
||||
m_Vertex.texMtx[1] = swxfregs.MatrixIndexA.Tex1MtxIdx;
|
||||
m_Vertex.texMtx[2] = swxfregs.MatrixIndexA.Tex2MtxIdx;
|
||||
m_Vertex.texMtx[3] = swxfregs.MatrixIndexA.Tex3MtxIdx;
|
||||
m_Vertex.texMtx[4] = swxfregs.MatrixIndexB.Tex4MtxIdx;
|
||||
m_Vertex.texMtx[5] = swxfregs.MatrixIndexB.Tex5MtxIdx;
|
||||
m_Vertex.texMtx[6] = swxfregs.MatrixIndexB.Tex6MtxIdx;
|
||||
m_Vertex.texMtx[7] = swxfregs.MatrixIndexB.Tex7MtxIdx;
|
||||
#else
|
||||
m_Vertex.posMtx = MatrixIndexA.PosNormalMtxIdx;
|
||||
m_Vertex.texMtx[0] = MatrixIndexA.Tex0MtxIdx;
|
||||
m_Vertex.texMtx[1] = MatrixIndexA.Tex1MtxIdx;
|
||||
m_Vertex.texMtx[2] = MatrixIndexA.Tex2MtxIdx;
|
||||
m_Vertex.texMtx[3] = MatrixIndexA.Tex3MtxIdx;
|
||||
m_Vertex.texMtx[4] = MatrixIndexB.Tex4MtxIdx;
|
||||
m_Vertex.texMtx[5] = MatrixIndexB.Tex5MtxIdx;
|
||||
m_Vertex.texMtx[6] = MatrixIndexB.Tex6MtxIdx;
|
||||
m_Vertex.texMtx[7] = MatrixIndexB.Tex7MtxIdx;
|
||||
m_Vertex.posMtx = MatrixIndexA.PosNormalMtxIdx;
|
||||
m_Vertex.texMtx[0] = MatrixIndexA.Tex0MtxIdx;
|
||||
m_Vertex.texMtx[1] = MatrixIndexA.Tex1MtxIdx;
|
||||
m_Vertex.texMtx[2] = MatrixIndexA.Tex2MtxIdx;
|
||||
m_Vertex.texMtx[3] = MatrixIndexA.Tex3MtxIdx;
|
||||
m_Vertex.texMtx[4] = MatrixIndexB.Tex4MtxIdx;
|
||||
m_Vertex.texMtx[5] = MatrixIndexB.Tex5MtxIdx;
|
||||
m_Vertex.texMtx[6] = MatrixIndexB.Tex6MtxIdx;
|
||||
m_Vertex.texMtx[7] = MatrixIndexB.Tex7MtxIdx;
|
||||
#endif
|
||||
|
||||
if (g_VtxDesc.PosMatIdx != NOT_PRESENT) {
|
||||
AddAttributeLoader(LoadPosMtx);
|
||||
m_VertexSize++;
|
||||
}
|
||||
if (g_VtxDesc.PosMatIdx != NOT_PRESENT)
|
||||
{
|
||||
AddAttributeLoader(LoadPosMtx);
|
||||
m_VertexSize++;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
if (tmDesc[i] != NOT_PRESENT)
|
||||
{
|
||||
AddAttributeLoader(LoadTexMtx, i);
|
||||
m_VertexSize++;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < 8; ++i)
|
||||
{
|
||||
if (tmDesc[i] != NOT_PRESENT)
|
||||
{
|
||||
AddAttributeLoader(LoadTexMtx, i);
|
||||
m_VertexSize++;
|
||||
}
|
||||
}
|
||||
|
||||
// Write vertex position loader
|
||||
m_positionLoader = VertexLoader_Position::GetFunction(g_VtxDesc.Position, m_CurrentVat->g0.PosFormat, m_CurrentVat->g0.PosElements);
|
||||
|
@ -178,14 +182,15 @@ void SWVertexLoader::SetFormat(u8 attributeIndex, u8 primitiveType)
|
|||
{
|
||||
ERROR_LOG(VIDEO, "VertexLoader_Normal::GetFunction returned zero!");
|
||||
}
|
||||
AddAttributeLoader(LoadNormal);
|
||||
}
|
||||
AddAttributeLoader(LoadNormal);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
switch (colDesc[i])
|
||||
{
|
||||
case NOT_PRESENT:
|
||||
m_colorLoader[i] = NULL;
|
||||
m_colorLoader[i] = NULL;
|
||||
break;
|
||||
case DIRECT:
|
||||
switch (colComp[i])
|
||||
|
@ -198,7 +203,7 @@ void SWVertexLoader::SetFormat(u8 attributeIndex, u8 primitiveType)
|
|||
case FORMAT_32B_8888: m_VertexSize += 4; m_colorLoader[i] = (Color_ReadDirect_32b_8888); break;
|
||||
default: _assert_(0); break;
|
||||
}
|
||||
AddAttributeLoader(LoadColor, i);
|
||||
AddAttributeLoader(LoadColor, i);
|
||||
break;
|
||||
case INDEX8:
|
||||
m_VertexSize += 1;
|
||||
|
@ -212,7 +217,7 @@ void SWVertexLoader::SetFormat(u8 attributeIndex, u8 primitiveType)
|
|||
case FORMAT_32B_8888: m_colorLoader[i] = (Color_ReadIndex8_32b_8888); break;
|
||||
default: _assert_(0); break;
|
||||
}
|
||||
AddAttributeLoader(LoadColor, i);
|
||||
AddAttributeLoader(LoadColor, i);
|
||||
break;
|
||||
case INDEX16:
|
||||
m_VertexSize += 2;
|
||||
|
@ -226,13 +231,14 @@ void SWVertexLoader::SetFormat(u8 attributeIndex, u8 primitiveType)
|
|||
case FORMAT_32B_8888: m_colorLoader[i] = (Color_ReadIndex16_32b_8888); break;
|
||||
default: _assert_(0); break;
|
||||
}
|
||||
AddAttributeLoader(LoadColor, i);
|
||||
AddAttributeLoader(LoadColor, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Texture matrix indices (remove if corresponding texture coordinate isn't enabled)
|
||||
for (int i = 0; i < 8; i++) {
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
const int desc = tcDesc[i];
|
||||
const int format = tcFormat[i];
|
||||
const int elements = tcElements[i];
|
||||
|
@ -244,7 +250,7 @@ void SWVertexLoader::SetFormat(u8 attributeIndex, u8 primitiveType)
|
|||
m_VertexSize += VertexLoader_TextCoord::GetSize(desc, format, elements);
|
||||
if (m_texCoordLoader[i])
|
||||
AddAttributeLoader(LoadTexCoord, i);
|
||||
}
|
||||
}
|
||||
|
||||
// special case if only pos and tex coord 0 and tex coord input is AB11
|
||||
m_TexGenSpecialCase =
|
||||
|
@ -252,80 +258,79 @@ void SWVertexLoader::SetFormat(u8 attributeIndex, u8 primitiveType)
|
|||
(g_VtxDesc.Tex0Coord != NOT_PRESENT) &&
|
||||
(swxfregs.texMtxInfo[0].projection == XF_TEXPROJ_ST);
|
||||
|
||||
|
||||
m_SetupUnit->Init(primitiveType);
|
||||
m_SetupUnit->Init(primitiveType);
|
||||
}
|
||||
|
||||
|
||||
void SWVertexLoader::LoadVertex()
|
||||
{
|
||||
for (int i = 0; i < m_NumAttributeLoaders; i++)
|
||||
m_AttributeLoaders[i].loader(this, &m_Vertex, m_AttributeLoaders[i].index);
|
||||
for (int i = 0; i < m_NumAttributeLoaders; i++)
|
||||
m_AttributeLoaders[i].loader(this, &m_Vertex, m_AttributeLoaders[i].index);
|
||||
|
||||
OutputVertexData* outVertex = m_SetupUnit->GetVertex();
|
||||
OutputVertexData* outVertex = m_SetupUnit->GetVertex();
|
||||
|
||||
// transform input data
|
||||
TransformUnit::TransformPosition(&m_Vertex, outVertex);
|
||||
// transform input data
|
||||
TransformUnit::TransformPosition(&m_Vertex, outVertex);
|
||||
|
||||
if (g_VtxDesc.Normal != NOT_PRESENT)
|
||||
{
|
||||
TransformUnit::TransformNormal(&m_Vertex, m_CurrentVat->g0.NormalElements, outVertex);
|
||||
}
|
||||
if (g_VtxDesc.Normal != NOT_PRESENT)
|
||||
{
|
||||
TransformUnit::TransformNormal(&m_Vertex, m_CurrentVat->g0.NormalElements, outVertex);
|
||||
}
|
||||
|
||||
TransformUnit::TransformColor(&m_Vertex, outVertex);
|
||||
TransformUnit::TransformColor(&m_Vertex, outVertex);
|
||||
|
||||
TransformUnit::TransformTexCoord(&m_Vertex, outVertex, m_TexGenSpecialCase);
|
||||
TransformUnit::TransformTexCoord(&m_Vertex, outVertex, m_TexGenSpecialCase);
|
||||
|
||||
m_SetupUnit->SetupVertex();
|
||||
m_SetupUnit->SetupVertex();
|
||||
|
||||
INCSTAT(swstats.thisFrame.numVerticesLoaded)
|
||||
INCSTAT(swstats.thisFrame.numVerticesLoaded)
|
||||
}
|
||||
|
||||
void SWVertexLoader::AddAttributeLoader(AttributeLoader loader, u8 index)
|
||||
{
|
||||
_assert_msg_(VIDEO, m_NumAttributeLoaders < 21, "Too many attribute loaders");
|
||||
m_AttributeLoaders[m_NumAttributeLoaders].loader = loader;
|
||||
m_AttributeLoaders[m_NumAttributeLoaders++].index = index;
|
||||
_assert_msg_(VIDEO, m_NumAttributeLoaders < 21, "Too many attribute loaders");
|
||||
m_AttributeLoaders[m_NumAttributeLoaders].loader = loader;
|
||||
m_AttributeLoaders[m_NumAttributeLoaders++].index = index;
|
||||
}
|
||||
|
||||
void SWVertexLoader::LoadPosMtx(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 unused)
|
||||
{
|
||||
vertex->posMtx = DataReadU8() & 0x3f;
|
||||
vertex->posMtx = DataReadU8() & 0x3f;
|
||||
}
|
||||
|
||||
void SWVertexLoader::LoadTexMtx(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 index)
|
||||
{
|
||||
vertex->texMtx[index] = DataReadU8() & 0x3f;
|
||||
}
|
||||
vertex->texMtx[index] = DataReadU8() & 0x3f;
|
||||
}
|
||||
|
||||
void SWVertexLoader::LoadPosition(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 unused)
|
||||
{
|
||||
VertexManager::s_pCurBufferPointer = (u8*)&vertex->position;
|
||||
vertexLoader->m_positionLoader();
|
||||
VertexManager::s_pCurBufferPointer = (u8*)&vertex->position;
|
||||
vertexLoader->m_positionLoader();
|
||||
}
|
||||
|
||||
void SWVertexLoader::LoadNormal(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 unused)
|
||||
{
|
||||
VertexManager::s_pCurBufferPointer = (u8*)&vertex->normal;
|
||||
vertexLoader->m_normalLoader();
|
||||
vertexLoader->m_normalLoader();
|
||||
}
|
||||
|
||||
void SWVertexLoader::LoadColor(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 index)
|
||||
{
|
||||
u32 color;
|
||||
VertexManager::s_pCurBufferPointer = (u8*)&color;
|
||||
colIndex = index;
|
||||
vertexLoader->m_colorLoader[index]();
|
||||
u32 color;
|
||||
VertexManager::s_pCurBufferPointer = (u8*)&color;
|
||||
colIndex = index;
|
||||
vertexLoader->m_colorLoader[index]();
|
||||
|
||||
// rgba -> abgr
|
||||
*(u32*)vertex->color[index] = Common::swap32(color);
|
||||
// rgba -> abgr
|
||||
*(u32*)vertex->color[index] = Common::swap32(color);
|
||||
}
|
||||
|
||||
void SWVertexLoader::LoadTexCoord(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 index)
|
||||
{
|
||||
VertexManager::s_pCurBufferPointer = (u8*)&vertex->texCoords[index];
|
||||
tcIndex = index;
|
||||
vertexLoader->m_texCoordLoader[index]();
|
||||
VertexManager::s_pCurBufferPointer = (u8*)&vertex->texCoords[index];
|
||||
tcIndex = index;
|
||||
vertexLoader->m_texCoordLoader[index]();
|
||||
}
|
||||
|
||||
void SWVertexLoader::DoState(PointerWrap &p)
|
||||
|
@ -339,4 +344,4 @@ void SWVertexLoader::DoState(PointerWrap &p)
|
|||
p.Do(m_NumAttributeLoaders);
|
||||
m_SetupUnit->DoState(p);
|
||||
p.Do(m_TexGenSpecialCase);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// Official Git repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _VERTEXLOADER_H_
|
||||
|
@ -28,48 +28,48 @@ class SetupUnit;
|
|||
|
||||
class SWVertexLoader
|
||||
{
|
||||
u32 m_VertexSize;
|
||||
u32 m_VertexSize;
|
||||
|
||||
VAT* m_CurrentVat;
|
||||
|
||||
TPipelineFunction m_positionLoader;
|
||||
TPipelineFunction m_normalLoader;
|
||||
TPipelineFunction m_colorLoader[2];
|
||||
TPipelineFunction m_texCoordLoader[8];
|
||||
VAT* m_CurrentVat;
|
||||
|
||||
InputVertexData m_Vertex;
|
||||
TPipelineFunction m_positionLoader;
|
||||
TPipelineFunction m_normalLoader;
|
||||
TPipelineFunction m_colorLoader[2];
|
||||
TPipelineFunction m_texCoordLoader[8];
|
||||
|
||||
typedef void (*AttributeLoader)(SWVertexLoader*, InputVertexData*, u8);
|
||||
struct AttrLoaderCall
|
||||
{
|
||||
AttributeLoader loader;
|
||||
u8 index;
|
||||
};
|
||||
AttrLoaderCall m_AttributeLoaders[1+8+1+1+2+8];
|
||||
int m_NumAttributeLoaders;
|
||||
void AddAttributeLoader(AttributeLoader loader, u8 index=0);
|
||||
InputVertexData m_Vertex;
|
||||
|
||||
// attribute loader functions
|
||||
static void LoadPosMtx(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 unused);
|
||||
static void LoadTexMtx(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 index);
|
||||
static void LoadPosition(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 unused);
|
||||
static void LoadNormal(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 unused);
|
||||
static void LoadColor(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 index);
|
||||
static void LoadTexCoord(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 index);
|
||||
typedef void (*AttributeLoader)(SWVertexLoader*, InputVertexData*, u8);
|
||||
struct AttrLoaderCall
|
||||
{
|
||||
AttributeLoader loader;
|
||||
u8 index;
|
||||
};
|
||||
AttrLoaderCall m_AttributeLoaders[1+8+1+1+2+8];
|
||||
int m_NumAttributeLoaders;
|
||||
void AddAttributeLoader(AttributeLoader loader, u8 index=0);
|
||||
|
||||
SetupUnit *m_SetupUnit;
|
||||
// attribute loader functions
|
||||
static void LoadPosMtx(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 unused);
|
||||
static void LoadTexMtx(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 index);
|
||||
static void LoadPosition(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 unused);
|
||||
static void LoadNormal(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 unused);
|
||||
static void LoadColor(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 index);
|
||||
static void LoadTexCoord(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 index);
|
||||
|
||||
SetupUnit *m_SetupUnit;
|
||||
|
||||
bool m_TexGenSpecialCase;
|
||||
|
||||
public:
|
||||
SWVertexLoader();
|
||||
~SWVertexLoader();
|
||||
SWVertexLoader();
|
||||
~SWVertexLoader();
|
||||
|
||||
void SetFormat(u8 attributeIndex, u8 primitiveType);
|
||||
void SetFormat(u8 attributeIndex, u8 primitiveType);
|
||||
|
||||
u32 GetVertexSize() { return m_VertexSize; }
|
||||
u32 GetVertexSize() { return m_VertexSize; }
|
||||
|
||||
void LoadVertex();
|
||||
void LoadVertex();
|
||||
void DoState(PointerWrap &p);
|
||||
};
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// Official Git repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "FileUtil.h"
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// Official Git repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _VIDEOSOFTWARE_CONFIG_H_
|
||||
|
@ -25,14 +25,14 @@
|
|||
// NEVER inherit from this class.
|
||||
struct SWVideoConfig : NonCopyable
|
||||
{
|
||||
SWVideoConfig();
|
||||
void Load(const char* ini_file);
|
||||
void Save(const char* ini_file);
|
||||
SWVideoConfig();
|
||||
void Load(const char* ini_file);
|
||||
void Save(const char* ini_file);
|
||||
|
||||
// General
|
||||
bool bFullscreen;
|
||||
bool bHideCursor;
|
||||
bool renderToMainframe;
|
||||
// General
|
||||
bool bFullscreen;
|
||||
bool bHideCursor;
|
||||
bool renderToMainframe;
|
||||
|
||||
bool bHwRasterizer;
|
||||
|
||||
|
@ -40,18 +40,18 @@ struct SWVideoConfig : NonCopyable
|
|||
bool bZComploc;
|
||||
bool bZFreeze;
|
||||
|
||||
bool bShowStats;
|
||||
bool bShowStats;
|
||||
|
||||
bool bDumpTextures;
|
||||
bool bDumpObjects;
|
||||
bool bDumpFrames;
|
||||
bool bDumpTextures;
|
||||
bool bDumpObjects;
|
||||
bool bDumpFrames;
|
||||
|
||||
// Debug only
|
||||
bool bDumpTevStages;
|
||||
bool bDumpTevStages;
|
||||
bool bDumpTevTextureFetches;
|
||||
|
||||
u32 drawStart;
|
||||
u32 drawEnd;
|
||||
u32 drawStart;
|
||||
u32 drawEnd;
|
||||
};
|
||||
|
||||
extern SWVideoConfig g_SWVideoConfig;
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// Official Git repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
|
||||
|
@ -213,30 +213,32 @@ u32 VideoSoftware::Video_AccessEFB(EFBAccessType type, u32 x, u32 y, u32 InputDa
|
|||
{
|
||||
u32 value = 0;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case PEEK_Z:
|
||||
{
|
||||
value = EfbInterface::GetDepth(x, y);
|
||||
break;
|
||||
}
|
||||
case POKE_Z:
|
||||
break;
|
||||
case PEEK_COLOR:
|
||||
{
|
||||
u32 color = 0;
|
||||
EfbInterface::GetColor(x, y, (u8*)&color);
|
||||
switch (type)
|
||||
{
|
||||
case PEEK_Z:
|
||||
{
|
||||
value = EfbInterface::GetDepth(x, y);
|
||||
break;
|
||||
}
|
||||
|
||||
// rgba to argb
|
||||
value = (color >> 8) | (color & 0xff) << 24;
|
||||
break;
|
||||
}
|
||||
|
||||
case POKE_COLOR:
|
||||
break;
|
||||
}
|
||||
case POKE_Z:
|
||||
break;
|
||||
|
||||
return value;
|
||||
case PEEK_COLOR:
|
||||
{
|
||||
u32 color = 0;
|
||||
EfbInterface::GetColor(x, y, (u8*)&color);
|
||||
|
||||
// rgba to argb
|
||||
value = (color >> 8) | (color & 0xff) << 24;
|
||||
break;
|
||||
}
|
||||
|
||||
case POKE_COLOR:
|
||||
break;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
u32 VideoSoftware::Video_GetQueryResult(PerfQueryType type)
|
||||
|
@ -256,7 +258,7 @@ bool VideoSoftware::Video_Screenshot(const char *_szFilename)
|
|||
void VideoSoftware::Video_EnterLoop()
|
||||
{
|
||||
std::lock_guard<std::mutex> lk(m_csSWVidOccupied);
|
||||
fifoStateRun = true;
|
||||
fifoStateRun = true;
|
||||
|
||||
while (fifoStateRun)
|
||||
{
|
||||
|
@ -279,7 +281,7 @@ void VideoSoftware::Video_EnterLoop()
|
|||
|
||||
void VideoSoftware::Video_ExitLoop()
|
||||
{
|
||||
fifoStateRun = false;
|
||||
fifoStateRun = false;
|
||||
}
|
||||
|
||||
// TODO : could use the OSD class in video common, we would need to implement the Renderer class
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// Official Git repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "SetupUnit.h"
|
||||
|
@ -27,7 +27,7 @@ void SetupUnit::Init(u8 primitiveType)
|
|||
{
|
||||
m_PrimType = primitiveType;
|
||||
|
||||
m_VertexCounter = 0;
|
||||
m_VertexCounter = 0;
|
||||
m_VertPointer[0] = &m_Vertices[0];
|
||||
m_VertPointer[1] = &m_Vertices[1];
|
||||
m_VertPointer[2] = &m_Vertices[2];
|
||||
|
@ -36,130 +36,130 @@ void SetupUnit::Init(u8 primitiveType)
|
|||
|
||||
void SetupUnit::SetupVertex()
|
||||
{
|
||||
switch(m_PrimType)
|
||||
{
|
||||
case GX_DRAW_QUADS:
|
||||
SetupQuad();
|
||||
break;
|
||||
case GX_DRAW_TRIANGLES:
|
||||
SetupTriangle();
|
||||
break;
|
||||
case GX_DRAW_TRIANGLE_STRIP:
|
||||
SetupTriStrip();
|
||||
break;
|
||||
case GX_DRAW_TRIANGLE_FAN:
|
||||
SetupTriFan();
|
||||
break;
|
||||
case GX_DRAW_LINES:
|
||||
SetupLine();
|
||||
break;
|
||||
case GX_DRAW_LINE_STRIP:
|
||||
SetupLineStrip();
|
||||
break;
|
||||
case GX_DRAW_POINTS:
|
||||
SetupPoint();
|
||||
break;
|
||||
}
|
||||
switch(m_PrimType)
|
||||
{
|
||||
case GX_DRAW_QUADS:
|
||||
SetupQuad();
|
||||
break;
|
||||
case GX_DRAW_TRIANGLES:
|
||||
SetupTriangle();
|
||||
break;
|
||||
case GX_DRAW_TRIANGLE_STRIP:
|
||||
SetupTriStrip();
|
||||
break;
|
||||
case GX_DRAW_TRIANGLE_FAN:
|
||||
SetupTriFan();
|
||||
break;
|
||||
case GX_DRAW_LINES:
|
||||
SetupLine();
|
||||
break;
|
||||
case GX_DRAW_LINE_STRIP:
|
||||
SetupLineStrip();
|
||||
break;
|
||||
case GX_DRAW_POINTS:
|
||||
SetupPoint();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SetupUnit::SetupQuad()
|
||||
{
|
||||
if (m_VertexCounter < 2)
|
||||
{
|
||||
m_VertexCounter++;
|
||||
m_VertWritePointer = m_VertPointer[m_VertexCounter];
|
||||
return;
|
||||
}
|
||||
void SetupUnit::SetupQuad()
|
||||
{
|
||||
if (m_VertexCounter < 2)
|
||||
{
|
||||
m_VertexCounter++;
|
||||
m_VertWritePointer = m_VertPointer[m_VertexCounter];
|
||||
return;
|
||||
}
|
||||
|
||||
Clipper::ProcessTriangle(m_VertPointer[0], m_VertPointer[1], m_VertPointer[2]);
|
||||
Clipper::ProcessTriangle(m_VertPointer[0], m_VertPointer[1], m_VertPointer[2]);
|
||||
|
||||
m_VertexCounter++;
|
||||
m_VertexCounter &= 3;
|
||||
m_VertWritePointer = &m_Vertices[m_VertexCounter & 1];
|
||||
OutputVertexData* temp = m_VertPointer[1];
|
||||
m_VertPointer[1] = m_VertPointer[2];
|
||||
m_VertPointer[2] = temp;
|
||||
}
|
||||
m_VertexCounter++;
|
||||
m_VertexCounter &= 3;
|
||||
m_VertWritePointer = &m_Vertices[m_VertexCounter & 1];
|
||||
OutputVertexData* temp = m_VertPointer[1];
|
||||
m_VertPointer[1] = m_VertPointer[2];
|
||||
m_VertPointer[2] = temp;
|
||||
}
|
||||
|
||||
void SetupUnit::SetupTriangle()
|
||||
{
|
||||
if (m_VertexCounter < 2)
|
||||
{
|
||||
m_VertexCounter++;
|
||||
m_VertWritePointer = m_VertPointer[m_VertexCounter];
|
||||
return;
|
||||
}
|
||||
if (m_VertexCounter < 2)
|
||||
{
|
||||
m_VertexCounter++;
|
||||
m_VertWritePointer = m_VertPointer[m_VertexCounter];
|
||||
return;
|
||||
}
|
||||
|
||||
Clipper::ProcessTriangle(m_VertPointer[0], m_VertPointer[1], m_VertPointer[2]);
|
||||
Clipper::ProcessTriangle(m_VertPointer[0], m_VertPointer[1], m_VertPointer[2]);
|
||||
|
||||
m_VertexCounter = 0;
|
||||
m_VertWritePointer = m_VertPointer[0];
|
||||
m_VertexCounter = 0;
|
||||
m_VertWritePointer = m_VertPointer[0];
|
||||
}
|
||||
|
||||
void SetupUnit::SetupTriStrip()
|
||||
{
|
||||
if (m_VertexCounter < 2)
|
||||
{
|
||||
m_VertexCounter++;
|
||||
m_VertWritePointer = m_VertPointer[m_VertexCounter];
|
||||
return;
|
||||
}
|
||||
if (m_VertexCounter < 2)
|
||||
{
|
||||
m_VertexCounter++;
|
||||
m_VertWritePointer = m_VertPointer[m_VertexCounter];
|
||||
return;
|
||||
}
|
||||
|
||||
Clipper::ProcessTriangle(m_VertPointer[0], m_VertPointer[1], m_VertPointer[2]);
|
||||
Clipper::ProcessTriangle(m_VertPointer[0], m_VertPointer[1], m_VertPointer[2]);
|
||||
|
||||
m_VertexCounter++;
|
||||
m_VertPointer[2 - (m_VertexCounter & 1)] = m_VertPointer[0];
|
||||
m_VertWritePointer = m_VertPointer[0];
|
||||
m_VertexCounter++;
|
||||
m_VertPointer[2 - (m_VertexCounter & 1)] = m_VertPointer[0];
|
||||
m_VertWritePointer = m_VertPointer[0];
|
||||
|
||||
m_VertPointer[0] = &m_Vertices[(m_VertexCounter + 1) % 3];
|
||||
m_VertPointer[0] = &m_Vertices[(m_VertexCounter + 1) % 3];
|
||||
}
|
||||
|
||||
void SetupUnit::SetupTriFan()
|
||||
{
|
||||
if (m_VertexCounter < 2)
|
||||
{
|
||||
m_VertexCounter++;
|
||||
m_VertWritePointer = m_VertPointer[m_VertexCounter];
|
||||
return;
|
||||
}
|
||||
if (m_VertexCounter < 2)
|
||||
{
|
||||
m_VertexCounter++;
|
||||
m_VertWritePointer = m_VertPointer[m_VertexCounter];
|
||||
return;
|
||||
}
|
||||
|
||||
Clipper::ProcessTriangle(m_VertPointer[0], m_VertPointer[1], m_VertPointer[2]);
|
||||
Clipper::ProcessTriangle(m_VertPointer[0], m_VertPointer[1], m_VertPointer[2]);
|
||||
|
||||
m_VertexCounter++;
|
||||
m_VertPointer[1] = m_VertPointer[2];
|
||||
m_VertPointer[2] = &m_Vertices[2 - (m_VertexCounter & 1)];
|
||||
m_VertexCounter++;
|
||||
m_VertPointer[1] = m_VertPointer[2];
|
||||
m_VertPointer[2] = &m_Vertices[2 - (m_VertexCounter & 1)];
|
||||
|
||||
m_VertWritePointer = m_VertPointer[2];
|
||||
m_VertWritePointer = m_VertPointer[2];
|
||||
}
|
||||
|
||||
void SetupUnit::SetupLine()
|
||||
{
|
||||
if (m_VertexCounter < 1)
|
||||
{
|
||||
m_VertexCounter++;
|
||||
m_VertWritePointer = m_VertPointer[m_VertexCounter];
|
||||
return;
|
||||
}
|
||||
{
|
||||
m_VertexCounter++;
|
||||
m_VertWritePointer = m_VertPointer[m_VertexCounter];
|
||||
return;
|
||||
}
|
||||
|
||||
Clipper::ProcessLine(m_VertPointer[0], m_VertPointer[1]);
|
||||
Clipper::ProcessLine(m_VertPointer[0], m_VertPointer[1]);
|
||||
|
||||
m_VertexCounter = 0;
|
||||
m_VertWritePointer = m_VertPointer[0];
|
||||
m_VertexCounter = 0;
|
||||
m_VertWritePointer = m_VertPointer[0];
|
||||
}
|
||||
|
||||
void SetupUnit::SetupLineStrip()
|
||||
{
|
||||
if (m_VertexCounter < 1)
|
||||
{
|
||||
m_VertexCounter++;
|
||||
{
|
||||
m_VertexCounter++;
|
||||
m_VertWritePointer = m_VertPointer[m_VertexCounter];
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
m_VertexCounter++;
|
||||
|
||||
Clipper::ProcessLine(m_VertPointer[0], m_VertPointer[1]);
|
||||
Clipper::ProcessLine(m_VertPointer[0], m_VertPointer[1]);
|
||||
|
||||
m_VertWritePointer = m_VertPointer[0];
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// Official Git repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
|
||||
|
@ -25,27 +25,27 @@
|
|||
|
||||
class SetupUnit
|
||||
{
|
||||
u8 m_PrimType;
|
||||
int m_VertexCounter;
|
||||
u8 m_PrimType;
|
||||
int m_VertexCounter;
|
||||
|
||||
OutputVertexData m_Vertices[3];
|
||||
OutputVertexData *m_VertPointer[3];
|
||||
OutputVertexData *m_VertWritePointer;
|
||||
|
||||
void SetupQuad();
|
||||
void SetupTriangle();
|
||||
void SetupTriStrip();
|
||||
void SetupTriFan();
|
||||
void SetupLine();
|
||||
void SetupLineStrip();
|
||||
void SetupPoint();
|
||||
OutputVertexData m_Vertices[3];
|
||||
OutputVertexData *m_VertPointer[3];
|
||||
OutputVertexData *m_VertWritePointer;
|
||||
|
||||
void SetupQuad();
|
||||
void SetupTriangle();
|
||||
void SetupTriStrip();
|
||||
void SetupTriFan();
|
||||
void SetupLine();
|
||||
void SetupLineStrip();
|
||||
void SetupPoint();
|
||||
|
||||
public:
|
||||
void Init(u8 primitiveType);
|
||||
void Init(u8 primitiveType);
|
||||
|
||||
OutputVertexData* GetVertex() { return m_VertWritePointer; }
|
||||
OutputVertexData* GetVertex() { return m_VertWritePointer; }
|
||||
|
||||
void SetupVertex();
|
||||
void SetupVertex();
|
||||
void DoState(PointerWrap &p);
|
||||
};
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -12,7 +12,7 @@
|
|||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// Official Git repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _TEV_H_
|
||||
|
@ -23,12 +23,13 @@
|
|||
|
||||
class Tev
|
||||
{
|
||||
struct InputRegType {
|
||||
unsigned a : 8;
|
||||
unsigned b : 8;
|
||||
unsigned c : 8;
|
||||
signed d : 11;
|
||||
};
|
||||
struct InputRegType
|
||||
{
|
||||
unsigned a : 8;
|
||||
unsigned b : 8;
|
||||
unsigned c : 8;
|
||||
signed d : 11;
|
||||
};
|
||||
|
||||
struct TextureCoordinateType
|
||||
{
|
||||
|
@ -36,26 +37,26 @@ class Tev
|
|||
signed t : 24;
|
||||
};
|
||||
|
||||
// color order: ABGR
|
||||
s16 Reg[4][4];
|
||||
s16 KonstantColors[4][4];
|
||||
s16 TexColor[4];
|
||||
s16 RasColor[4];
|
||||
s16 StageKonst[4];
|
||||
s16 Zero16[4];
|
||||
|
||||
// color order: ABGR
|
||||
s16 Reg[4][4];
|
||||
s16 KonstantColors[4][4];
|
||||
s16 TexColor[4];
|
||||
s16 RasColor[4];
|
||||
s16 StageKonst[4];
|
||||
s16 Zero16[4];
|
||||
|
||||
s16 FixedConstants[9];
|
||||
u8 AlphaBump;
|
||||
u8 IndirectTex[4][4];
|
||||
u8 IndirectTex[4][4];
|
||||
TextureCoordinateType TexCoord;
|
||||
|
||||
s16 *m_ColorInputLUT[16][3];
|
||||
s16 *m_AlphaInputLUT[8]; // values must point to ABGR color
|
||||
s16 *m_KonstLUT[32][4];
|
||||
u8 *m_RasColorLUT[8];
|
||||
s16 m_BiasLUT[4];
|
||||
u8 m_ScaleLShiftLUT[4];
|
||||
u8 m_ScaleRShiftLUT[4];
|
||||
s16 *m_ColorInputLUT[16][3];
|
||||
s16 *m_AlphaInputLUT[8]; // values must point to ABGR color
|
||||
s16 *m_KonstLUT[32][4];
|
||||
u8 *m_RasColorLUT[8];
|
||||
s16 m_BiasLUT[4];
|
||||
u8 m_ScaleLShiftLUT[4];
|
||||
u8 m_ScaleRShiftLUT[4];
|
||||
|
||||
// enumeration for color input LUT
|
||||
enum
|
||||
|
@ -72,29 +73,29 @@ class Tev
|
|||
INDIRECT = 32
|
||||
};
|
||||
|
||||
void SetRasColor(int colorChan, int swaptable);
|
||||
void SetRasColor(int colorChan, int swaptable);
|
||||
|
||||
void DrawColorRegular(TevStageCombiner::ColorCombiner &cc);
|
||||
void DrawColorCompare(TevStageCombiner::ColorCombiner &cc);
|
||||
void DrawAlphaRegular(TevStageCombiner::AlphaCombiner &ac);
|
||||
void DrawAlphaCompare(TevStageCombiner::AlphaCombiner &ac);
|
||||
void DrawColorRegular(TevStageCombiner::ColorCombiner &cc);
|
||||
void DrawColorCompare(TevStageCombiner::ColorCombiner &cc);
|
||||
void DrawAlphaRegular(TevStageCombiner::AlphaCombiner &ac);
|
||||
void DrawAlphaCompare(TevStageCombiner::AlphaCombiner &ac);
|
||||
|
||||
void Indirect(unsigned int stageNum, s32 s, s32 t);
|
||||
void Indirect(unsigned int stageNum, s32 s, s32 t);
|
||||
|
||||
public:
|
||||
s32 Position[3];
|
||||
u8 Color[2][4]; // must be RGBA for correct swap table ordering
|
||||
TextureCoordinateType Uv[8];
|
||||
s32 IndirectLod[4];
|
||||
u8 Color[2][4]; // must be RGBA for correct swap table ordering
|
||||
TextureCoordinateType Uv[8];
|
||||
s32 IndirectLod[4];
|
||||
bool IndirectLinear[4];
|
||||
s32 TextureLod[16];
|
||||
bool TextureLinear[16];
|
||||
|
||||
void Init();
|
||||
void Init();
|
||||
|
||||
void Draw();
|
||||
void Draw();
|
||||
|
||||
void SetRegColor(int reg, int comp, bool konst, s16 color);
|
||||
void SetRegColor(int reg, int comp, bool konst, s16 color);
|
||||
|
||||
enum { ALP_C, BLU_C, GRN_C, RED_C };
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -12,7 +12,7 @@
|
|||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// Official Git repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
|
||||
|
@ -23,7 +23,7 @@
|
|||
|
||||
namespace TextureEncoder
|
||||
{
|
||||
void Encode(u8 *dest_ptr);
|
||||
void Encode(u8 *dest_ptr);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// Official Git repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
|
||||
|
@ -30,51 +30,51 @@ namespace TextureSampler
|
|||
|
||||
inline void WrapCoord(int &coord, int wrapMode, int imageSize)
|
||||
{
|
||||
switch (wrapMode)
|
||||
{
|
||||
case 0: // clamp
|
||||
coord = (coord>imageSize)?imageSize:(coord<0)?0:coord;
|
||||
break;
|
||||
case 1: // wrap
|
||||
coord = coord % (imageSize + 1);
|
||||
coord = (coord<0)?imageSize+coord:coord;
|
||||
break;
|
||||
case 2: // mirror
|
||||
{
|
||||
int sizePlus1 = imageSize + 1;
|
||||
int div = coord / sizePlus1;
|
||||
coord = coord - (div * sizePlus1);
|
||||
coord = (coord<0)?-coord:coord;
|
||||
coord = (div&1)?imageSize - coord:coord;
|
||||
}
|
||||
break;
|
||||
}
|
||||
switch (wrapMode)
|
||||
{
|
||||
case 0: // clamp
|
||||
coord = (coord>imageSize)?imageSize:(coord<0)?0:coord;
|
||||
break;
|
||||
case 1: // wrap
|
||||
coord = coord % (imageSize + 1);
|
||||
coord = (coord<0)?imageSize+coord:coord;
|
||||
break;
|
||||
case 2: // mirror
|
||||
{
|
||||
int sizePlus1 = imageSize + 1;
|
||||
int div = coord / sizePlus1;
|
||||
coord = coord - (div * sizePlus1);
|
||||
coord = (coord<0)?-coord:coord;
|
||||
coord = (div&1)?imageSize - coord:coord;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
inline void SetTexel(u8 *inTexel, u32 *outTexel, u32 fract)
|
||||
{
|
||||
outTexel[0] = inTexel[0] * fract;
|
||||
outTexel[1] = inTexel[1] * fract;
|
||||
outTexel[2] = inTexel[2] * fract;
|
||||
outTexel[3] = inTexel[3] * fract;
|
||||
outTexel[0] = inTexel[0] * fract;
|
||||
outTexel[1] = inTexel[1] * fract;
|
||||
outTexel[2] = inTexel[2] * fract;
|
||||
outTexel[3] = inTexel[3] * fract;
|
||||
}
|
||||
|
||||
inline void AddTexel(u8 *inTexel, u32 *outTexel, u32 fract)
|
||||
{
|
||||
outTexel[0] += inTexel[0] * fract;
|
||||
outTexel[1] += inTexel[1] * fract;
|
||||
outTexel[2] += inTexel[2] * fract;
|
||||
outTexel[3] += inTexel[3] * fract;
|
||||
outTexel[0] += inTexel[0] * fract;
|
||||
outTexel[1] += inTexel[1] * fract;
|
||||
outTexel[2] += inTexel[2] * fract;
|
||||
outTexel[3] += inTexel[3] * fract;
|
||||
}
|
||||
|
||||
void Sample(s32 s, s32 t, s32 lod, bool linear, u8 texmap, u8 *sample)
|
||||
{
|
||||
int baseMip = 0;
|
||||
int baseMip = 0;
|
||||
bool mipLinear = false;
|
||||
|
||||
#if (ALLOW_MIPMAP)
|
||||
FourTexUnits& texUnit = bpmem.tex[(texmap >> 2) & 1];
|
||||
TexMode0& tm0 = texUnit.texMode0[texmap & 3];
|
||||
TexMode0& tm0 = texUnit.texMode0[texmap & 3];
|
||||
|
||||
s32 lodFract = lod & 0xf;
|
||||
|
||||
|
@ -91,7 +91,7 @@ void Sample(s32 s, s32 t, s32 lod, bool linear, u8 texmap, u8 *sample)
|
|||
if (mipLinear)
|
||||
{
|
||||
u8 sampledTex[4];
|
||||
u32 texel[4];
|
||||
u32 texel[4];
|
||||
|
||||
SampleMip(s, t, baseMip, linear, texmap, sampledTex);
|
||||
SetTexel(sampledTex, texel, (16 - lodFract));
|
||||
|
@ -100,25 +100,25 @@ void Sample(s32 s, s32 t, s32 lod, bool linear, u8 texmap, u8 *sample)
|
|||
AddTexel(sampledTex, texel, lodFract);
|
||||
|
||||
sample[0] = (u8)(texel[0] >> 4);
|
||||
sample[1] = (u8)(texel[1] >> 4);
|
||||
sample[2] = (u8)(texel[2] >> 4);
|
||||
sample[3] = (u8)(texel[3] >> 4);
|
||||
sample[1] = (u8)(texel[1] >> 4);
|
||||
sample[2] = (u8)(texel[2] >> 4);
|
||||
sample[3] = (u8)(texel[3] >> 4);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
SampleMip(s, t, baseMip, linear, texmap, sample);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SampleMip(s32 s, s32 t, s32 mip, bool linear, u8 texmap, u8 *sample)
|
||||
{
|
||||
FourTexUnits& texUnit = bpmem.tex[(texmap >> 2) & 1];
|
||||
u8 subTexmap = texmap & 3;
|
||||
u8 subTexmap = texmap & 3;
|
||||
|
||||
TexMode0& tm0 = texUnit.texMode0[subTexmap];
|
||||
TexImage0& ti0 = texUnit.texImage0[subTexmap];
|
||||
TexTLUT& texTlut = texUnit.texTlut[subTexmap];
|
||||
TexMode0& tm0 = texUnit.texMode0[subTexmap];
|
||||
TexImage0& ti0 = texUnit.texImage0[subTexmap];
|
||||
TexTLUT& texTlut = texUnit.texTlut[subTexmap];
|
||||
|
||||
u8 *imageSrc, *imageSrcOdd = NULL;
|
||||
if (texUnit.texImage1[subTexmap].image_type)
|
||||
|
@ -129,7 +129,7 @@ void SampleMip(s32 s, s32 t, s32 mip, bool linear, u8 texmap, u8 *sample)
|
|||
}
|
||||
else
|
||||
{
|
||||
u32 imageBase = texUnit.texImage3[subTexmap].image_base << 5;
|
||||
u32 imageBase = texUnit.texImage3[subTexmap].image_base << 5;
|
||||
imageSrc = Memory::GetPointer(imageBase);
|
||||
}
|
||||
|
||||
|
@ -167,8 +167,8 @@ void SampleMip(s32 s, s32 t, s32 mip, bool linear, u8 texmap, u8 *sample)
|
|||
}
|
||||
}
|
||||
|
||||
if (linear)
|
||||
{
|
||||
if (linear)
|
||||
{
|
||||
// offset linear sampling
|
||||
s -= 64;
|
||||
t -= 64;
|
||||
|
@ -179,18 +179,18 @@ void SampleMip(s32 s, s32 t, s32 mip, bool linear, u8 texmap, u8 *sample)
|
|||
|
||||
// linear sampling
|
||||
int imageSPlus1 = imageS + 1;
|
||||
int fractS = s & 0x7f;
|
||||
|
||||
int imageTPlus1 = imageT + 1;
|
||||
int fractT = t & 0x7f;
|
||||
int fractS = s & 0x7f;
|
||||
|
||||
u8 sampledTex[4];
|
||||
u32 texel[4];
|
||||
int imageTPlus1 = imageT + 1;
|
||||
int fractT = t & 0x7f;
|
||||
|
||||
WrapCoord(imageS, tm0.wrap_s, imageWidth);
|
||||
WrapCoord(imageT, tm0.wrap_t, imageHeight);
|
||||
WrapCoord(imageSPlus1, tm0.wrap_s, imageWidth);
|
||||
WrapCoord(imageTPlus1, tm0.wrap_t, imageHeight);
|
||||
u8 sampledTex[4];
|
||||
u32 texel[4];
|
||||
|
||||
WrapCoord(imageS, tm0.wrap_s, imageWidth);
|
||||
WrapCoord(imageT, tm0.wrap_t, imageHeight);
|
||||
WrapCoord(imageSPlus1, tm0.wrap_s, imageWidth);
|
||||
WrapCoord(imageTPlus1, tm0.wrap_t, imageHeight);
|
||||
|
||||
if (!(ti0.format == GX_TF_RGBA8 && texUnit.texImage1[subTexmap].image_type))
|
||||
{
|
||||
|
@ -221,26 +221,26 @@ void SampleMip(s32 s, s32 t, s32 mip, bool linear, u8 texmap, u8 *sample)
|
|||
AddTexel(sampledTex, texel, (fractS) * (fractT));
|
||||
}
|
||||
|
||||
sample[0] = (u8)(texel[0] >> 14);
|
||||
sample[1] = (u8)(texel[1] >> 14);
|
||||
sample[2] = (u8)(texel[2] >> 14);
|
||||
sample[3] = (u8)(texel[3] >> 14);
|
||||
}
|
||||
else
|
||||
{
|
||||
sample[0] = (u8)(texel[0] >> 14);
|
||||
sample[1] = (u8)(texel[1] >> 14);
|
||||
sample[2] = (u8)(texel[2] >> 14);
|
||||
sample[3] = (u8)(texel[3] >> 14);
|
||||
}
|
||||
else
|
||||
{
|
||||
// integer part of sample location
|
||||
int imageS = s >> 7;
|
||||
int imageT = t >> 7;
|
||||
|
||||
// nearest neighbor sampling
|
||||
// nearest neighbor sampling
|
||||
WrapCoord(imageS, tm0.wrap_s, imageWidth);
|
||||
WrapCoord(imageT, tm0.wrap_t, imageHeight);
|
||||
WrapCoord(imageT, tm0.wrap_t, imageHeight);
|
||||
|
||||
if (!(ti0.format == GX_TF_RGBA8 && texUnit.texImage1[subTexmap].image_type))
|
||||
TexDecoder_DecodeTexel(sample, imageSrc, imageS, imageT, imageWidth, ti0.format, tlutAddress, texTlut.tlut_format);
|
||||
TexDecoder_DecodeTexel(sample, imageSrc, imageS, imageT, imageWidth, ti0.format, tlutAddress, texTlut.tlut_format);
|
||||
else
|
||||
TexDecoder_DecodeTexelRGBA8FromTmem(sample, imageSrc, imageSrcOdd, imageS, imageT, imageWidth);
|
||||
}
|
||||
TexDecoder_DecodeTexelRGBA8FromTmem(sample, imageSrc, imageSrcOdd, imageS, imageT, imageWidth);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// Official Git repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _TEXTURESAMPLER_H_
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// Official Git repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "Common.h"
|
||||
|
@ -33,114 +33,114 @@ namespace TransformUnit
|
|||
|
||||
void MultiplyVec2Mat24(const Vec3 &vec, const float *mat, Vec3 &result)
|
||||
{
|
||||
result.x = mat[0] * vec.x + mat[1] * vec.y + mat[2] + mat[3];
|
||||
result.y = mat[4] * vec.x + mat[5] * vec.y + mat[6] + mat[7];
|
||||
result.x = mat[0] * vec.x + mat[1] * vec.y + mat[2] + mat[3];
|
||||
result.y = mat[4] * vec.x + mat[5] * vec.y + mat[6] + mat[7];
|
||||
result.z = 1.0f;
|
||||
}
|
||||
|
||||
void MultiplyVec2Mat34(const Vec3 &vec, const float *mat, Vec3 &result)
|
||||
{
|
||||
result.x = mat[0] * vec.x + mat[1] * vec.y + mat[2] + mat[3];
|
||||
result.y = mat[4] * vec.x + mat[5] * vec.y + mat[6] + mat[7];
|
||||
result.z = mat[8] * vec.x + mat[9] * vec.y + mat[10] + mat[11];
|
||||
result.x = mat[0] * vec.x + mat[1] * vec.y + mat[2] + mat[3];
|
||||
result.y = mat[4] * vec.x + mat[5] * vec.y + mat[6] + mat[7];
|
||||
result.z = mat[8] * vec.x + mat[9] * vec.y + mat[10] + mat[11];
|
||||
}
|
||||
|
||||
void MultiplyVec3Mat33(const Vec3 &vec, const float *mat, Vec3 &result)
|
||||
{
|
||||
result.x = mat[0] * vec.x + mat[1] * vec.y + mat[2] * vec.z;
|
||||
result.y = mat[3] * vec.x + mat[4] * vec.y + mat[5] * vec.z;
|
||||
result.z = mat[6] * vec.x + mat[7] * vec.y + mat[8] * vec.z;
|
||||
result.x = mat[0] * vec.x + mat[1] * vec.y + mat[2] * vec.z;
|
||||
result.y = mat[3] * vec.x + mat[4] * vec.y + mat[5] * vec.z;
|
||||
result.z = mat[6] * vec.x + mat[7] * vec.y + mat[8] * vec.z;
|
||||
}
|
||||
|
||||
void MultiplyVec3Mat24(const Vec3 &vec, const float *mat, Vec3 &result)
|
||||
{
|
||||
result.x = mat[0] * vec.x + mat[1] * vec.y + mat[2] * vec.z + mat[3];
|
||||
result.y = mat[4] * vec.x + mat[5] * vec.y + mat[6] * vec.z + mat[7];
|
||||
result.z = 1.0f;
|
||||
result.x = mat[0] * vec.x + mat[1] * vec.y + mat[2] * vec.z + mat[3];
|
||||
result.y = mat[4] * vec.x + mat[5] * vec.y + mat[6] * vec.z + mat[7];
|
||||
result.z = 1.0f;
|
||||
}
|
||||
|
||||
void MultiplyVec3Mat34(const Vec3 &vec, const float *mat, Vec3 &result)
|
||||
{
|
||||
result.x = mat[0] * vec.x + mat[1] * vec.y + mat[2] * vec.z + mat[3];
|
||||
result.y = mat[4] * vec.x + mat[5] * vec.y + mat[6] * vec.z + mat[7];
|
||||
result.z = mat[8] * vec.x + mat[9] * vec.y + mat[10] * vec.z + mat[11];
|
||||
result.x = mat[0] * vec.x + mat[1] * vec.y + mat[2] * vec.z + mat[3];
|
||||
result.y = mat[4] * vec.x + mat[5] * vec.y + mat[6] * vec.z + mat[7];
|
||||
result.z = mat[8] * vec.x + mat[9] * vec.y + mat[10] * vec.z + mat[11];
|
||||
}
|
||||
|
||||
void MultipleVec3Perspective(const Vec3 &vec, const float *proj, Vec4 &result)
|
||||
{
|
||||
result.x = proj[0] * vec.x + proj[1] * vec.z;
|
||||
result.y = proj[2] * vec.y + proj[3] * vec.z;
|
||||
//result.z = (proj[4] * vec.z + proj[5]);
|
||||
result.z = (proj[4] * vec.z + proj[5]) * (1.0f - (float)1e-7);
|
||||
result.w = -vec.z;
|
||||
result.x = proj[0] * vec.x + proj[1] * vec.z;
|
||||
result.y = proj[2] * vec.y + proj[3] * vec.z;
|
||||
//result.z = (proj[4] * vec.z + proj[5]);
|
||||
result.z = (proj[4] * vec.z + proj[5]) * (1.0f - (float)1e-7);
|
||||
result.w = -vec.z;
|
||||
}
|
||||
|
||||
void MultipleVec3Ortho(const Vec3 &vec, const float *proj, Vec4 &result)
|
||||
{
|
||||
result.x = proj[0] * vec.x + proj[1];
|
||||
result.y = proj[2] * vec.y + proj[3];
|
||||
result.z = proj[4] * vec.z + proj[5];
|
||||
result.w = 1;
|
||||
result.x = proj[0] * vec.x + proj[1];
|
||||
result.y = proj[2] * vec.y + proj[3];
|
||||
result.z = proj[4] * vec.z + proj[5];
|
||||
result.w = 1;
|
||||
}
|
||||
|
||||
void TransformPosition(const InputVertexData *src, OutputVertexData *dst)
|
||||
{
|
||||
const float* mat = (const float*)&swxfregs.posMatrices[src->posMtx * 4];
|
||||
MultiplyVec3Mat34(src->position, mat, dst->mvPosition);
|
||||
const float* mat = (const float*)&swxfregs.posMatrices[src->posMtx * 4];
|
||||
MultiplyVec3Mat34(src->position, mat, dst->mvPosition);
|
||||
|
||||
if (swxfregs.projection.type == GX_PERSPECTIVE)
|
||||
{
|
||||
MultipleVec3Perspective(dst->mvPosition, swxfregs.projection.rawProjection, dst->projectedPosition);
|
||||
}
|
||||
else
|
||||
{
|
||||
MultipleVec3Ortho(dst->mvPosition, swxfregs.projection.rawProjection, dst->projectedPosition);
|
||||
}
|
||||
if (swxfregs.projection.type == GX_PERSPECTIVE)
|
||||
{
|
||||
MultipleVec3Perspective(dst->mvPosition, swxfregs.projection.rawProjection, dst->projectedPosition);
|
||||
}
|
||||
else
|
||||
{
|
||||
MultipleVec3Ortho(dst->mvPosition, swxfregs.projection.rawProjection, dst->projectedPosition);
|
||||
}
|
||||
}
|
||||
|
||||
void TransformNormal(const InputVertexData *src, bool nbt, OutputVertexData *dst)
|
||||
{
|
||||
const float* mat = (const float*)&swxfregs.normalMatrices[(src->posMtx & 31) * 3];
|
||||
const float* mat = (const float*)&swxfregs.normalMatrices[(src->posMtx & 31) * 3];
|
||||
|
||||
if (nbt)
|
||||
{
|
||||
MultiplyVec3Mat33(src->normal[0], mat, dst->normal[0]);
|
||||
MultiplyVec3Mat33(src->normal[1], mat, dst->normal[1]);
|
||||
MultiplyVec3Mat33(src->normal[2], mat, dst->normal[2]);
|
||||
dst->normal[0].normalize();
|
||||
}
|
||||
else
|
||||
{
|
||||
MultiplyVec3Mat33(src->normal[0], mat, dst->normal[0]);
|
||||
dst->normal[0].normalize();
|
||||
}
|
||||
if (nbt)
|
||||
{
|
||||
MultiplyVec3Mat33(src->normal[0], mat, dst->normal[0]);
|
||||
MultiplyVec3Mat33(src->normal[1], mat, dst->normal[1]);
|
||||
MultiplyVec3Mat33(src->normal[2], mat, dst->normal[2]);
|
||||
dst->normal[0].normalize();
|
||||
}
|
||||
else
|
||||
{
|
||||
MultiplyVec3Mat33(src->normal[0], mat, dst->normal[0]);
|
||||
dst->normal[0].normalize();
|
||||
}
|
||||
}
|
||||
|
||||
void TransformTexCoordRegular(const TexMtxInfo &texinfo, int coordNum, bool specialCase, const InputVertexData *srcVertex, OutputVertexData *dstVertex)
|
||||
{
|
||||
const Vec3 *src;
|
||||
switch (texinfo.sourcerow)
|
||||
{
|
||||
case XF_SRCGEOM_INROW:
|
||||
src = &srcVertex->position;
|
||||
break;
|
||||
case XF_SRCNORMAL_INROW:
|
||||
src = &srcVertex->normal[0];
|
||||
break;
|
||||
case XF_SRCBINORMAL_T_INROW:
|
||||
src = &srcVertex->normal[1];
|
||||
break;
|
||||
case XF_SRCBINORMAL_B_INROW:
|
||||
src = &srcVertex->normal[2];
|
||||
break;
|
||||
default:
|
||||
_assert_(texinfo.sourcerow >= XF_SRCTEX0_INROW && texinfo.sourcerow <= XF_SRCTEX7_INROW);
|
||||
src = (Vec3*)srcVertex->texCoords[texinfo.sourcerow - XF_SRCTEX0_INROW];
|
||||
break;
|
||||
}
|
||||
const Vec3 *src;
|
||||
switch (texinfo.sourcerow)
|
||||
{
|
||||
case XF_SRCGEOM_INROW:
|
||||
src = &srcVertex->position;
|
||||
break;
|
||||
case XF_SRCNORMAL_INROW:
|
||||
src = &srcVertex->normal[0];
|
||||
break;
|
||||
case XF_SRCBINORMAL_T_INROW:
|
||||
src = &srcVertex->normal[1];
|
||||
break;
|
||||
case XF_SRCBINORMAL_B_INROW:
|
||||
src = &srcVertex->normal[2];
|
||||
break;
|
||||
default:
|
||||
_assert_(texinfo.sourcerow >= XF_SRCTEX0_INROW && texinfo.sourcerow <= XF_SRCTEX7_INROW);
|
||||
src = (Vec3*)srcVertex->texCoords[texinfo.sourcerow - XF_SRCTEX0_INROW];
|
||||
break;
|
||||
}
|
||||
|
||||
const float *mat = (const float*)&swxfregs.posMatrices[srcVertex->texMtx[coordNum] * 4];
|
||||
Vec3 *dst = &dstVertex->texCoords[coordNum];
|
||||
const float *mat = (const float*)&swxfregs.posMatrices[srcVertex->texMtx[coordNum] * 4];
|
||||
Vec3 *dst = &dstVertex->texCoords[coordNum];
|
||||
|
||||
if (texinfo.projection == XF_TEXPROJ_ST)
|
||||
{
|
||||
|
@ -159,12 +159,12 @@ void TransformTexCoordRegular(const TexMtxInfo &texinfo, int coordNum, bool spec
|
|||
MultiplyVec3Mat34(*src, mat, *dst);
|
||||
}
|
||||
|
||||
if (swxfregs.dualTexTrans)
|
||||
{
|
||||
Vec3 tempCoord;
|
||||
if (swxfregs.dualTexTrans)
|
||||
{
|
||||
Vec3 tempCoord;
|
||||
|
||||
// normalize
|
||||
const PostMtxInfo &postInfo = swxfregs.postMtxInfo[coordNum];
|
||||
// normalize
|
||||
const PostMtxInfo &postInfo = swxfregs.postMtxInfo[coordNum];
|
||||
const float *postMat = (const float*)&swxfregs.postMatrices[postInfo.index * 4];
|
||||
|
||||
if (specialCase)
|
||||
|
@ -180,7 +180,7 @@ void TransformTexCoordRegular(const TexMtxInfo &texinfo, int coordNum, bool spec
|
|||
dst->z = 1.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
if (postInfo.normalize)
|
||||
tempCoord = dst->normalized();
|
||||
else
|
||||
|
@ -188,320 +188,336 @@ void TransformTexCoordRegular(const TexMtxInfo &texinfo, int coordNum, bool spec
|
|||
|
||||
MultiplyVec3Mat34(tempCoord, postMat, *dst);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct LightPointer
|
||||
{
|
||||
u32 reserved[3];
|
||||
u8 color[4];
|
||||
Vec3 cosatt;
|
||||
Vec3 distatt;
|
||||
Vec3 pos;
|
||||
Vec3 dir;
|
||||
u32 reserved[3];
|
||||
u8 color[4];
|
||||
Vec3 cosatt;
|
||||
Vec3 distatt;
|
||||
Vec3 pos;
|
||||
Vec3 dir;
|
||||
};
|
||||
|
||||
inline void AddIntegerColor(const u8 *src, Vec3 &dst)
|
||||
{
|
||||
dst.x += src[1];
|
||||
dst.y += src[2];
|
||||
dst.z += src[3];
|
||||
dst.x += src[1];
|
||||
dst.y += src[2];
|
||||
dst.z += src[3];
|
||||
}
|
||||
|
||||
inline void AddScaledIntegerColor(const u8 *src, float scale, Vec3 &dst)
|
||||
{
|
||||
dst.x += src[1] * scale;
|
||||
dst.y += src[2] * scale;
|
||||
dst.z += src[3] * scale;
|
||||
dst.x += src[1] * scale;
|
||||
dst.y += src[2] * scale;
|
||||
dst.z += src[3] * scale;
|
||||
}
|
||||
|
||||
inline float Clamp(float val, float a, float b)
|
||||
{
|
||||
return val<a?a:val>b?b:val;
|
||||
return val<a?a:val>b?b:val;
|
||||
}
|
||||
|
||||
inline float SafeDivide(float n, float d)
|
||||
{
|
||||
return (d==0)?(n>0?1:0):n/d;
|
||||
return (d==0) ? (n>0?1:0) : n/d;
|
||||
}
|
||||
|
||||
void LightColor(const Vec3 &pos, const Vec3 &normal, u8 lightNum, const LitChannel &chan, Vec3 &lightCol)
|
||||
{
|
||||
const LightPointer *light = (const LightPointer*)&swxfregs.lights[0x10*lightNum];
|
||||
const LightPointer *light = (const LightPointer*)&swxfregs.lights[0x10*lightNum];
|
||||
|
||||
if (!(chan.attnfunc & 1)) {
|
||||
// atten disabled
|
||||
switch (chan.diffusefunc) {
|
||||
case LIGHTDIF_NONE:
|
||||
AddIntegerColor(light->color, lightCol);
|
||||
break;
|
||||
case LIGHTDIF_SIGN:
|
||||
{
|
||||
Vec3 ldir = (light->pos - pos).normalized();
|
||||
float diffuse = ldir * normal;
|
||||
AddScaledIntegerColor(light->color, diffuse, lightCol);
|
||||
}
|
||||
break;
|
||||
case LIGHTDIF_CLAMP:
|
||||
{
|
||||
Vec3 ldir = (light->pos - pos).normalized();
|
||||
float diffuse = max(0.0f, ldir * normal);
|
||||
AddScaledIntegerColor(light->color, diffuse, lightCol);
|
||||
}
|
||||
break;
|
||||
default: _assert_(0);
|
||||
}
|
||||
}
|
||||
else { // spec and spot
|
||||
// not sure about divide by zero checks
|
||||
Vec3 ldir = light->pos - pos;
|
||||
float attn;
|
||||
if (!(chan.attnfunc & 1))
|
||||
{
|
||||
// atten disabled
|
||||
switch (chan.diffusefunc)
|
||||
{
|
||||
case LIGHTDIF_NONE:
|
||||
AddIntegerColor(light->color, lightCol);
|
||||
break;
|
||||
case LIGHTDIF_SIGN:
|
||||
{
|
||||
Vec3 ldir = (light->pos - pos).normalized();
|
||||
float diffuse = ldir * normal;
|
||||
AddScaledIntegerColor(light->color, diffuse, lightCol);
|
||||
}
|
||||
break;
|
||||
case LIGHTDIF_CLAMP:
|
||||
{
|
||||
Vec3 ldir = (light->pos - pos).normalized();
|
||||
float diffuse = max(0.0f, ldir * normal);
|
||||
AddScaledIntegerColor(light->color, diffuse, lightCol);
|
||||
}
|
||||
break;
|
||||
default: _assert_(0);
|
||||
}
|
||||
}
|
||||
else // spec and spot
|
||||
{
|
||||
// not sure about divide by zero checks
|
||||
Vec3 ldir = light->pos - pos;
|
||||
float attn;
|
||||
|
||||
if (chan.attnfunc == 3) { // spot
|
||||
float dist2 = ldir.length2();
|
||||
float dist = sqrtf(dist2);
|
||||
ldir = ldir / dist;
|
||||
attn = max(0.0f, ldir * light->dir);
|
||||
if (chan.attnfunc == 3) // spot
|
||||
{
|
||||
float dist2 = ldir.length2();
|
||||
float dist = sqrtf(dist2);
|
||||
ldir = ldir / dist;
|
||||
attn = max(0.0f, ldir * light->dir);
|
||||
|
||||
float cosAtt = light->cosatt.x + (light->cosatt.y * attn) + (light->cosatt.z * attn * attn);
|
||||
float distAtt = light->distatt.x + (light->distatt.y * dist) + (light->distatt.z * dist2);
|
||||
attn = SafeDivide(max(0.0f, cosAtt), distAtt);
|
||||
}
|
||||
else if (chan.attnfunc == 1) { // specular
|
||||
// donko - what is going on here? 655.36 is a guess but seems about right.
|
||||
attn = (light->pos * normal) > -655.36 ? max(0.0f, (light->dir * normal)) : 0;
|
||||
ldir.set(1.0f, attn, attn * attn);
|
||||
float cosAtt = light->cosatt.x + (light->cosatt.y * attn) + (light->cosatt.z * attn * attn);
|
||||
float distAtt = light->distatt.x + (light->distatt.y * dist) + (light->distatt.z * dist2);
|
||||
attn = SafeDivide(max(0.0f, cosAtt), distAtt);
|
||||
}
|
||||
else if (chan.attnfunc == 1) // specular
|
||||
{
|
||||
// donko - what is going on here? 655.36 is a guess but seems about right.
|
||||
attn = (light->pos * normal) > -655.36 ? max(0.0f, (light->dir * normal)) : 0;
|
||||
ldir.set(1.0f, attn, attn * attn);
|
||||
|
||||
float cosAtt = max(0.0f, light->cosatt * ldir);
|
||||
float distAtt = light->distatt * ldir;
|
||||
attn = SafeDivide(max(0.0f, cosAtt), distAtt);
|
||||
} else {
|
||||
PanicAlert("LightColor");
|
||||
return;
|
||||
}
|
||||
float cosAtt = max(0.0f, light->cosatt * ldir);
|
||||
float distAtt = light->distatt * ldir;
|
||||
attn = SafeDivide(max(0.0f, cosAtt), distAtt);
|
||||
}
|
||||
else
|
||||
{
|
||||
PanicAlert("LightColor");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (chan.diffusefunc) {
|
||||
case LIGHTDIF_NONE:
|
||||
AddScaledIntegerColor(light->color, attn, lightCol);
|
||||
break;
|
||||
case LIGHTDIF_SIGN:
|
||||
{
|
||||
float difAttn = ldir * normal;
|
||||
AddScaledIntegerColor(light->color, attn * difAttn, lightCol);
|
||||
}
|
||||
break;
|
||||
switch (chan.diffusefunc)
|
||||
{
|
||||
case LIGHTDIF_NONE:
|
||||
AddScaledIntegerColor(light->color, attn, lightCol);
|
||||
break;
|
||||
case LIGHTDIF_SIGN:
|
||||
{
|
||||
float difAttn = ldir * normal;
|
||||
AddScaledIntegerColor(light->color, attn * difAttn, lightCol);
|
||||
}
|
||||
break;
|
||||
|
||||
case LIGHTDIF_CLAMP:
|
||||
{
|
||||
float difAttn = max(0.0f, ldir * normal);
|
||||
AddScaledIntegerColor(light->color, attn * difAttn, lightCol);
|
||||
}
|
||||
break;
|
||||
default: _assert_(0);
|
||||
}
|
||||
}
|
||||
case LIGHTDIF_CLAMP:
|
||||
{
|
||||
float difAttn = max(0.0f, ldir * normal);
|
||||
AddScaledIntegerColor(light->color, attn * difAttn, lightCol);
|
||||
}
|
||||
break;
|
||||
default: _assert_(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LightAlpha(const Vec3 &pos, const Vec3 &normal, u8 lightNum, const LitChannel &chan, float &lightCol)
|
||||
{
|
||||
const LightPointer *light = (const LightPointer*)&swxfregs.lights[0x10*lightNum];
|
||||
const LightPointer *light = (const LightPointer*)&swxfregs.lights[0x10*lightNum];
|
||||
|
||||
if (!(chan.attnfunc & 1)) {
|
||||
// atten disabled
|
||||
switch (chan.diffusefunc) {
|
||||
case LIGHTDIF_NONE:
|
||||
lightCol += light->color[0];
|
||||
break;
|
||||
case LIGHTDIF_SIGN:
|
||||
{
|
||||
Vec3 ldir = (light->pos - pos).normalized();
|
||||
float diffuse = ldir * normal;
|
||||
lightCol += light->color[0] * diffuse;
|
||||
}
|
||||
break;
|
||||
case LIGHTDIF_CLAMP:
|
||||
{
|
||||
Vec3 ldir = (light->pos - pos).normalized();
|
||||
float diffuse = max(0.0f, ldir * normal);
|
||||
lightCol += light->color[0] * diffuse;
|
||||
}
|
||||
break;
|
||||
default: _assert_(0);
|
||||
}
|
||||
}
|
||||
else { // spec and spot
|
||||
Vec3 ldir = light->pos - pos;
|
||||
float attn;
|
||||
if (!(chan.attnfunc & 1))
|
||||
{
|
||||
// atten disabled
|
||||
switch (chan.diffusefunc)
|
||||
{
|
||||
case LIGHTDIF_NONE:
|
||||
lightCol += light->color[0];
|
||||
break;
|
||||
case LIGHTDIF_SIGN:
|
||||
{
|
||||
Vec3 ldir = (light->pos - pos).normalized();
|
||||
float diffuse = ldir * normal;
|
||||
lightCol += light->color[0] * diffuse;
|
||||
}
|
||||
break;
|
||||
case LIGHTDIF_CLAMP:
|
||||
{
|
||||
Vec3 ldir = (light->pos - pos).normalized();
|
||||
float diffuse = max(0.0f, ldir * normal);
|
||||
lightCol += light->color[0] * diffuse;
|
||||
}
|
||||
break;
|
||||
default: _assert_(0);
|
||||
}
|
||||
}
|
||||
else // spec and spot
|
||||
{
|
||||
Vec3 ldir = light->pos - pos;
|
||||
float attn;
|
||||
|
||||
if (chan.attnfunc == 3) { // spot
|
||||
float dist2 = ldir.length2();
|
||||
float dist = sqrtf(dist2);
|
||||
ldir = ldir / dist;
|
||||
attn = max(0.0f, ldir * light->dir);
|
||||
if (chan.attnfunc == 3) // spot
|
||||
{
|
||||
float dist2 = ldir.length2();
|
||||
float dist = sqrtf(dist2);
|
||||
ldir = ldir / dist;
|
||||
attn = max(0.0f, ldir * light->dir);
|
||||
|
||||
float cosAtt = light->cosatt.x + (light->cosatt.y * attn) + (light->cosatt.z * attn * attn);
|
||||
float distAtt = light->distatt.x + (light->distatt.y * dist) + (light->distatt.z * dist2);
|
||||
attn = SafeDivide(max(0.0f, cosAtt), distAtt);
|
||||
}
|
||||
else /* if (chan.attnfunc == 1) */ { // specular
|
||||
// donko - what is going on here? 655.36 is a guess but seems about right.
|
||||
attn = (light->pos * normal) > -655.36 ? max(0.0f, (light->dir * normal)) : 0;
|
||||
ldir.set(1.0f, attn, attn * attn);
|
||||
float cosAtt = light->cosatt.x + (light->cosatt.y * attn) + (light->cosatt.z * attn * attn);
|
||||
float distAtt = light->distatt.x + (light->distatt.y * dist) + (light->distatt.z * dist2);
|
||||
attn = SafeDivide(max(0.0f, cosAtt), distAtt);
|
||||
}
|
||||
else /* if (chan.attnfunc == 1) */ // specular
|
||||
{
|
||||
// donko - what is going on here? 655.36 is a guess but seems about right.
|
||||
attn = (light->pos * normal) > -655.36 ? max(0.0f, (light->dir * normal)) : 0;
|
||||
ldir.set(1.0f, attn, attn * attn);
|
||||
|
||||
float cosAtt = light->cosatt * ldir;
|
||||
float distAtt = light->distatt * ldir;
|
||||
attn = SafeDivide(max(0.0f, cosAtt), distAtt);
|
||||
}
|
||||
float cosAtt = light->cosatt * ldir;
|
||||
float distAtt = light->distatt * ldir;
|
||||
attn = SafeDivide(max(0.0f, cosAtt), distAtt);
|
||||
}
|
||||
|
||||
switch (chan.diffusefunc) {
|
||||
case LIGHTDIF_NONE:
|
||||
lightCol += light->color[0] * attn;
|
||||
break;
|
||||
case LIGHTDIF_SIGN:
|
||||
{
|
||||
float difAttn = ldir * normal;
|
||||
lightCol += light->color[0] * attn * difAttn;
|
||||
}
|
||||
break;
|
||||
switch (chan.diffusefunc)
|
||||
{
|
||||
case LIGHTDIF_NONE:
|
||||
lightCol += light->color[0] * attn;
|
||||
break;
|
||||
case LIGHTDIF_SIGN:
|
||||
{
|
||||
float difAttn = ldir * normal;
|
||||
lightCol += light->color[0] * attn * difAttn;
|
||||
}
|
||||
break;
|
||||
|
||||
case LIGHTDIF_CLAMP:
|
||||
{
|
||||
float difAttn = max(0.0f, ldir * normal);
|
||||
lightCol += light->color[0] * attn * difAttn;
|
||||
}
|
||||
break;
|
||||
default: _assert_(0);
|
||||
}
|
||||
}
|
||||
case LIGHTDIF_CLAMP:
|
||||
{
|
||||
float difAttn = max(0.0f, ldir * normal);
|
||||
lightCol += light->color[0] * attn * difAttn;
|
||||
}
|
||||
break;
|
||||
default: _assert_(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TransformColor(const InputVertexData *src, OutputVertexData *dst)
|
||||
{
|
||||
for (u32 chan = 0; chan < swxfregs.nNumChans; chan++)
|
||||
{
|
||||
// abgr
|
||||
u8 matcolor[4];
|
||||
u8 chancolor[4];
|
||||
for (u32 chan = 0; chan < swxfregs.nNumChans; chan++)
|
||||
{
|
||||
// abgr
|
||||
u8 matcolor[4];
|
||||
u8 chancolor[4];
|
||||
|
||||
// color
|
||||
LitChannel &colorchan = swxfregs.color[chan];
|
||||
if (colorchan.matsource)
|
||||
*(u32*)matcolor = *(u32*)src->color[chan]; // vertex
|
||||
else
|
||||
*(u32*)matcolor = swxfregs.matColor[chan];
|
||||
// color
|
||||
LitChannel &colorchan = swxfregs.color[chan];
|
||||
if (colorchan.matsource)
|
||||
*(u32*)matcolor = *(u32*)src->color[chan]; // vertex
|
||||
else
|
||||
*(u32*)matcolor = swxfregs.matColor[chan];
|
||||
|
||||
if (colorchan.enablelighting)
|
||||
{
|
||||
Vec3 lightCol;
|
||||
if (colorchan.ambsource)
|
||||
{
|
||||
// vertex
|
||||
lightCol.x = src->color[chan][1];
|
||||
lightCol.y = src->color[chan][2];
|
||||
lightCol.z = src->color[chan][3];
|
||||
}
|
||||
else
|
||||
{
|
||||
u8 *ambColor = (u8*)&swxfregs.ambColor[chan];
|
||||
lightCol.x = ambColor[1];
|
||||
lightCol.y = ambColor[2];
|
||||
lightCol.z = ambColor[3];
|
||||
}
|
||||
if (colorchan.enablelighting)
|
||||
{
|
||||
Vec3 lightCol;
|
||||
if (colorchan.ambsource)
|
||||
{
|
||||
// vertex
|
||||
lightCol.x = src->color[chan][1];
|
||||
lightCol.y = src->color[chan][2];
|
||||
lightCol.z = src->color[chan][3];
|
||||
}
|
||||
else
|
||||
{
|
||||
u8 *ambColor = (u8*)&swxfregs.ambColor[chan];
|
||||
lightCol.x = ambColor[1];
|
||||
lightCol.y = ambColor[2];
|
||||
lightCol.z = ambColor[3];
|
||||
}
|
||||
|
||||
u8 mask = colorchan.GetFullLightMask();
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
if (mask&(1<<i))
|
||||
LightColor(dst->mvPosition, dst->normal[0], i, colorchan, lightCol);
|
||||
}
|
||||
u8 mask = colorchan.GetFullLightMask();
|
||||
for (int i = 0; i < 8; ++i)
|
||||
{
|
||||
if (mask&(1<<i))
|
||||
LightColor(dst->mvPosition, dst->normal[0], i, colorchan, lightCol);
|
||||
}
|
||||
|
||||
float inv = 1.0f / 255.0f;
|
||||
chancolor[1] = (u8)(matcolor[1] * Clamp(lightCol.x * inv, 0.0f, 1.0f));
|
||||
chancolor[2] = (u8)(matcolor[2] * Clamp(lightCol.y * inv, 0.0f, 1.0f));
|
||||
chancolor[3] = (u8)(matcolor[3] * Clamp(lightCol.z * inv, 0.0f, 1.0f));
|
||||
}
|
||||
else
|
||||
{
|
||||
*(u32*)chancolor = *(u32*)matcolor;
|
||||
}
|
||||
float inv = 1.0f / 255.0f;
|
||||
chancolor[1] = (u8)(matcolor[1] * Clamp(lightCol.x * inv, 0.0f, 1.0f));
|
||||
chancolor[2] = (u8)(matcolor[2] * Clamp(lightCol.y * inv, 0.0f, 1.0f));
|
||||
chancolor[3] = (u8)(matcolor[3] * Clamp(lightCol.z * inv, 0.0f, 1.0f));
|
||||
}
|
||||
else
|
||||
{
|
||||
*(u32*)chancolor = *(u32*)matcolor;
|
||||
}
|
||||
|
||||
// alpha
|
||||
LitChannel &alphachan = swxfregs.alpha[chan];
|
||||
if (alphachan.matsource)
|
||||
matcolor[0] = src->color[chan][0]; // vertex
|
||||
else
|
||||
matcolor[0] = swxfregs.matColor[chan] & 0xff;
|
||||
// alpha
|
||||
LitChannel &alphachan = swxfregs.alpha[chan];
|
||||
if (alphachan.matsource)
|
||||
matcolor[0] = src->color[chan][0]; // vertex
|
||||
else
|
||||
matcolor[0] = swxfregs.matColor[chan] & 0xff;
|
||||
|
||||
if (swxfregs.alpha[chan].enablelighting)
|
||||
{
|
||||
float lightCol;
|
||||
if (alphachan.ambsource)
|
||||
lightCol = src->color[chan][0]; // vertex
|
||||
else
|
||||
lightCol = (float)(swxfregs.ambColor[chan] & 0xff);
|
||||
if (swxfregs.alpha[chan].enablelighting)
|
||||
{
|
||||
float lightCol;
|
||||
if (alphachan.ambsource)
|
||||
lightCol = src->color[chan][0]; // vertex
|
||||
else
|
||||
lightCol = (float)(swxfregs.ambColor[chan] & 0xff);
|
||||
|
||||
u8 mask = alphachan.GetFullLightMask();
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
if (mask&(1<<i))
|
||||
LightAlpha(dst->mvPosition, dst->normal[0], i, alphachan, lightCol);
|
||||
}
|
||||
u8 mask = alphachan.GetFullLightMask();
|
||||
for (int i = 0; i < 8; ++i)
|
||||
{
|
||||
if (mask&(1<<i))
|
||||
LightAlpha(dst->mvPosition, dst->normal[0], i, alphachan, lightCol);
|
||||
}
|
||||
|
||||
chancolor[0] = (u8)(matcolor[0] * Clamp(lightCol / 255.0f, 0.0f, 1.0f));
|
||||
}
|
||||
else
|
||||
{
|
||||
chancolor[0] = matcolor[0];
|
||||
}
|
||||
chancolor[0] = (u8)(matcolor[0] * Clamp(lightCol / 255.0f, 0.0f, 1.0f));
|
||||
}
|
||||
else
|
||||
{
|
||||
chancolor[0] = matcolor[0];
|
||||
}
|
||||
|
||||
// abgr -> rgba
|
||||
*(u32*)dst->color[chan] = Common::swap32(*(u32*)chancolor);
|
||||
}
|
||||
// abgr -> rgba
|
||||
*(u32*)dst->color[chan] = Common::swap32(*(u32*)chancolor);
|
||||
}
|
||||
}
|
||||
|
||||
void TransformTexCoord(const InputVertexData *src, OutputVertexData *dst, bool specialCase)
|
||||
{
|
||||
for (u32 coordNum = 0; coordNum < swxfregs.numTexGens; coordNum++)
|
||||
{
|
||||
const TexMtxInfo &texinfo = swxfregs.texMtxInfo[coordNum];
|
||||
for (u32 coordNum = 0; coordNum < swxfregs.numTexGens; coordNum++)
|
||||
{
|
||||
const TexMtxInfo &texinfo = swxfregs.texMtxInfo[coordNum];
|
||||
|
||||
switch (texinfo.texgentype)
|
||||
{
|
||||
case XF_TEXGEN_REGULAR:
|
||||
TransformTexCoordRegular(texinfo, coordNum, specialCase, src, dst);
|
||||
break;
|
||||
case XF_TEXGEN_EMBOSS_MAP:
|
||||
{
|
||||
const LightPointer *light = (const LightPointer*)&swxfregs.lights[0x10*texinfo.embosslightshift];
|
||||
switch (texinfo.texgentype)
|
||||
{
|
||||
case XF_TEXGEN_REGULAR:
|
||||
TransformTexCoordRegular(texinfo, coordNum, specialCase, src, dst);
|
||||
break;
|
||||
case XF_TEXGEN_EMBOSS_MAP:
|
||||
{
|
||||
const LightPointer *light = (const LightPointer*)&swxfregs.lights[0x10*texinfo.embosslightshift];
|
||||
|
||||
Vec3 ldir = (light->pos - dst->mvPosition).normalized();
|
||||
float d1 = ldir * dst->normal[1];
|
||||
float d2 = ldir * dst->normal[2];
|
||||
Vec3 ldir = (light->pos - dst->mvPosition).normalized();
|
||||
float d1 = ldir * dst->normal[1];
|
||||
float d2 = ldir * dst->normal[2];
|
||||
|
||||
dst->texCoords[coordNum].x = dst->texCoords[texinfo.embosssourceshift].x + d1;
|
||||
dst->texCoords[coordNum].y = dst->texCoords[texinfo.embosssourceshift].y + d2;
|
||||
dst->texCoords[coordNum].z = dst->texCoords[texinfo.embosssourceshift].z;
|
||||
}
|
||||
break;
|
||||
case XF_TEXGEN_COLOR_STRGBC0:
|
||||
_assert_(texinfo.sourcerow == XF_SRCCOLORS_INROW);
|
||||
_assert_(texinfo.inputform == XF_TEXINPUT_AB11);
|
||||
dst->texCoords[coordNum].x = (float)dst->color[0][0] / 255.0f;
|
||||
dst->texCoords[coordNum].y = (float)dst->color[0][1] / 255.0f;
|
||||
dst->texCoords[coordNum].z = 1.0f;
|
||||
break;
|
||||
case XF_TEXGEN_COLOR_STRGBC1:
|
||||
_assert_(texinfo.sourcerow == XF_SRCCOLORS_INROW);
|
||||
_assert_(texinfo.inputform == XF_TEXINPUT_AB11);
|
||||
dst->texCoords[coordNum].x = (float)dst->color[1][0] / 255.0f;
|
||||
dst->texCoords[coordNum].y = (float)dst->color[1][1] / 255.0f;
|
||||
dst->texCoords[coordNum].z = 1.0f;
|
||||
break;
|
||||
default:
|
||||
ERROR_LOG(VIDEO, "Bad tex gen type %i", texinfo.texgentype);
|
||||
}
|
||||
}
|
||||
dst->texCoords[coordNum].x = dst->texCoords[texinfo.embosssourceshift].x + d1;
|
||||
dst->texCoords[coordNum].y = dst->texCoords[texinfo.embosssourceshift].y + d2;
|
||||
dst->texCoords[coordNum].z = dst->texCoords[texinfo.embosssourceshift].z;
|
||||
}
|
||||
break;
|
||||
case XF_TEXGEN_COLOR_STRGBC0:
|
||||
_assert_(texinfo.sourcerow == XF_SRCCOLORS_INROW);
|
||||
_assert_(texinfo.inputform == XF_TEXINPUT_AB11);
|
||||
dst->texCoords[coordNum].x = (float)dst->color[0][0] / 255.0f;
|
||||
dst->texCoords[coordNum].y = (float)dst->color[0][1] / 255.0f;
|
||||
dst->texCoords[coordNum].z = 1.0f;
|
||||
break;
|
||||
case XF_TEXGEN_COLOR_STRGBC1:
|
||||
_assert_(texinfo.sourcerow == XF_SRCCOLORS_INROW);
|
||||
_assert_(texinfo.inputform == XF_TEXINPUT_AB11);
|
||||
dst->texCoords[coordNum].x = (float)dst->color[1][0] / 255.0f;
|
||||
dst->texCoords[coordNum].y = (float)dst->color[1][1] / 255.0f;
|
||||
dst->texCoords[coordNum].z = 1.0f;
|
||||
break;
|
||||
default:
|
||||
ERROR_LOG(VIDEO, "Bad tex gen type %i", texinfo.texgentype);
|
||||
}
|
||||
}
|
||||
|
||||
for (u32 coordNum = 0; coordNum < swxfregs.numTexGens; coordNum++)
|
||||
{
|
||||
{
|
||||
dst->texCoords[coordNum][0] *= (bpmem.texcoords[coordNum].s.scale_minus_1 + 1);
|
||||
dst->texCoords[coordNum][1] *= (bpmem.texcoords[coordNum].t.scale_minus_1 + 1);
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// Official Git repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _TRANSFORM_UNIT_H_
|
||||
|
@ -23,15 +23,15 @@ struct OutputVertexData;
|
|||
|
||||
namespace TransformUnit
|
||||
{
|
||||
void MultiplyVec2Mat24(const float *vec, const float *mat, float *result);
|
||||
void MultiplyVec2Mat34(const float *vec, const float *mat, float *result);
|
||||
void MultiplyVec3Mat33(const float *vec, const float *mat, float *result);
|
||||
void MultiplyVec3Mat34(const float *vec, const float *mat, float *result);
|
||||
void MultiplyVec2Mat24(const float *vec, const float *mat, float *result);
|
||||
void MultiplyVec2Mat34(const float *vec, const float *mat, float *result);
|
||||
void MultiplyVec3Mat33(const float *vec, const float *mat, float *result);
|
||||
void MultiplyVec3Mat34(const float *vec, const float *mat, float *result);
|
||||
|
||||
void TransformPosition(const InputVertexData *src, OutputVertexData *dst);
|
||||
void TransformNormal(const InputVertexData *src, bool nbt, OutputVertexData *dst);
|
||||
void TransformColor(const InputVertexData *src, OutputVertexData *dst);
|
||||
void TransformTexCoord(const InputVertexData *src, OutputVertexData *dst, bool specialCase);
|
||||
void TransformPosition(const InputVertexData *src, OutputVertexData *dst);
|
||||
void TransformNormal(const InputVertexData *src, bool nbt, OutputVertexData *dst);
|
||||
void TransformColor(const InputVertexData *src, OutputVertexData *dst);
|
||||
void TransformTexCoord(const InputVertexData *src, OutputVertexData *dst, bool specialCase);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// Official Git repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _VEC3_H
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// Official Git repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "VideoConfigDiag.h"
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// Official Git repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _VIDEOSOFTWARE_CONFIG_DIAG_H_
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// Official Git repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "VideoCommon.h"
|
||||
|
@ -26,15 +26,15 @@ XFRegisters swxfregs;
|
|||
|
||||
void InitXFMemory()
|
||||
{
|
||||
memset(&swxfregs, 0, sizeof(swxfregs));
|
||||
memset(&swxfregs, 0, sizeof(swxfregs));
|
||||
}
|
||||
|
||||
void XFWritten(u32 transferSize, u32 baseAddress)
|
||||
{
|
||||
u32 topAddress = baseAddress + transferSize;
|
||||
u32 topAddress = baseAddress + transferSize;
|
||||
|
||||
if (baseAddress <= 0x1026 && topAddress >= 0x1020)
|
||||
Clipper::SetViewOffset();
|
||||
if (baseAddress <= 0x1026 && topAddress >= 0x1020)
|
||||
Clipper::SetViewOffset();
|
||||
|
||||
// fix lights so invalid values don't trash the lighting computations
|
||||
if (baseAddress <= 0x067f && topAddress >= 0x0604)
|
||||
|
@ -63,32 +63,32 @@ void XFWritten(u32 transferSize, u32 baseAddress)
|
|||
|
||||
void SWLoadXFReg(u32 transferSize, u32 baseAddress, u32 *pData)
|
||||
{
|
||||
u32 size = transferSize;
|
||||
u32 size = transferSize;
|
||||
|
||||
// do not allow writes past registers
|
||||
if (baseAddress + transferSize > 0x1058)
|
||||
{
|
||||
INFO_LOG(VIDEO, "xf load exceeds address space: %x %d bytes\n", baseAddress, transferSize);
|
||||
// do not allow writes past registers
|
||||
if (baseAddress + transferSize > 0x1058)
|
||||
{
|
||||
INFO_LOG(VIDEO, "xf load exceeds address space: %x %d bytes\n", baseAddress, transferSize);
|
||||
|
||||
if (baseAddress >= 0x1058)
|
||||
size = 0;
|
||||
else
|
||||
size = 0x1058 - baseAddress;
|
||||
}
|
||||
|
||||
if (size > 0) {
|
||||
memcpy_gc( &((u32*)&swxfregs)[baseAddress], pData, size * 4);
|
||||
XFWritten(transferSize, baseAddress);
|
||||
}
|
||||
if (baseAddress >= 0x1058)
|
||||
size = 0;
|
||||
else
|
||||
size = 0x1058 - baseAddress;
|
||||
}
|
||||
|
||||
if (size > 0)
|
||||
{
|
||||
memcpy_gc( &((u32*)&swxfregs)[baseAddress], pData, size * 4);
|
||||
XFWritten(transferSize, baseAddress);
|
||||
}
|
||||
}
|
||||
|
||||
void SWLoadIndexedXF(u32 val, int array)
|
||||
{
|
||||
int index = val >> 16;
|
||||
int address = val & 0xFFF; //check mask
|
||||
int size = ((val >> 12) & 0xF) + 1;
|
||||
//load stuff from array to address in xf mem
|
||||
int index = val >> 16;
|
||||
int address = val & 0xFFF; //check mask
|
||||
int size = ((val >> 12) & 0xF) + 1;
|
||||
//load stuff from array to address in xf mem
|
||||
|
||||
u32 *pData = (u32*)Memory::GetPointer(arraybases[array] + arraystrides[array]*index);
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// Official Git repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _XFMEMLOADER_H_
|
||||
|
@ -31,49 +31,49 @@
|
|||
#define XF_TEXINPUT_AB11 0
|
||||
#define XF_TEXINPUT_ABC1 1
|
||||
|
||||
#define XF_TEXGEN_REGULAR 0
|
||||
#define XF_TEXGEN_EMBOSS_MAP 1 // used when bump mapping
|
||||
#define XF_TEXGEN_REGULAR 0
|
||||
#define XF_TEXGEN_EMBOSS_MAP 1 // used when bump mapping
|
||||
#define XF_TEXGEN_COLOR_STRGBC0 2
|
||||
#define XF_TEXGEN_COLOR_STRGBC1 3
|
||||
|
||||
#define XF_SRCGEOM_INROW 0 // input is abc
|
||||
#define XF_SRCNORMAL_INROW 1 // input is abc
|
||||
#define XF_SRCCOLORS_INROW 2
|
||||
#define XF_SRCGEOM_INROW 0 // input is abc
|
||||
#define XF_SRCNORMAL_INROW 1 // input is abc
|
||||
#define XF_SRCCOLORS_INROW 2
|
||||
#define XF_SRCBINORMAL_T_INROW 3 // input is abc
|
||||
#define XF_SRCBINORMAL_B_INROW 4 // input is abc
|
||||
#define XF_SRCTEX0_INROW 5
|
||||
#define XF_SRCTEX1_INROW 6
|
||||
#define XF_SRCTEX2_INROW 7
|
||||
#define XF_SRCTEX3_INROW 8
|
||||
#define XF_SRCTEX4_INROW 9
|
||||
#define XF_SRCTEX5_INROW 10
|
||||
#define XF_SRCTEX6_INROW 11
|
||||
#define XF_SRCTEX7_INROW 12
|
||||
#define XF_SRCTEX0_INROW 5
|
||||
#define XF_SRCTEX1_INROW 6
|
||||
#define XF_SRCTEX2_INROW 7
|
||||
#define XF_SRCTEX3_INROW 8
|
||||
#define XF_SRCTEX4_INROW 9
|
||||
#define XF_SRCTEX5_INROW 10
|
||||
#define XF_SRCTEX6_INROW 11
|
||||
#define XF_SRCTEX7_INROW 12
|
||||
|
||||
#define GX_SRC_REG 0
|
||||
#define GX_SRC_VTX 1
|
||||
|
||||
struct Light
|
||||
{
|
||||
u32 useless[3];
|
||||
u32 color; //rgba
|
||||
float a0; //attenuation
|
||||
float a1;
|
||||
float a2;
|
||||
float k0; //k stuff
|
||||
float k1;
|
||||
float k2;
|
||||
union
|
||||
{
|
||||
struct {
|
||||
u32 useless[3];
|
||||
u32 color; //rgba
|
||||
float a0; //attenuation
|
||||
float a1;
|
||||
float a2;
|
||||
float k0; //k stuff
|
||||
float k1;
|
||||
float k2;
|
||||
union
|
||||
{
|
||||
struct {
|
||||
float dpos[3];
|
||||
float ddir[3]; // specular lights only
|
||||
};
|
||||
struct {
|
||||
float sdir[3];
|
||||
float shalfangle[3]; // specular lights only
|
||||
};
|
||||
};
|
||||
float ddir[3]; // specular lights only
|
||||
};
|
||||
struct {
|
||||
float sdir[3];
|
||||
float shalfangle[3]; // specular lights only
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
#define LIGHTDIF_NONE 0
|
||||
|
@ -83,74 +83,74 @@ struct Light
|
|||
#define LIGHTATTN_SPEC 0 // specular attenuation
|
||||
#define LIGHTATTN_SPOT 1 // distance/spotlight attenuation
|
||||
#define LIGHTATTN_NONE 2
|
||||
#define LIGHTATTN_DIR 3
|
||||
#define LIGHTATTN_DIR 3
|
||||
|
||||
#define GX_PERSPECTIVE 0
|
||||
#define GX_ORTHOGRAPHIC 1
|
||||
|
||||
union LitChannel
|
||||
{
|
||||
struct
|
||||
{
|
||||
u32 matsource : 1;
|
||||
u32 enablelighting : 1;
|
||||
u32 lightMask0_3 : 4;
|
||||
u32 ambsource : 1;
|
||||
u32 diffusefunc : 2; // LIGHTDIF_X
|
||||
u32 attnfunc : 2; // LIGHTATTN_X
|
||||
u32 lightMask4_7 : 4;
|
||||
u32 unused : 17;
|
||||
};
|
||||
u32 hex;
|
||||
unsigned int GetFullLightMask() const
|
||||
{
|
||||
return enablelighting ? (lightMask0_3 | (lightMask4_7 << 4)) : 0;
|
||||
}
|
||||
struct
|
||||
{
|
||||
u32 matsource : 1;
|
||||
u32 enablelighting : 1;
|
||||
u32 lightMask0_3 : 4;
|
||||
u32 ambsource : 1;
|
||||
u32 diffusefunc : 2; // LIGHTDIF_X
|
||||
u32 attnfunc : 2; // LIGHTATTN_X
|
||||
u32 lightMask4_7 : 4;
|
||||
u32 unused : 17;
|
||||
};
|
||||
u32 hex;
|
||||
unsigned int GetFullLightMask() const
|
||||
{
|
||||
return enablelighting ? (lightMask0_3 | (lightMask4_7 << 4)) : 0;
|
||||
}
|
||||
};
|
||||
|
||||
union INVTXSPEC
|
||||
{
|
||||
struct
|
||||
{
|
||||
u32 numcolors : 2;
|
||||
u32 numnormals : 2; // 0 - nothing, 1 - just normal, 2 - normals and binormals
|
||||
u32 numtextures : 4;
|
||||
u32 unused : 24;
|
||||
};
|
||||
u32 hex;
|
||||
struct
|
||||
{
|
||||
u32 numcolors : 2;
|
||||
u32 numnormals : 2; // 0 - nothing, 1 - just normal, 2 - normals and binormals
|
||||
u32 numtextures : 4;
|
||||
u32 unused : 24;
|
||||
};
|
||||
u32 hex;
|
||||
};
|
||||
|
||||
union TXFMatrixIndexA
|
||||
{
|
||||
struct
|
||||
{
|
||||
u32 PosNormalMtxIdx : 6;
|
||||
u32 Tex0MtxIdx : 6;
|
||||
u32 Tex1MtxIdx : 6;
|
||||
u32 Tex2MtxIdx : 6;
|
||||
u32 Tex3MtxIdx : 6;
|
||||
};
|
||||
struct
|
||||
{
|
||||
u32 Hex : 30;
|
||||
u32 unused : 2;
|
||||
};
|
||||
struct
|
||||
{
|
||||
u32 PosNormalMtxIdx : 6;
|
||||
u32 Tex0MtxIdx : 6;
|
||||
u32 Tex1MtxIdx : 6;
|
||||
u32 Tex2MtxIdx : 6;
|
||||
u32 Tex3MtxIdx : 6;
|
||||
};
|
||||
struct
|
||||
{
|
||||
u32 Hex : 30;
|
||||
u32 unused : 2;
|
||||
};
|
||||
};
|
||||
|
||||
union TXFMatrixIndexB
|
||||
{
|
||||
struct
|
||||
{
|
||||
u32 Tex4MtxIdx : 6;
|
||||
u32 Tex5MtxIdx : 6;
|
||||
u32 Tex6MtxIdx : 6;
|
||||
u32 Tex7MtxIdx : 6;
|
||||
};
|
||||
struct
|
||||
{
|
||||
u32 Hex : 24;
|
||||
u32 unused : 8;
|
||||
};
|
||||
struct
|
||||
{
|
||||
u32 Tex4MtxIdx : 6;
|
||||
u32 Tex5MtxIdx : 6;
|
||||
u32 Tex6MtxIdx : 6;
|
||||
u32 Tex7MtxIdx : 6;
|
||||
};
|
||||
struct
|
||||
{
|
||||
u32 Hex : 24;
|
||||
u32 unused : 8;
|
||||
};
|
||||
};
|
||||
|
||||
struct Viewport
|
||||
|
@ -171,68 +171,68 @@ struct Projection
|
|||
|
||||
union TexMtxInfo
|
||||
{
|
||||
struct
|
||||
{
|
||||
u32 unknown : 1;
|
||||
u32 projection : 1; // XF_TEXPROJ_X
|
||||
u32 inputform : 2; // XF_TEXINPUT_X
|
||||
u32 texgentype : 3; // XF_TEXGEN_X
|
||||
u32 sourcerow : 5; // XF_SRCGEOM_X
|
||||
u32 embosssourceshift : 3; // what generated texcoord to use
|
||||
u32 embosslightshift : 3; // light index that is used
|
||||
};
|
||||
u32 hex;
|
||||
struct
|
||||
{
|
||||
u32 unknown : 1;
|
||||
u32 projection : 1; // XF_TEXPROJ_X
|
||||
u32 inputform : 2; // XF_TEXINPUT_X
|
||||
u32 texgentype : 3; // XF_TEXGEN_X
|
||||
u32 sourcerow : 5; // XF_SRCGEOM_X
|
||||
u32 embosssourceshift : 3; // what generated texcoord to use
|
||||
u32 embosslightshift : 3; // light index that is used
|
||||
};
|
||||
u32 hex;
|
||||
};
|
||||
|
||||
union PostMtxInfo
|
||||
{
|
||||
struct
|
||||
{
|
||||
u32 index : 6; // base row of dual transform matrix
|
||||
u32 unused : 2;
|
||||
u32 normalize : 1; // normalize before send operation
|
||||
};
|
||||
u32 hex;
|
||||
struct
|
||||
{
|
||||
u32 index : 6; // base row of dual transform matrix
|
||||
u32 unused : 2;
|
||||
u32 normalize : 1; // normalize before send operation
|
||||
};
|
||||
u32 hex;
|
||||
};
|
||||
|
||||
struct XFRegisters
|
||||
{
|
||||
u32 posMatrices[256]; // 0x0000 - 0x00ff
|
||||
u32 unk0[768]; // 0x0100 - 0x03ff
|
||||
u32 normalMatrices[96]; // 0x0400 - 0x045f
|
||||
u32 unk1[160]; // 0x0460 - 0x04ff
|
||||
u32 postMatrices[256]; // 0x0500 - 0x05ff
|
||||
u32 lights[128]; // 0x0600 - 0x067f
|
||||
u32 unk2[2432]; // 0x0680 - 0x0fff
|
||||
u32 error; // 0x1000
|
||||
u32 diag; // 0x1001
|
||||
u32 state0; // 0x1002
|
||||
u32 state1; // 0x1003
|
||||
u32 xfClock; // 0x1004
|
||||
u32 clipDisable; // 0x1005
|
||||
u32 perf0; // 0x1006
|
||||
u32 perf1; // 0x1007
|
||||
INVTXSPEC hostinfo; // 0x1008 number of textures,colors,normals from vertex input
|
||||
u32 nNumChans; // 0x1009
|
||||
u32 ambColor[2]; // 0x100a, 0x100b
|
||||
u32 matColor[2]; // 0x100c, 0x100d
|
||||
LitChannel color[2]; // 0x100e, 0x100f
|
||||
LitChannel alpha[2]; // 0x1010, 0x1011
|
||||
u32 dualTexTrans; // 0x1012
|
||||
u32 unk3; // 0x1013
|
||||
u32 unk4; // 0x1014
|
||||
u32 unk5; // 0x1015
|
||||
u32 unk6; // 0x1016
|
||||
u32 unk7; // 0x1017
|
||||
TXFMatrixIndexA MatrixIndexA; // 0x1018
|
||||
TXFMatrixIndexB MatrixIndexB; // 0x1019
|
||||
Viewport viewport; // 0x101a - 0x101f
|
||||
Projection projection; // 0x1020 - 0x1026
|
||||
u32 unk8[24]; // 0x1027 - 0x103e
|
||||
u32 numTexGens; // 0x103f
|
||||
TexMtxInfo texMtxInfo[8]; // 0x1040 - 0x1047
|
||||
u32 unk9[8]; // 0x1048 - 0x104f
|
||||
PostMtxInfo postMtxInfo[8]; // 0x1050 - 0x1057
|
||||
u32 posMatrices[256]; // 0x0000 - 0x00ff
|
||||
u32 unk0[768]; // 0x0100 - 0x03ff
|
||||
u32 normalMatrices[96]; // 0x0400 - 0x045f
|
||||
u32 unk1[160]; // 0x0460 - 0x04ff
|
||||
u32 postMatrices[256]; // 0x0500 - 0x05ff
|
||||
u32 lights[128]; // 0x0600 - 0x067f
|
||||
u32 unk2[2432]; // 0x0680 - 0x0fff
|
||||
u32 error; // 0x1000
|
||||
u32 diag; // 0x1001
|
||||
u32 state0; // 0x1002
|
||||
u32 state1; // 0x1003
|
||||
u32 xfClock; // 0x1004
|
||||
u32 clipDisable; // 0x1005
|
||||
u32 perf0; // 0x1006
|
||||
u32 perf1; // 0x1007
|
||||
INVTXSPEC hostinfo; // 0x1008 number of textures,colors,normals from vertex input
|
||||
u32 nNumChans; // 0x1009
|
||||
u32 ambColor[2]; // 0x100a, 0x100b
|
||||
u32 matColor[2]; // 0x100c, 0x100d
|
||||
LitChannel color[2]; // 0x100e, 0x100f
|
||||
LitChannel alpha[2]; // 0x1010, 0x1011
|
||||
u32 dualTexTrans; // 0x1012
|
||||
u32 unk3; // 0x1013
|
||||
u32 unk4; // 0x1014
|
||||
u32 unk5; // 0x1015
|
||||
u32 unk6; // 0x1016
|
||||
u32 unk7; // 0x1017
|
||||
TXFMatrixIndexA MatrixIndexA; // 0x1018
|
||||
TXFMatrixIndexB MatrixIndexB; // 0x1019
|
||||
Viewport viewport; // 0x101a - 0x101f
|
||||
Projection projection; // 0x1020 - 0x1026
|
||||
u32 unk8[24]; // 0x1027 - 0x103e
|
||||
u32 numTexGens; // 0x103f
|
||||
TexMtxInfo texMtxInfo[8]; // 0x1040 - 0x1047
|
||||
u32 unk9[8]; // 0x1048 - 0x104f
|
||||
PostMtxInfo postMtxInfo[8]; // 0x1050 - 0x1057
|
||||
};
|
||||
|
||||
#define XFMEM_POSMATRICES 0x000
|
||||
|
@ -249,7 +249,7 @@ extern XFRegisters swxfregs;
|
|||
|
||||
void InitXFMemory();
|
||||
|
||||
void XFWritten(u32 transferSize, u32 baseAddress);
|
||||
void XFWritten(u32 transferSize, u32 baseAddress);
|
||||
|
||||
void SWLoadXFReg(u32 transferSize, u32 baseAddress, u32 *pData);
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// Official Git repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "stdafx.h"
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// Official Git repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#pragma once
|
||||
|
|
Loading…
Reference in New Issue