Clean up most (99.99%) of the tab/space mismatches in the VideoSoftware project.
Got rid of trailing spaces that were unnecessary too. Also update the license header for this project. We don't use SVN anymore.
This commit is contained in:
parent
48927c17d2
commit
7ab0cca645
|
@ -12,7 +12,7 @@
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official Git repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#include "VideoCommon.h"
|
#include "VideoCommon.h"
|
||||||
|
@ -29,67 +29,67 @@
|
||||||
|
|
||||||
void InitBPMemory()
|
void InitBPMemory()
|
||||||
{
|
{
|
||||||
memset(&bpmem, 0, sizeof(bpmem));
|
memset(&bpmem, 0, sizeof(bpmem));
|
||||||
bpmem.bpMask = 0xFFFFFF;
|
bpmem.bpMask = 0xFFFFFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SWLoadBPReg(u32 value)
|
void SWLoadBPReg(u32 value)
|
||||||
{
|
{
|
||||||
//handle the mask register
|
//handle the mask register
|
||||||
int address = value >> 24;
|
int address = value >> 24;
|
||||||
int oldval = ((u32*)&bpmem)[address];
|
int oldval = ((u32*)&bpmem)[address];
|
||||||
int newval = (oldval & ~bpmem.bpMask) | (value & bpmem.bpMask);
|
int newval = (oldval & ~bpmem.bpMask) | (value & bpmem.bpMask);
|
||||||
|
|
||||||
((u32*)&bpmem)[address] = newval;
|
((u32*)&bpmem)[address] = newval;
|
||||||
|
|
||||||
//reset the mask register
|
//reset the mask register
|
||||||
if (address != 0xFE)
|
if (address != 0xFE)
|
||||||
bpmem.bpMask = 0xFFFFFF;
|
bpmem.bpMask = 0xFFFFFF;
|
||||||
|
|
||||||
SWBPWritten(address, newval);
|
SWBPWritten(address, newval);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SWBPWritten(int address, int newvalue)
|
void SWBPWritten(int address, int newvalue)
|
||||||
{
|
{
|
||||||
switch (address)
|
switch (address)
|
||||||
{
|
{
|
||||||
case BPMEM_SCISSORTL:
|
case BPMEM_SCISSORTL:
|
||||||
case BPMEM_SCISSORBR:
|
case BPMEM_SCISSORBR:
|
||||||
case BPMEM_SCISSOROFFSET:
|
case BPMEM_SCISSOROFFSET:
|
||||||
Rasterizer::SetScissor();
|
Rasterizer::SetScissor();
|
||||||
break;
|
break;
|
||||||
case BPMEM_SETDRAWDONE: // This is called when the game is done drawing (eg: like in DX: Begin(); Draw(); End();)
|
case BPMEM_SETDRAWDONE: // This is called when the game is done drawing (eg: like in DX: Begin(); Draw(); End();)
|
||||||
switch (bpmem.drawdone & 0xFF)
|
switch (bpmem.drawdone & 0xFF)
|
||||||
{
|
{
|
||||||
case 0x02:
|
case 0x02:
|
||||||
SWPixelEngine::SetFinish(); // may generate interrupt
|
SWPixelEngine::SetFinish(); // may generate interrupt
|
||||||
DEBUG_LOG(VIDEO, "GXSetDrawDone SetPEFinish (value: 0x%02X)", (bpmem.drawdone & 0xFFFF));
|
DEBUG_LOG(VIDEO, "GXSetDrawDone SetPEFinish (value: 0x%02X)", (bpmem.drawdone & 0xFFFF));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
WARN_LOG(VIDEO, "GXSetDrawDone ??? (value 0x%02X)", (bpmem.drawdone & 0xFFFF));
|
WARN_LOG(VIDEO, "GXSetDrawDone ??? (value 0x%02X)", (bpmem.drawdone & 0xFFFF));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case BPMEM_PE_TOKEN_ID: // Pixel Engine Token ID
|
case BPMEM_PE_TOKEN_ID: // Pixel Engine Token ID
|
||||||
DEBUG_LOG(VIDEO, "SetPEToken 0x%04x", (bpmem.petoken & 0xFFFF));
|
DEBUG_LOG(VIDEO, "SetPEToken 0x%04x", (bpmem.petoken & 0xFFFF));
|
||||||
SWPixelEngine::SetToken(static_cast<u16>(bpmem.petokenint & 0xFFFF), false);
|
SWPixelEngine::SetToken(static_cast<u16>(bpmem.petokenint & 0xFFFF), false);
|
||||||
break;
|
break;
|
||||||
case BPMEM_PE_TOKEN_INT_ID: // Pixel Engine Interrupt Token ID
|
case BPMEM_PE_TOKEN_INT_ID: // Pixel Engine Interrupt Token ID
|
||||||
DEBUG_LOG(VIDEO, "SetPEToken + INT 0x%04x", (bpmem.petokenint & 0xFFFF));
|
DEBUG_LOG(VIDEO, "SetPEToken + INT 0x%04x", (bpmem.petokenint & 0xFFFF));
|
||||||
SWPixelEngine::SetToken(static_cast<u16>(bpmem.petokenint & 0xFFFF), true);
|
SWPixelEngine::SetToken(static_cast<u16>(bpmem.petokenint & 0xFFFF), true);
|
||||||
break;
|
break;
|
||||||
case BPMEM_TRIGGER_EFB_COPY:
|
case BPMEM_TRIGGER_EFB_COPY:
|
||||||
EfbCopy::CopyEfb();
|
EfbCopy::CopyEfb();
|
||||||
break;
|
break;
|
||||||
case BPMEM_CLEARBBOX1:
|
case BPMEM_CLEARBBOX1:
|
||||||
SWPixelEngine::pereg.boxRight = newvalue >> 10;
|
SWPixelEngine::pereg.boxRight = newvalue >> 10;
|
||||||
SWPixelEngine::pereg.boxLeft = newvalue & 0x3ff;
|
SWPixelEngine::pereg.boxLeft = newvalue & 0x3ff;
|
||||||
break;
|
break;
|
||||||
case BPMEM_CLEARBBOX2:
|
case BPMEM_CLEARBBOX2:
|
||||||
SWPixelEngine::pereg.boxBottom = newvalue >> 10;
|
SWPixelEngine::pereg.boxBottom = newvalue >> 10;
|
||||||
SWPixelEngine::pereg.boxTop = newvalue & 0x3ff;
|
SWPixelEngine::pereg.boxTop = newvalue & 0x3ff;
|
||||||
break;
|
break;
|
||||||
case BPMEM_CLEAR_PIXEL_PERF:
|
case BPMEM_CLEAR_PIXEL_PERF:
|
||||||
// TODO: I didn't test if the value written to this register affects the amount of cleared registers
|
// TODO: I didn't test if the value written to this register affects the amount of cleared registers
|
||||||
SWPixelEngine::pereg.perfZcompInputZcomplocLo = 0;
|
SWPixelEngine::pereg.perfZcompInputZcomplocLo = 0;
|
||||||
|
@ -105,16 +105,16 @@ void SWBPWritten(int address, int newvalue)
|
||||||
SWPixelEngine::pereg.perfEfbCopyClocksLo = 0;
|
SWPixelEngine::pereg.perfEfbCopyClocksLo = 0;
|
||||||
SWPixelEngine::pereg.perfEfbCopyClocksHi = 0;
|
SWPixelEngine::pereg.perfEfbCopyClocksHi = 0;
|
||||||
break;
|
break;
|
||||||
case BPMEM_LOADTLUT0: // This one updates bpmem.tlutXferSrc, no need to do anything here.
|
case BPMEM_LOADTLUT0: // This one updates bpmem.tlutXferSrc, no need to do anything here.
|
||||||
break;
|
break;
|
||||||
case BPMEM_LOADTLUT1: // Load a Texture Look Up Table
|
case BPMEM_LOADTLUT1: // Load a Texture Look Up Table
|
||||||
{
|
{
|
||||||
u32 tlutTMemAddr = (newvalue & 0x3FF) << 9;
|
u32 tlutTMemAddr = (newvalue & 0x3FF) << 9;
|
||||||
u32 tlutXferCount = (newvalue & 0x1FFC00) >> 5;
|
u32 tlutXferCount = (newvalue & 0x1FFC00) >> 5;
|
||||||
|
|
||||||
u8 *ptr = 0;
|
u8 *ptr = 0;
|
||||||
|
|
||||||
// TODO - figure out a cleaner way.
|
// TODO - figure out a cleaner way.
|
||||||
if (Core::g_CoreStartupParameter.bWii)
|
if (Core::g_CoreStartupParameter.bWii)
|
||||||
ptr = Memory::GetPointer(bpmem.tmem_config.tlut_src << 5);
|
ptr = Memory::GetPointer(bpmem.tmem_config.tlut_src << 5);
|
||||||
else
|
else
|
||||||
|
@ -125,7 +125,7 @@ void SWBPWritten(int address, int newvalue)
|
||||||
else
|
else
|
||||||
PanicAlert("Invalid palette pointer %08x %08x %08x", bpmem.tmem_config.tlut_src, bpmem.tmem_config.tlut_src << 5, (bpmem.tmem_config.tlut_src & 0xFFFFF)<< 5);
|
PanicAlert("Invalid palette pointer %08x %08x %08x", bpmem.tmem_config.tlut_src, bpmem.tmem_config.tlut_src << 5, (bpmem.tmem_config.tlut_src & 0xFFFFF)<< 5);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case BPMEM_PRELOAD_MODE:
|
case BPMEM_PRELOAD_MODE:
|
||||||
if (newvalue != 0)
|
if (newvalue != 0)
|
||||||
|
@ -166,36 +166,36 @@ void SWBPWritten(int address, int newvalue)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BPMEM_TEV_REGISTER_L: // Reg 1
|
case BPMEM_TEV_REGISTER_L: // Reg 1
|
||||||
case BPMEM_TEV_REGISTER_L+2: // Reg 2
|
case BPMEM_TEV_REGISTER_L+2: // Reg 2
|
||||||
case BPMEM_TEV_REGISTER_L+4: // Reg 3
|
case BPMEM_TEV_REGISTER_L+4: // Reg 3
|
||||||
case BPMEM_TEV_REGISTER_L+6: // Reg 4
|
case BPMEM_TEV_REGISTER_L+6: // Reg 4
|
||||||
{
|
{
|
||||||
int regNum = (address >> 1 ) & 0x3;
|
int regNum = (address >> 1 ) & 0x3;
|
||||||
ColReg& reg = bpmem.tevregs[regNum].low;
|
ColReg& reg = bpmem.tevregs[regNum].low;
|
||||||
bool konst = reg.type;
|
bool konst = reg.type;
|
||||||
|
|
||||||
Rasterizer::SetTevReg(regNum, Tev::ALP_C, konst, reg.b); // A
|
Rasterizer::SetTevReg(regNum, Tev::ALP_C, konst, reg.b); // A
|
||||||
Rasterizer::SetTevReg(regNum, Tev::RED_C, konst, reg.a); // R
|
Rasterizer::SetTevReg(regNum, Tev::RED_C, konst, reg.a); // R
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case BPMEM_TEV_REGISTER_H: // Reg 1
|
case BPMEM_TEV_REGISTER_H: // Reg 1
|
||||||
case BPMEM_TEV_REGISTER_H+2: // Reg 2
|
case BPMEM_TEV_REGISTER_H+2: // Reg 2
|
||||||
case BPMEM_TEV_REGISTER_H+4: // Reg 3
|
case BPMEM_TEV_REGISTER_H+4: // Reg 3
|
||||||
case BPMEM_TEV_REGISTER_H+6: // Reg 4
|
case BPMEM_TEV_REGISTER_H+6: // Reg 4
|
||||||
{
|
{
|
||||||
int regNum = (address >> 1 ) & 0x3;
|
int regNum = (address >> 1 ) & 0x3;
|
||||||
ColReg& reg = bpmem.tevregs[regNum].high;
|
ColReg& reg = bpmem.tevregs[regNum].high;
|
||||||
bool konst = reg.type;
|
bool konst = reg.type;
|
||||||
|
|
||||||
Rasterizer::SetTevReg(regNum, Tev::GRN_C, konst, reg.b); // G
|
Rasterizer::SetTevReg(regNum, Tev::GRN_C, konst, reg.b); // G
|
||||||
Rasterizer::SetTevReg(regNum, Tev::BLU_C, konst, reg.a); // B
|
Rasterizer::SetTevReg(regNum, Tev::BLU_C, konst, reg.a); // B
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official Git repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#ifndef _BPMEMLOADER_H_
|
#ifndef _BPMEMLOADER_H_
|
||||||
|
|
|
@ -22,10 +22,10 @@
|
||||||
|
|
||||||
void SWLoadCPReg(u32 sub_cmd, u32 value)
|
void SWLoadCPReg(u32 sub_cmd, u32 value)
|
||||||
{
|
{
|
||||||
switch (sub_cmd & 0xF0)
|
switch (sub_cmd & 0xF0)
|
||||||
{
|
{
|
||||||
case 0x30:
|
case 0x30:
|
||||||
MatrixIndexA.Hex = value;
|
MatrixIndexA.Hex = value;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x40:
|
case 0x40:
|
||||||
|
@ -60,7 +60,7 @@ void SWLoadCPReg(u32 sub_cmd, u32 value)
|
||||||
// Pointers to vertex arrays in GC RAM
|
// Pointers to vertex arrays in GC RAM
|
||||||
case 0xA0:
|
case 0xA0:
|
||||||
arraybases[sub_cmd & 0xF] = value;
|
arraybases[sub_cmd & 0xF] = value;
|
||||||
cached_arraybases[sub_cmd & 0xF] = Memory::GetPointer(value);
|
cached_arraybases[sub_cmd & 0xF] = Memory::GetPointer(value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xB0:
|
case 0xB0:
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official Git repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#ifndef _CPMEMLOADER_H_
|
#ifndef _CPMEMLOADER_H_
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official Git repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -62,8 +62,8 @@ namespace Clipper
|
||||||
|
|
||||||
float m_ViewOffset[2];
|
float m_ViewOffset[2];
|
||||||
|
|
||||||
OutputVertexData ClippedVertices[NUM_CLIPPED_VERTICES];
|
OutputVertexData ClippedVertices[NUM_CLIPPED_VERTICES];
|
||||||
OutputVertexData *Vertices[NUM_INDICES];
|
OutputVertexData *Vertices[NUM_INDICES];
|
||||||
|
|
||||||
void DoState(PointerWrap &p)
|
void DoState(PointerWrap &p)
|
||||||
{
|
{
|
||||||
|
@ -72,94 +72,94 @@ namespace Clipper
|
||||||
ClippedVertices[i].DoState(p);
|
ClippedVertices[i].DoState(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Init()
|
void Init()
|
||||||
{
|
{
|
||||||
for (int i = 0; i < NUM_CLIPPED_VERTICES; ++i)
|
for (int i = 0; i < NUM_CLIPPED_VERTICES; ++i)
|
||||||
Vertices[i+3] = &ClippedVertices[i];
|
Vertices[i+3] = &ClippedVertices[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetViewOffset()
|
void SetViewOffset()
|
||||||
{
|
{
|
||||||
m_ViewOffset[0] = swxfregs.viewport.xOrig - 342;
|
m_ViewOffset[0] = swxfregs.viewport.xOrig - 342;
|
||||||
m_ViewOffset[1] = swxfregs.viewport.yOrig - 342;
|
m_ViewOffset[1] = swxfregs.viewport.yOrig - 342;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
enum {
|
|
||||||
SKIP_FLAG = -1,
|
|
||||||
CLIP_POS_X_BIT = 0x01,
|
|
||||||
CLIP_NEG_X_BIT = 0x02,
|
|
||||||
CLIP_POS_Y_BIT = 0x04,
|
|
||||||
CLIP_NEG_Y_BIT = 0x08,
|
|
||||||
CLIP_POS_Z_BIT = 0x10,
|
|
||||||
CLIP_NEG_Z_BIT = 0x20
|
|
||||||
};
|
|
||||||
|
|
||||||
static inline int CalcClipMask(OutputVertexData *v)
|
enum {
|
||||||
{
|
SKIP_FLAG = -1,
|
||||||
int cmask = 0;
|
CLIP_POS_X_BIT = 0x01,
|
||||||
Vec4 pos = v->projectedPosition;
|
CLIP_NEG_X_BIT = 0x02,
|
||||||
if (pos.w - pos.x < 0) cmask |= CLIP_POS_X_BIT;
|
CLIP_POS_Y_BIT = 0x04,
|
||||||
if (pos.x + pos.w < 0) cmask |= CLIP_NEG_X_BIT;
|
CLIP_NEG_Y_BIT = 0x08,
|
||||||
if (pos.w - pos.y < 0) cmask |= CLIP_POS_Y_BIT;
|
CLIP_POS_Z_BIT = 0x10,
|
||||||
if (pos.y + pos.w < 0) cmask |= CLIP_NEG_Y_BIT;
|
CLIP_NEG_Z_BIT = 0x20
|
||||||
if (pos.w * pos.z > 0) cmask |= CLIP_POS_Z_BIT;
|
};
|
||||||
if (pos.z + pos.w < 0) cmask |= CLIP_NEG_Z_BIT;
|
|
||||||
return cmask;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void AddInterpolatedVertex(float t, int out, int in, int& numVertices)
|
static inline int CalcClipMask(OutputVertexData *v)
|
||||||
{
|
{
|
||||||
Vertices[numVertices]->Lerp(t, Vertices[out], Vertices[in]);
|
int cmask = 0;
|
||||||
numVertices++;
|
Vec4 pos = v->projectedPosition;
|
||||||
}
|
if (pos.w - pos.x < 0) cmask |= CLIP_POS_X_BIT;
|
||||||
|
if (pos.x + pos.w < 0) cmask |= CLIP_NEG_X_BIT;
|
||||||
|
if (pos.w - pos.y < 0) cmask |= CLIP_POS_Y_BIT;
|
||||||
|
if (pos.y + pos.w < 0) cmask |= CLIP_NEG_Y_BIT;
|
||||||
|
if (pos.w * pos.z > 0) cmask |= CLIP_POS_Z_BIT;
|
||||||
|
if (pos.z + pos.w < 0) cmask |= CLIP_NEG_Z_BIT;
|
||||||
|
return cmask;
|
||||||
|
}
|
||||||
|
|
||||||
#define DIFFERENT_SIGNS(x,y) ((x <= 0 && y > 0) || (x > 0 && y <= 0))
|
static inline void AddInterpolatedVertex(float t, int out, int in, int& numVertices)
|
||||||
|
{
|
||||||
|
Vertices[numVertices]->Lerp(t, Vertices[out], Vertices[in]);
|
||||||
|
numVertices++;
|
||||||
|
}
|
||||||
|
|
||||||
#define CLIP_DOTPROD(I, A, B, C, D) \
|
#define DIFFERENT_SIGNS(x,y) ((x <= 0 && y > 0) || (x > 0 && y <= 0))
|
||||||
(Vertices[I]->projectedPosition.x * A + Vertices[I]->projectedPosition.y * B + Vertices[I]->projectedPosition.z * C + Vertices[I]->projectedPosition.w * D)
|
|
||||||
|
|
||||||
#define POLY_CLIP( PLANE_BIT, A, B, C, D ) \
|
#define CLIP_DOTPROD(I, A, B, C, D) \
|
||||||
{ \
|
(Vertices[I]->projectedPosition.x * A + Vertices[I]->projectedPosition.y * B + Vertices[I]->projectedPosition.z * C + Vertices[I]->projectedPosition.w * D)
|
||||||
if (mask & PLANE_BIT) { \
|
|
||||||
int idxPrev = inlist[0]; \
|
#define POLY_CLIP( PLANE_BIT, A, B, C, D ) \
|
||||||
float dpPrev = CLIP_DOTPROD(idxPrev, A, B, C, D ); \
|
{ \
|
||||||
int outcount = 0; \
|
if (mask & PLANE_BIT) { \
|
||||||
\
|
int idxPrev = inlist[0]; \
|
||||||
inlist[n] = inlist[0]; \
|
float dpPrev = CLIP_DOTPROD(idxPrev, A, B, C, D ); \
|
||||||
for (int j = 1; j <= n; j++) { \
|
int outcount = 0; \
|
||||||
int idx = inlist[j]; \
|
\
|
||||||
float dp = CLIP_DOTPROD(idx, A, B, C, D ); \
|
inlist[n] = inlist[0]; \
|
||||||
if (dpPrev >= 0) { \
|
for (int j = 1; j <= n; j++) { \
|
||||||
outlist[outcount++] = idxPrev; \
|
int idx = inlist[j]; \
|
||||||
} \
|
float dp = CLIP_DOTPROD(idx, A, B, C, D ); \
|
||||||
\
|
if (dpPrev >= 0) { \
|
||||||
if (DIFFERENT_SIGNS(dp, dpPrev)) { \
|
outlist[outcount++] = idxPrev; \
|
||||||
if (dp < 0) { \
|
} \
|
||||||
float t = dp / (dp - dpPrev); \
|
\
|
||||||
AddInterpolatedVertex(t, idx, idxPrev, numVertices); \
|
if (DIFFERENT_SIGNS(dp, dpPrev)) { \
|
||||||
} else { \
|
if (dp < 0) { \
|
||||||
float t = dpPrev / (dpPrev - dp); \
|
float t = dp / (dp - dpPrev); \
|
||||||
AddInterpolatedVertex(t, idxPrev, idx, numVertices); \
|
AddInterpolatedVertex(t, idx, idxPrev, numVertices); \
|
||||||
} \
|
} else { \
|
||||||
outlist[outcount++] = numVertices - 1; \
|
float t = dpPrev / (dpPrev - dp); \
|
||||||
} \
|
AddInterpolatedVertex(t, idxPrev, idx, numVertices); \
|
||||||
\
|
} \
|
||||||
idxPrev = idx; \
|
outlist[outcount++] = numVertices - 1; \
|
||||||
dpPrev = dp; \
|
} \
|
||||||
} \
|
\
|
||||||
\
|
idxPrev = idx; \
|
||||||
if (outcount < 3) \
|
dpPrev = dp; \
|
||||||
continue; \
|
} \
|
||||||
\
|
\
|
||||||
{ \
|
if (outcount < 3) \
|
||||||
int *tmp = inlist; \
|
continue; \
|
||||||
inlist = outlist; \
|
\
|
||||||
outlist = tmp; \
|
{ \
|
||||||
n = outcount; \
|
int *tmp = inlist; \
|
||||||
} \
|
inlist = outlist; \
|
||||||
} \
|
outlist = tmp; \
|
||||||
}
|
n = outcount; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
#define LINE_CLIP(PLANE_BIT, A, B, C, D ) \
|
#define LINE_CLIP(PLANE_BIT, A, B, C, D ) \
|
||||||
{ \
|
{ \
|
||||||
|
@ -173,63 +173,63 @@ namespace Clipper
|
||||||
return; \
|
return; \
|
||||||
\
|
\
|
||||||
if (neg_dp1) { \
|
if (neg_dp1) { \
|
||||||
float t = dp1 / (dp1 - dp0); \
|
float t = dp1 / (dp1 - dp0); \
|
||||||
if (t > t1) t1 = t; \
|
if (t > t1) t1 = t; \
|
||||||
} else if (neg_dp0) { \
|
} else if (neg_dp0) { \
|
||||||
float t = dp0 / (dp0 - dp1); \
|
float t = dp0 / (dp0 - dp1); \
|
||||||
if (t > t0) t0 = t; \
|
if (t > t0) t0 = t; \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClipTriangle(int *indices, int &numIndices)
|
void ClipTriangle(int *indices, int &numIndices)
|
||||||
{
|
{
|
||||||
int mask = 0;
|
int mask = 0;
|
||||||
|
|
||||||
mask |= CalcClipMask(Vertices[0]);
|
|
||||||
mask |= CalcClipMask(Vertices[1]);
|
|
||||||
mask |= CalcClipMask(Vertices[2]);
|
|
||||||
|
|
||||||
if (mask != 0)
|
mask |= CalcClipMask(Vertices[0]);
|
||||||
{
|
mask |= CalcClipMask(Vertices[1]);
|
||||||
for(int i = 0; i < 3; i += 3)
|
mask |= CalcClipMask(Vertices[2]);
|
||||||
{
|
|
||||||
int vlist[2][2*6+1];
|
|
||||||
int *inlist = vlist[0], *outlist = vlist[1];
|
|
||||||
int n = 3;
|
|
||||||
int numVertices = 3;
|
|
||||||
|
|
||||||
inlist[0] = 0;
|
if (mask != 0)
|
||||||
inlist[1] = 1;
|
{
|
||||||
inlist[2] = 2;
|
for(int i = 0; i < 3; i += 3)
|
||||||
|
{
|
||||||
|
int vlist[2][2*6+1];
|
||||||
|
int *inlist = vlist[0], *outlist = vlist[1];
|
||||||
|
int n = 3;
|
||||||
|
int numVertices = 3;
|
||||||
|
|
||||||
// mark this triangle as unused in case it should be completely
|
inlist[0] = 0;
|
||||||
// clipped
|
inlist[1] = 1;
|
||||||
indices[0] = SKIP_FLAG;
|
inlist[2] = 2;
|
||||||
indices[1] = SKIP_FLAG;
|
|
||||||
indices[2] = SKIP_FLAG;
|
|
||||||
|
|
||||||
POLY_CLIP(CLIP_POS_X_BIT, -1, 0, 0, 1);
|
// mark this triangle as unused in case it should be completely
|
||||||
POLY_CLIP(CLIP_NEG_X_BIT, 1, 0, 0, 1);
|
// clipped
|
||||||
POLY_CLIP(CLIP_POS_Y_BIT, 0, -1, 0, 1);
|
indices[0] = SKIP_FLAG;
|
||||||
POLY_CLIP(CLIP_NEG_Y_BIT, 0, 1, 0, 1);
|
indices[1] = SKIP_FLAG;
|
||||||
POLY_CLIP(CLIP_POS_Z_BIT, 0, 0, 0, 1);
|
indices[2] = SKIP_FLAG;
|
||||||
POLY_CLIP(CLIP_NEG_Z_BIT, 0, 0, 1, 1);
|
|
||||||
|
|
||||||
INCSTAT(swstats.thisFrame.numTrianglesClipped);
|
POLY_CLIP(CLIP_POS_X_BIT, -1, 0, 0, 1);
|
||||||
|
POLY_CLIP(CLIP_NEG_X_BIT, 1, 0, 0, 1);
|
||||||
|
POLY_CLIP(CLIP_POS_Y_BIT, 0, -1, 0, 1);
|
||||||
|
POLY_CLIP(CLIP_NEG_Y_BIT, 0, 1, 0, 1);
|
||||||
|
POLY_CLIP(CLIP_POS_Z_BIT, 0, 0, 0, 1);
|
||||||
|
POLY_CLIP(CLIP_NEG_Z_BIT, 0, 0, 1, 1);
|
||||||
|
|
||||||
// transform the poly in inlist into triangles
|
INCSTAT(swstats.thisFrame.numTrianglesClipped);
|
||||||
indices[0] = inlist[0];
|
|
||||||
indices[1] = inlist[1];
|
// transform the poly in inlist into triangles
|
||||||
indices[2] = inlist[2];
|
indices[0] = inlist[0];
|
||||||
for (int j = 3; j < n; ++j) {
|
indices[1] = inlist[1];
|
||||||
indices[numIndices++] = inlist[0];
|
indices[2] = inlist[2];
|
||||||
indices[numIndices++] = inlist[j - 1];
|
for (int j = 3; j < n; ++j) {
|
||||||
indices[numIndices++] = inlist[j];
|
indices[numIndices++] = inlist[0];
|
||||||
}
|
indices[numIndices++] = inlist[j - 1];
|
||||||
}
|
indices[numIndices++] = inlist[j];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ClipLine(int *indices)
|
void ClipLine(int *indices)
|
||||||
{
|
{
|
||||||
|
@ -267,59 +267,61 @@ namespace Clipper
|
||||||
|
|
||||||
int numVertices = 2;
|
int numVertices = 2;
|
||||||
|
|
||||||
if (clip_mask[0]) {
|
if (clip_mask[0])
|
||||||
|
{
|
||||||
indices[0] = numVertices;
|
indices[0] = numVertices;
|
||||||
AddInterpolatedVertex(t0, 0, 1, numVertices);
|
AddInterpolatedVertex(t0, 0, 1, numVertices);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (clip_mask[1]) {
|
if (clip_mask[1])
|
||||||
|
{
|
||||||
indices[1] = numVertices;
|
indices[1] = numVertices;
|
||||||
AddInterpolatedVertex(t1, 1, 0, numVertices);
|
AddInterpolatedVertex(t1, 1, 0, numVertices);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProcessTriangle(OutputVertexData *v0, OutputVertexData *v1, OutputVertexData *v2)
|
void ProcessTriangle(OutputVertexData *v0, OutputVertexData *v1, OutputVertexData *v2)
|
||||||
{
|
{
|
||||||
INCSTAT(swstats.thisFrame.numTrianglesIn)
|
INCSTAT(swstats.thisFrame.numTrianglesIn)
|
||||||
|
|
||||||
bool backface;
|
bool backface;
|
||||||
|
|
||||||
if(!CullTest(v0, v1, v2, backface))
|
if(!CullTest(v0, v1, v2, backface))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
int indices[NUM_INDICES] = { 0, 1, 2, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG,
|
|
||||||
SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG,
|
|
||||||
SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG };
|
|
||||||
int numIndices = 3;
|
|
||||||
|
|
||||||
if (backface)
|
int indices[NUM_INDICES] = { 0, 1, 2, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG,
|
||||||
{
|
SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG,
|
||||||
Vertices[0] = v0;
|
SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG, SKIP_FLAG };
|
||||||
Vertices[1] = v2;
|
int numIndices = 3;
|
||||||
Vertices[2] = v1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Vertices[0] = v0;
|
|
||||||
Vertices[1] = v1;
|
|
||||||
Vertices[2] = v2;
|
|
||||||
}
|
|
||||||
|
|
||||||
ClipTriangle(indices, numIndices);
|
if (backface)
|
||||||
|
{
|
||||||
|
Vertices[0] = v0;
|
||||||
|
Vertices[1] = v2;
|
||||||
|
Vertices[2] = v1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Vertices[0] = v0;
|
||||||
|
Vertices[1] = v1;
|
||||||
|
Vertices[2] = v2;
|
||||||
|
}
|
||||||
|
|
||||||
for(int i = 0; i+3 <= numIndices; i+=3)
|
ClipTriangle(indices, numIndices);
|
||||||
{
|
|
||||||
|
for(int i = 0; i+3 <= numIndices; i+=3)
|
||||||
|
{
|
||||||
_assert_(i < NUM_INDICES);
|
_assert_(i < NUM_INDICES);
|
||||||
if(indices[i] != SKIP_FLAG)
|
if(indices[i] != SKIP_FLAG)
|
||||||
{
|
{
|
||||||
PerspectiveDivide(Vertices[indices[i]]);
|
PerspectiveDivide(Vertices[indices[i]]);
|
||||||
PerspectiveDivide(Vertices[indices[i+1]]);
|
PerspectiveDivide(Vertices[indices[i+1]]);
|
||||||
PerspectiveDivide(Vertices[indices[i+2]]);
|
PerspectiveDivide(Vertices[indices[i+2]]);
|
||||||
|
|
||||||
Rasterizer::DrawTriangleFrontFace(Vertices[indices[i]], Vertices[indices[i+1]], Vertices[indices[i+2]]);
|
Rasterizer::DrawTriangleFrontFace(Vertices[indices[i]], Vertices[indices[i+1]], Vertices[indices[i+2]]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CopyVertex(OutputVertexData *dst, OutputVertexData *src, float dx, float dy, unsigned int sOffset)
|
void CopyVertex(OutputVertexData *dst, OutputVertexData *src, float dx, float dy, unsigned int sOffset)
|
||||||
{
|
{
|
||||||
|
@ -343,7 +345,7 @@ namespace Clipper
|
||||||
int indices[4] = { 0, 1, SKIP_FLAG, SKIP_FLAG };
|
int indices[4] = { 0, 1, SKIP_FLAG, SKIP_FLAG };
|
||||||
|
|
||||||
Vertices[0] = lineV0;
|
Vertices[0] = lineV0;
|
||||||
Vertices[1] = lineV1;
|
Vertices[1] = lineV1;
|
||||||
|
|
||||||
// point to a valid vertex to store to when clipping
|
// point to a valid vertex to store to when clipping
|
||||||
Vertices[2] = &ClippedVertices[17];
|
Vertices[2] = &ClippedVertices[17];
|
||||||
|
@ -356,7 +358,7 @@ namespace Clipper
|
||||||
OutputVertexData *v1 = Vertices[indices[1]];
|
OutputVertexData *v1 = Vertices[indices[1]];
|
||||||
|
|
||||||
PerspectiveDivide(v0);
|
PerspectiveDivide(v0);
|
||||||
PerspectiveDivide(v1);
|
PerspectiveDivide(v1);
|
||||||
|
|
||||||
float dx = v1->screenPosition.x - v0->screenPosition.x;
|
float dx = v1->screenPosition.x - v0->screenPosition.x;
|
||||||
float dy = v1->screenPosition.y - v0->screenPosition.y;
|
float dy = v1->screenPosition.y - v0->screenPosition.y;
|
||||||
|
@ -393,57 +395,57 @@ namespace Clipper
|
||||||
Rasterizer::DrawTriangleFrontFace(&triangle[0], &triangle[1], &triangle[2]);
|
Rasterizer::DrawTriangleFrontFace(&triangle[0], &triangle[1], &triangle[2]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CullTest(OutputVertexData *v0, OutputVertexData *v1, OutputVertexData *v2, bool &backface)
|
|
||||||
{
|
|
||||||
int mask = CalcClipMask(v0);
|
|
||||||
mask &= CalcClipMask(v1);
|
|
||||||
mask &= CalcClipMask(v2);
|
|
||||||
|
|
||||||
if(mask)
|
bool CullTest(OutputVertexData *v0, OutputVertexData *v1, OutputVertexData *v2, bool &backface)
|
||||||
{
|
{
|
||||||
INCSTAT(swstats.thisFrame.numTrianglesRejected)
|
int mask = CalcClipMask(v0);
|
||||||
return false;
|
mask &= CalcClipMask(v1);
|
||||||
}
|
mask &= CalcClipMask(v2);
|
||||||
|
|
||||||
float x0 = v0->projectedPosition.x;
|
if(mask)
|
||||||
float x1 = v1->projectedPosition.x;
|
{
|
||||||
float x2 = v2->projectedPosition.x;
|
INCSTAT(swstats.thisFrame.numTrianglesRejected)
|
||||||
float y1 = v1->projectedPosition.y;
|
return false;
|
||||||
float y0 = v0->projectedPosition.y;
|
}
|
||||||
float y2 = v2->projectedPosition.y;
|
|
||||||
float w0 = v0->projectedPosition.w;
|
|
||||||
float w1 = v1->projectedPosition.w;
|
|
||||||
float w2 = v2->projectedPosition.w;
|
|
||||||
|
|
||||||
float normalZDir = (x0*w2 - x2*w0)*y1 + (x2*y0 - x0*y2)*w1 + (y2*w0 - y0*w2)*x1;
|
float x0 = v0->projectedPosition.x;
|
||||||
|
float x1 = v1->projectedPosition.x;
|
||||||
|
float x2 = v2->projectedPosition.x;
|
||||||
|
float y1 = v1->projectedPosition.y;
|
||||||
|
float y0 = v0->projectedPosition.y;
|
||||||
|
float y2 = v2->projectedPosition.y;
|
||||||
|
float w0 = v0->projectedPosition.w;
|
||||||
|
float w1 = v1->projectedPosition.w;
|
||||||
|
float w2 = v2->projectedPosition.w;
|
||||||
|
|
||||||
backface = normalZDir <= 0.0f;
|
float normalZDir = (x0*w2 - x2*w0)*y1 + (x2*y0 - x0*y2)*w1 + (y2*w0 - y0*w2)*x1;
|
||||||
|
|
||||||
if ((bpmem.genMode.cullmode & 1) && !backface) // cull frontfacing
|
backface = normalZDir <= 0.0f;
|
||||||
{
|
|
||||||
INCSTAT(swstats.thisFrame.numTrianglesCulled)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((bpmem.genMode.cullmode & 2) && backface) // cull backfacing
|
if ((bpmem.genMode.cullmode & 1) && !backface) // cull frontfacing
|
||||||
{
|
{
|
||||||
INCSTAT(swstats.thisFrame.numTrianglesCulled)
|
INCSTAT(swstats.thisFrame.numTrianglesCulled)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
if ((bpmem.genMode.cullmode & 2) && backface) // cull backfacing
|
||||||
}
|
{
|
||||||
|
INCSTAT(swstats.thisFrame.numTrianglesCulled)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void PerspectiveDivide(OutputVertexData *vertex)
|
return true;
|
||||||
{
|
}
|
||||||
Vec4 &projected = vertex->projectedPosition;
|
|
||||||
Vec3 &screen = vertex->screenPosition;
|
void PerspectiveDivide(OutputVertexData *vertex)
|
||||||
|
{
|
||||||
|
Vec4 &projected = vertex->projectedPosition;
|
||||||
|
Vec3 &screen = vertex->screenPosition;
|
||||||
|
|
||||||
|
float wInverse = 1.0f/projected.w;
|
||||||
|
screen.x = projected.x * wInverse * swxfregs.viewport.wd + m_ViewOffset[0];
|
||||||
|
screen.y = projected.y * wInverse * swxfregs.viewport.ht + m_ViewOffset[1];
|
||||||
|
screen.z = projected.z * wInverse * swxfregs.viewport.zRange + swxfregs.viewport.farZ;
|
||||||
|
}
|
||||||
|
|
||||||
float wInverse = 1.0f/projected.w;
|
|
||||||
screen.x = projected.x * wInverse * swxfregs.viewport.wd + m_ViewOffset[0];
|
|
||||||
screen.y = projected.y * wInverse * swxfregs.viewport.ht + m_ViewOffset[1];
|
|
||||||
screen.z = projected.z * wInverse * swxfregs.viewport.zRange + swxfregs.viewport.farZ;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official Git repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#ifndef _CLIPPER_H_
|
#ifndef _CLIPPER_H_
|
||||||
|
@ -26,17 +26,17 @@
|
||||||
|
|
||||||
namespace Clipper
|
namespace Clipper
|
||||||
{
|
{
|
||||||
void Init();
|
void Init();
|
||||||
|
|
||||||
void SetViewOffset();
|
void SetViewOffset();
|
||||||
|
|
||||||
void ProcessTriangle(OutputVertexData *v0, OutputVertexData *v1, OutputVertexData *v2);
|
void ProcessTriangle(OutputVertexData *v0, OutputVertexData *v1, OutputVertexData *v2);
|
||||||
|
|
||||||
void ProcessLine(OutputVertexData *v0, OutputVertexData *v1);
|
void ProcessLine(OutputVertexData *v0, OutputVertexData *v1);
|
||||||
|
|
||||||
bool CullTest(OutputVertexData *v0, OutputVertexData *v1, OutputVertexData *v2, bool &backface);
|
bool CullTest(OutputVertexData *v0, OutputVertexData *v1, OutputVertexData *v2, bool &backface);
|
||||||
|
|
||||||
void PerspectiveDivide(OutputVertexData *vertex);
|
void PerspectiveDivide(OutputVertexData *vertex);
|
||||||
|
|
||||||
void DoState(PointerWrap &p);
|
void DoState(PointerWrap &p);
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official Git repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
|
@ -46,57 +46,57 @@ int BufferBase[NumObjectBuffers];
|
||||||
|
|
||||||
void Init()
|
void Init()
|
||||||
{
|
{
|
||||||
for (int i = 0; i < NumObjectBuffers; i++)
|
for (int i = 0; i < NumObjectBuffers; i++)
|
||||||
{
|
{
|
||||||
memset(ObjectBuffer[i], 0, sizeof(ObjectBuffer[i]));
|
memset(ObjectBuffer[i], 0, sizeof(ObjectBuffer[i]));
|
||||||
DrawnToBuffer[i] = false;
|
DrawnToBuffer[i] = false;
|
||||||
ObjectBufferName[i] = 0;
|
ObjectBufferName[i] = 0;
|
||||||
BufferBase[i] = 0;
|
BufferBase[i] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SaveTexture(const char* filename, u32 texmap, s32 mip)
|
void SaveTexture(const char* filename, u32 texmap, s32 mip)
|
||||||
{
|
{
|
||||||
FourTexUnits& texUnit = bpmem.tex[(texmap >> 2) & 1];
|
FourTexUnits& texUnit = bpmem.tex[(texmap >> 2) & 1];
|
||||||
u8 subTexmap = texmap & 3;
|
u8 subTexmap = texmap & 3;
|
||||||
|
|
||||||
TexImage0& ti0 = texUnit.texImage0[subTexmap];
|
TexImage0& ti0 = texUnit.texImage0[subTexmap];
|
||||||
|
|
||||||
u32 width = ti0.width + 1;
|
u32 width = ti0.width + 1;
|
||||||
u32 height = ti0.height + 1;
|
u32 height = ti0.height + 1;
|
||||||
|
|
||||||
u8 *data = new u8[width * height * 4];
|
u8 *data = new u8[width * height * 4];
|
||||||
|
|
||||||
GetTextureBGRA(data, texmap, mip, width, height);
|
|
||||||
|
|
||||||
(void)SaveTGA(filename, width, height, data);
|
GetTextureBGRA(data, texmap, mip, width, height);
|
||||||
|
|
||||||
delete []data;
|
(void)SaveTGA(filename, width, height, data);
|
||||||
|
|
||||||
|
delete []data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GetTextureBGRA(u8 *dst, u32 texmap, s32 mip, u32 width, u32 height)
|
void GetTextureBGRA(u8 *dst, u32 texmap, s32 mip, u32 width, u32 height)
|
||||||
{
|
{
|
||||||
u8 sample[4];
|
u8 sample[4];
|
||||||
|
|
||||||
for (u32 y = 0; y < height; y++)
|
for (u32 y = 0; y < height; y++)
|
||||||
{
|
{
|
||||||
for (u32 x = 0; x < width; x++)
|
for (u32 x = 0; x < width; x++)
|
||||||
{
|
{
|
||||||
TextureSampler::SampleMip(x << 7, y << 7, mip, false, texmap, sample);
|
TextureSampler::SampleMip(x << 7, y << 7, mip, false, texmap, sample);
|
||||||
|
|
||||||
// RGBA to BGRA
|
// RGBA to BGRA
|
||||||
*(dst++) = sample[2];
|
*(dst++) = sample[2];
|
||||||
*(dst++) = sample[1];
|
*(dst++) = sample[1];
|
||||||
*(dst++) = sample[0];
|
*(dst++) = sample[0];
|
||||||
*(dst++) = sample[3];
|
*(dst++) = sample[3];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 GetMaxTextureLod(u32 texmap)
|
s32 GetMaxTextureLod(u32 texmap)
|
||||||
{
|
{
|
||||||
FourTexUnits& texUnit = bpmem.tex[(texmap >> 2) & 1];
|
FourTexUnits& texUnit = bpmem.tex[(texmap >> 2) & 1];
|
||||||
u8 subTexmap = texmap & 3;
|
u8 subTexmap = texmap & 3;
|
||||||
|
|
||||||
u8 maxLod = texUnit.texMode1[subTexmap].max_lod;
|
u8 maxLod = texUnit.texMode1[subTexmap].max_lod;
|
||||||
u8 mip = maxLod >> 4;
|
u8 mip = maxLod >> 4;
|
||||||
|
@ -110,9 +110,9 @@ s32 GetMaxTextureLod(u32 texmap)
|
||||||
|
|
||||||
void DumpActiveTextures()
|
void DumpActiveTextures()
|
||||||
{
|
{
|
||||||
for (unsigned int stageNum = 0; stageNum < bpmem.genMode.numindstages; stageNum++)
|
for (unsigned int stageNum = 0; stageNum < bpmem.genMode.numindstages; stageNum++)
|
||||||
{
|
{
|
||||||
u32 texmap = bpmem.tevindref.getTexMap(stageNum);
|
u32 texmap = bpmem.tevindref.getTexMap(stageNum);
|
||||||
|
|
||||||
s32 maxLod = GetMaxTextureLod(texmap);
|
s32 maxLod = GetMaxTextureLod(texmap);
|
||||||
for (s32 mip = 0; mip <= maxLod; ++mip)
|
for (s32 mip = 0; mip <= maxLod; ++mip)
|
||||||
|
@ -121,90 +121,96 @@ void DumpActiveTextures()
|
||||||
File::GetUserPath(D_DUMPTEXTURES_IDX).c_str(),
|
File::GetUserPath(D_DUMPTEXTURES_IDX).c_str(),
|
||||||
swstats.thisFrame.numDrawnObjects, stageNum, texmap, mip).c_str(), texmap, mip);
|
swstats.thisFrame.numDrawnObjects, stageNum, texmap, mip).c_str(), texmap, mip);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (unsigned int stageNum = 0; stageNum <= bpmem.genMode.numtevstages; stageNum++)
|
for (unsigned int stageNum = 0; stageNum <= bpmem.genMode.numtevstages; stageNum++)
|
||||||
{
|
{
|
||||||
int stageNum2 = stageNum >> 1;
|
int stageNum2 = stageNum >> 1;
|
||||||
int stageOdd = stageNum&1;
|
int stageOdd = stageNum&1;
|
||||||
TwoTevStageOrders &order = bpmem.tevorders[stageNum2];
|
TwoTevStageOrders &order = bpmem.tevorders[stageNum2];
|
||||||
|
|
||||||
int texmap = order.getTexMap(stageOdd);
|
int texmap = order.getTexMap(stageOdd);
|
||||||
|
|
||||||
s32 maxLod = GetMaxTextureLod(texmap);
|
s32 maxLod = GetMaxTextureLod(texmap);
|
||||||
for (s32 mip = 0; mip <= maxLod; ++mip)
|
for (s32 mip = 0; mip <= maxLod; ++mip)
|
||||||
{
|
{
|
||||||
SaveTexture(StringFromFormat("%star%i_stage%i_map%i_mip%i.tga",
|
SaveTexture(StringFromFormat("%star%i_stage%i_map%i_mip%i.tga",
|
||||||
File::GetUserPath(D_DUMPTEXTURES_IDX).c_str(),
|
File::GetUserPath(D_DUMPTEXTURES_IDX).c_str(),
|
||||||
swstats.thisFrame.numDrawnObjects, stageNum, texmap, mip).c_str(), texmap, mip);
|
swstats.thisFrame.numDrawnObjects, stageNum, texmap, mip).c_str(), texmap, mip);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DumpEfb(const char* filename)
|
void DumpEfb(const char* filename)
|
||||||
{
|
{
|
||||||
u8 *data = new u8[EFB_WIDTH * EFB_HEIGHT * 4];
|
u8 *data = new u8[EFB_WIDTH * EFB_HEIGHT * 4];
|
||||||
u8 *writePtr = data;
|
u8 *writePtr = data;
|
||||||
u8 sample[4];
|
u8 sample[4];
|
||||||
|
|
||||||
for (int y = 0; y < EFB_HEIGHT; y++)
|
for (int y = 0; y < EFB_HEIGHT; y++)
|
||||||
for (int x = 0; x < EFB_WIDTH; x++) {
|
{
|
||||||
EfbInterface::GetColor(x, y, sample);
|
for (int x = 0; x < EFB_WIDTH; x++)
|
||||||
// ABGR to BGRA
|
{
|
||||||
*(writePtr++) = sample[1];
|
EfbInterface::GetColor(x, y, sample);
|
||||||
*(writePtr++) = sample[2];
|
// ABGR to BGRA
|
||||||
*(writePtr++) = sample[3];
|
*(writePtr++) = sample[1];
|
||||||
*(writePtr++) = sample[0];
|
*(writePtr++) = sample[2];
|
||||||
}
|
*(writePtr++) = sample[3];
|
||||||
|
*(writePtr++) = sample[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
(void)SaveTGA(filename, EFB_WIDTH, EFB_HEIGHT, data);
|
(void)SaveTGA(filename, EFB_WIDTH, EFB_HEIGHT, data);
|
||||||
|
|
||||||
delete []data;
|
delete []data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DumpDepth(const char* filename)
|
void DumpDepth(const char* filename)
|
||||||
{
|
{
|
||||||
u8 *data = new u8[EFB_WIDTH * EFB_HEIGHT * 4];
|
u8 *data = new u8[EFB_WIDTH * EFB_HEIGHT * 4];
|
||||||
u8 *writePtr = data;
|
u8 *writePtr = data;
|
||||||
|
|
||||||
for (int y = 0; y < EFB_HEIGHT; y++)
|
for (int y = 0; y < EFB_HEIGHT; y++)
|
||||||
for (int x = 0; x < EFB_WIDTH; x++) {
|
{
|
||||||
u32 depth = EfbInterface::GetDepth(x, y);
|
for (int x = 0; x < EFB_WIDTH; x++)
|
||||||
// depth to bgra
|
{
|
||||||
*(writePtr++) = (depth >> 16) & 0xff;
|
u32 depth = EfbInterface::GetDepth(x, y);
|
||||||
*(writePtr++) = (depth >> 8) & 0xff;
|
// depth to bgra
|
||||||
*(writePtr++) = depth & 0xff;
|
*(writePtr++) = (depth >> 16) & 0xff;
|
||||||
*(writePtr++) = 255;
|
*(writePtr++) = (depth >> 8) & 0xff;
|
||||||
}
|
*(writePtr++) = depth & 0xff;
|
||||||
|
*(writePtr++) = 255;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
(void)SaveTGA(filename, EFB_WIDTH, EFB_HEIGHT, data);
|
(void)SaveTGA(filename, EFB_WIDTH, EFB_HEIGHT, data);
|
||||||
|
|
||||||
delete []data;
|
delete []data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrawObjectBuffer(s16 x, s16 y, u8 *color, int bufferBase, int subBuffer, const char *name)
|
void DrawObjectBuffer(s16 x, s16 y, u8 *color, int bufferBase, int subBuffer, const char *name)
|
||||||
{
|
{
|
||||||
int buffer = bufferBase + subBuffer;
|
int buffer = bufferBase + subBuffer;
|
||||||
|
|
||||||
u32 offset = (x + y * EFB_WIDTH) * 4;
|
u32 offset = (x + y * EFB_WIDTH) * 4;
|
||||||
u8 *dst = (u8*)&ObjectBuffer[buffer][offset];
|
u8 *dst = (u8*)&ObjectBuffer[buffer][offset];
|
||||||
*(dst++) = color[2];
|
*(dst++) = color[2];
|
||||||
*(dst++) = color[1];
|
*(dst++) = color[1];
|
||||||
*(dst++) = color[0];
|
*(dst++) = color[0];
|
||||||
*(dst++) = color[3];
|
*(dst++) = color[3];
|
||||||
|
|
||||||
DrawnToBuffer[buffer] = true;
|
DrawnToBuffer[buffer] = true;
|
||||||
ObjectBufferName[buffer] = name;
|
ObjectBufferName[buffer] = name;
|
||||||
BufferBase[buffer] = bufferBase;
|
BufferBase[buffer] = bufferBase;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrawTempBuffer(u8 *color, int buffer)
|
void DrawTempBuffer(u8 *color, int buffer)
|
||||||
{
|
{
|
||||||
u8 *dst = (u8*)&TempBuffer[buffer];
|
u8 *dst = (u8*)&TempBuffer[buffer];
|
||||||
*(dst++) = color[2];
|
*(dst++) = color[2];
|
||||||
*(dst++) = color[1];
|
*(dst++) = color[1];
|
||||||
*(dst++) = color[0];
|
*(dst++) = color[0];
|
||||||
*(dst++) = color[3];
|
*(dst++) = color[3];
|
||||||
}
|
}
|
||||||
|
|
||||||
void CopyTempBuffer(s16 x, s16 y, int bufferBase, int subBuffer, const char *name)
|
void CopyTempBuffer(s16 x, s16 y, int bufferBase, int subBuffer, const char *name)
|
||||||
|
@ -215,69 +221,69 @@ void CopyTempBuffer(s16 x, s16 y, int bufferBase, int subBuffer, const char *nam
|
||||||
ObjectBuffer[buffer][offset] = TempBuffer[buffer];
|
ObjectBuffer[buffer][offset] = TempBuffer[buffer];
|
||||||
|
|
||||||
DrawnToBuffer[buffer] = true;
|
DrawnToBuffer[buffer] = true;
|
||||||
ObjectBufferName[buffer] = name;
|
ObjectBufferName[buffer] = name;
|
||||||
BufferBase[buffer] = bufferBase;
|
BufferBase[buffer] = bufferBase;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnObjectBegin()
|
void OnObjectBegin()
|
||||||
{
|
{
|
||||||
if (!g_bSkipCurrentFrame)
|
if (!g_bSkipCurrentFrame)
|
||||||
{
|
{
|
||||||
if (g_SWVideoConfig.bDumpTextures && swstats.thisFrame.numDrawnObjects >= g_SWVideoConfig.drawStart && swstats.thisFrame.numDrawnObjects < g_SWVideoConfig.drawEnd)
|
if (g_SWVideoConfig.bDumpTextures && swstats.thisFrame.numDrawnObjects >= g_SWVideoConfig.drawStart && swstats.thisFrame.numDrawnObjects < g_SWVideoConfig.drawEnd)
|
||||||
DumpActiveTextures();
|
DumpActiveTextures();
|
||||||
|
|
||||||
if (g_SWVideoConfig.bHwRasterizer)
|
if (g_SWVideoConfig.bHwRasterizer)
|
||||||
{
|
{
|
||||||
HwRasterizer::BeginTriangles();
|
HwRasterizer::BeginTriangles();
|
||||||
drawingHwTriangles = true;
|
drawingHwTriangles = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnObjectEnd()
|
void OnObjectEnd()
|
||||||
{
|
{
|
||||||
if (!g_bSkipCurrentFrame)
|
if (!g_bSkipCurrentFrame)
|
||||||
{
|
{
|
||||||
if (g_SWVideoConfig.bDumpObjects && swstats.thisFrame.numDrawnObjects >= g_SWVideoConfig.drawStart && swstats.thisFrame.numDrawnObjects < g_SWVideoConfig.drawEnd)
|
if (g_SWVideoConfig.bDumpObjects && swstats.thisFrame.numDrawnObjects >= g_SWVideoConfig.drawStart && swstats.thisFrame.numDrawnObjects < g_SWVideoConfig.drawEnd)
|
||||||
DumpEfb(StringFromFormat("%sobject%i.tga",
|
DumpEfb(StringFromFormat("%sobject%i.tga",
|
||||||
File::GetUserPath(D_DUMPFRAMES_IDX).c_str(),
|
File::GetUserPath(D_DUMPFRAMES_IDX).c_str(),
|
||||||
swstats.thisFrame.numDrawnObjects).c_str());
|
swstats.thisFrame.numDrawnObjects).c_str());
|
||||||
|
|
||||||
if (g_SWVideoConfig.bHwRasterizer || drawingHwTriangles)
|
if (g_SWVideoConfig.bHwRasterizer || drawingHwTriangles)
|
||||||
{
|
{
|
||||||
HwRasterizer::EndTriangles();
|
HwRasterizer::EndTriangles();
|
||||||
drawingHwTriangles = false;
|
drawingHwTriangles = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < NumObjectBuffers; i++)
|
for (int i = 0; i < NumObjectBuffers; i++)
|
||||||
{
|
{
|
||||||
if (DrawnToBuffer[i])
|
if (DrawnToBuffer[i])
|
||||||
{
|
{
|
||||||
DrawnToBuffer[i] = false;
|
DrawnToBuffer[i] = false;
|
||||||
(void)SaveTGA(StringFromFormat("%sobject%i_%s(%i).tga",
|
(void)SaveTGA(StringFromFormat("%sobject%i_%s(%i).tga",
|
||||||
File::GetUserPath(D_DUMPFRAMES_IDX).c_str(),
|
File::GetUserPath(D_DUMPFRAMES_IDX).c_str(),
|
||||||
swstats.thisFrame.numDrawnObjects, ObjectBufferName[i], i - BufferBase[i]).c_str(),
|
swstats.thisFrame.numDrawnObjects, ObjectBufferName[i], i - BufferBase[i]).c_str(),
|
||||||
EFB_WIDTH, EFB_HEIGHT, ObjectBuffer[i]);
|
EFB_WIDTH, EFB_HEIGHT, ObjectBuffer[i]);
|
||||||
memset(ObjectBuffer[i], 0, sizeof(ObjectBuffer[i]));
|
memset(ObjectBuffer[i], 0, sizeof(ObjectBuffer[i]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
swstats.thisFrame.numDrawnObjects++;
|
swstats.thisFrame.numDrawnObjects++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnFrameEnd()
|
void OnFrameEnd()
|
||||||
{
|
{
|
||||||
if (!g_bSkipCurrentFrame)
|
if (!g_bSkipCurrentFrame)
|
||||||
{
|
{
|
||||||
if (g_SWVideoConfig.bDumpFrames)
|
if (g_SWVideoConfig.bDumpFrames)
|
||||||
{
|
{
|
||||||
DumpEfb(StringFromFormat("%sframe%i_color.tga",
|
DumpEfb(StringFromFormat("%sframe%i_color.tga",
|
||||||
File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), swstats.frameCount).c_str());
|
File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), swstats.frameCount).c_str());
|
||||||
DumpDepth(StringFromFormat("%sframe%i_depth.tga",
|
DumpDepth(StringFromFormat("%sframe%i_depth.tga",
|
||||||
File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), swstats.frameCount).c_str());
|
File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), swstats.frameCount).c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official Git repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#ifndef _DEBUGUTIL_H
|
#ifndef _DEBUGUTIL_H
|
||||||
|
@ -20,18 +20,18 @@
|
||||||
|
|
||||||
namespace DebugUtil
|
namespace DebugUtil
|
||||||
{
|
{
|
||||||
void Init();
|
void Init();
|
||||||
|
|
||||||
void GetTextureBGRA(u8 *dst, u32 texmap, s32 mip, u32 width, u32 height);
|
void GetTextureBGRA(u8 *dst, u32 texmap, s32 mip, u32 width, u32 height);
|
||||||
|
|
||||||
void DumpActiveTextures();
|
void DumpActiveTextures();
|
||||||
|
|
||||||
void OnObjectBegin();
|
void OnObjectBegin();
|
||||||
void OnObjectEnd();
|
void OnObjectEnd();
|
||||||
|
|
||||||
void OnFrameEnd();
|
void OnFrameEnd();
|
||||||
|
|
||||||
void DrawObjectBuffer(s16 x, s16 y, u8 *color, int bufferBase, int subBuffer, const char *name);
|
void DrawObjectBuffer(s16 x, s16 y, u8 *color, int bufferBase, int subBuffer, const char *name);
|
||||||
|
|
||||||
void DrawTempBuffer(u8 *color, int buffer);
|
void DrawTempBuffer(u8 *color, int buffer);
|
||||||
void CopyTempBuffer(s16 x, s16 y, int bufferBase, int subBuffer, const char *name);
|
void CopyTempBuffer(s16 x, s16 y, int bufferBase, int subBuffer, const char *name);
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official Git repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#include "BPMemLoader.h"
|
#include "BPMemLoader.h"
|
||||||
|
@ -30,84 +30,83 @@
|
||||||
|
|
||||||
namespace EfbCopy
|
namespace EfbCopy
|
||||||
{
|
{
|
||||||
void CopyToXfb()
|
void CopyToXfb()
|
||||||
{
|
{
|
||||||
GLInterface->Update(); // just updates the render window position and the backbuffer size
|
GLInterface->Update(); // just updates the render window position and the backbuffer size
|
||||||
|
|
||||||
if (!g_SWVideoConfig.bHwRasterizer)
|
if (!g_SWVideoConfig.bHwRasterizer)
|
||||||
{
|
{
|
||||||
// copy to open gl for rendering
|
// copy to open gl for rendering
|
||||||
EfbInterface::UpdateColorTexture();
|
EfbInterface::UpdateColorTexture();
|
||||||
SWRenderer::DrawTexture(EfbInterface::efbColorTexture, EFB_WIDTH, EFB_HEIGHT);
|
SWRenderer::DrawTexture(EfbInterface::efbColorTexture, EFB_WIDTH, EFB_HEIGHT);
|
||||||
}
|
}
|
||||||
|
|
||||||
SWRenderer::SwapBuffer();
|
SWRenderer::SwapBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
void CopyToRam()
|
||||||
|
{
|
||||||
void CopyToRam()
|
if (!g_SWVideoConfig.bHwRasterizer)
|
||||||
{
|
|
||||||
if (!g_SWVideoConfig.bHwRasterizer)
|
|
||||||
{
|
{
|
||||||
u8 *dest_ptr = Memory::GetPointer(bpmem.copyTexDest << 5);
|
u8 *dest_ptr = Memory::GetPointer(bpmem.copyTexDest << 5);
|
||||||
|
|
||||||
TextureEncoder::Encode(dest_ptr);
|
TextureEncoder::Encode(dest_ptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClearEfb()
|
void ClearEfb()
|
||||||
{
|
{
|
||||||
u32 clearColor = (bpmem.clearcolorAR & 0xff) << 24 | bpmem.clearcolorGB << 8 | (bpmem.clearcolorAR & 0xff00) >> 8;
|
u32 clearColor = (bpmem.clearcolorAR & 0xff) << 24 | bpmem.clearcolorGB << 8 | (bpmem.clearcolorAR & 0xff00) >> 8;
|
||||||
|
|
||||||
int left = bpmem.copyTexSrcXY.x;
|
int left = bpmem.copyTexSrcXY.x;
|
||||||
int top = bpmem.copyTexSrcXY.y;
|
int top = bpmem.copyTexSrcXY.y;
|
||||||
int right = left + bpmem.copyTexSrcWH.x;
|
int right = left + bpmem.copyTexSrcWH.x;
|
||||||
int bottom = top + bpmem.copyTexSrcWH.y;
|
int bottom = top + bpmem.copyTexSrcWH.y;
|
||||||
|
|
||||||
for (u16 y = top; y <= bottom; y++)
|
for (u16 y = top; y <= bottom; y++)
|
||||||
{
|
{
|
||||||
for (u16 x = left; x <= right; x++)
|
for (u16 x = left; x <= right; x++)
|
||||||
{
|
{
|
||||||
EfbInterface::SetColor(x, y, (u8*)(&clearColor));
|
EfbInterface::SetColor(x, y, (u8*)(&clearColor));
|
||||||
EfbInterface::SetDepth(x, y, bpmem.clearZValue);
|
EfbInterface::SetDepth(x, y, bpmem.clearZValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CopyEfb()
|
void CopyEfb()
|
||||||
{
|
{
|
||||||
if (bpmem.triggerEFBCopy.copy_to_xfb)
|
if (bpmem.triggerEFBCopy.copy_to_xfb)
|
||||||
DebugUtil::OnFrameEnd();
|
DebugUtil::OnFrameEnd();
|
||||||
|
|
||||||
if (!g_bSkipCurrentFrame)
|
if (!g_bSkipCurrentFrame)
|
||||||
{
|
{
|
||||||
if (bpmem.triggerEFBCopy.copy_to_xfb)
|
if (bpmem.triggerEFBCopy.copy_to_xfb)
|
||||||
{
|
{
|
||||||
CopyToXfb();
|
CopyToXfb();
|
||||||
Core::Callback_VideoCopiedToXFB(true);
|
Core::Callback_VideoCopiedToXFB(true);
|
||||||
|
|
||||||
swstats.frameCount++;
|
swstats.frameCount++;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
CopyToRam();
|
CopyToRam();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bpmem.triggerEFBCopy.clear)
|
if (bpmem.triggerEFBCopy.clear)
|
||||||
{
|
{
|
||||||
if (g_SWVideoConfig.bHwRasterizer)
|
if (g_SWVideoConfig.bHwRasterizer)
|
||||||
HwRasterizer::Clear();
|
HwRasterizer::Clear();
|
||||||
else
|
else
|
||||||
ClearEfb();
|
ClearEfb();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (bpmem.triggerEFBCopy.copy_to_xfb)
|
if (bpmem.triggerEFBCopy.copy_to_xfb)
|
||||||
{
|
{
|
||||||
// no frame rendered but tell that a frame has finished for frame skip counter
|
// no frame rendered but tell that a frame has finished for frame skip counter
|
||||||
Core::Callback_VideoCopiedToXFB(false);
|
Core::Callback_VideoCopiedToXFB(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official Git repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#ifndef _EFB_COPY_H_
|
#ifndef _EFB_COPY_H_
|
||||||
|
@ -23,9 +23,9 @@
|
||||||
|
|
||||||
namespace EfbCopy
|
namespace EfbCopy
|
||||||
{
|
{
|
||||||
// Copy the EFB to RAM as a texture format or XFB
|
// Copy the EFB to RAM as a texture format or XFB
|
||||||
// Clear the EFB if needed
|
// Clear the EFB if needed
|
||||||
void CopyEfb();
|
void CopyEfb();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official Git repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
|
@ -29,17 +29,17 @@ u8 efb[EFB_WIDTH*EFB_HEIGHT*6];
|
||||||
namespace EfbInterface
|
namespace EfbInterface
|
||||||
{
|
{
|
||||||
|
|
||||||
u8 efbColorTexture[EFB_WIDTH*EFB_HEIGHT*4];
|
u8 efbColorTexture[EFB_WIDTH*EFB_HEIGHT*4];
|
||||||
|
|
||||||
inline u32 GetColorOffset(u16 x, u16 y)
|
inline u32 GetColorOffset(u16 x, u16 y)
|
||||||
{
|
{
|
||||||
return (x + y * EFB_WIDTH) * 3;
|
return (x + y * EFB_WIDTH) * 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline u32 GetDepthOffset(u16 x, u16 y)
|
inline u32 GetDepthOffset(u16 x, u16 y)
|
||||||
{
|
{
|
||||||
return (x + y * EFB_WIDTH) * 3 + DEPTH_BUFFER_START;
|
return (x + y * EFB_WIDTH) * 3 + DEPTH_BUFFER_START;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DoState(PointerWrap &p)
|
void DoState(PointerWrap &p)
|
||||||
{
|
{
|
||||||
|
@ -47,45 +47,45 @@ namespace EfbInterface
|
||||||
p.DoArray(efbColorTexture, EFB_WIDTH*EFB_HEIGHT*4);
|
p.DoArray(efbColorTexture, EFB_WIDTH*EFB_HEIGHT*4);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetPixelAlphaOnly(u32 offset, u8 a)
|
void SetPixelAlphaOnly(u32 offset, u8 a)
|
||||||
{
|
{
|
||||||
switch (bpmem.zcontrol.pixel_format)
|
switch (bpmem.zcontrol.pixel_format)
|
||||||
{
|
{
|
||||||
case PIXELFMT_RGB8_Z24:
|
case PIXELFMT_RGB8_Z24:
|
||||||
case PIXELFMT_Z24:
|
case PIXELFMT_Z24:
|
||||||
case PIXELFMT_RGB565_Z16:
|
case PIXELFMT_RGB565_Z16:
|
||||||
// do nothing
|
// do nothing
|
||||||
break;
|
break;
|
||||||
case PIXELFMT_RGBA6_Z24:
|
case PIXELFMT_RGBA6_Z24:
|
||||||
{
|
{
|
||||||
u32 a32 = a;
|
u32 a32 = a;
|
||||||
u32 *dst = (u32*)&efb[offset];
|
u32 *dst = (u32*)&efb[offset];
|
||||||
u32 val = *dst & 0xffffffc0;
|
u32 val = *dst & 0xffffffc0;
|
||||||
val |= (a32 >> 2) & 0x0000003f;
|
val |= (a32 >> 2) & 0x0000003f;
|
||||||
*dst = val;
|
*dst = val;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ERROR_LOG(VIDEO, "Unsupported pixel format: %i", bpmem.zcontrol.pixel_format);
|
ERROR_LOG(VIDEO, "Unsupported pixel format: %i", bpmem.zcontrol.pixel_format);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetPixelColorOnly(u32 offset, u8 *rgb)
|
void SetPixelColorOnly(u32 offset, u8 *rgb)
|
||||||
{
|
{
|
||||||
switch (bpmem.zcontrol.pixel_format)
|
switch (bpmem.zcontrol.pixel_format)
|
||||||
{
|
{
|
||||||
case PIXELFMT_RGB8_Z24:
|
case PIXELFMT_RGB8_Z24:
|
||||||
case PIXELFMT_Z24:
|
case PIXELFMT_Z24:
|
||||||
{
|
{
|
||||||
u32 src = *(u32*)rgb;
|
u32 src = *(u32*)rgb;
|
||||||
u32 *dst = (u32*)&efb[offset];
|
u32 *dst = (u32*)&efb[offset];
|
||||||
u32 val = *dst & 0xff000000;
|
u32 val = *dst & 0xff000000;
|
||||||
val |= src >> 8;
|
val |= src >> 8;
|
||||||
*dst = val;
|
*dst = val;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case PIXELFMT_RGBA6_Z24:
|
case PIXELFMT_RGBA6_Z24:
|
||||||
{
|
{
|
||||||
u32 src = *(u32*)rgb;
|
u32 src = *(u32*)rgb;
|
||||||
u32 *dst = (u32*)&efb[offset];
|
u32 *dst = (u32*)&efb[offset];
|
||||||
u32 val = *dst & 0xff00003f;
|
u32 val = *dst & 0xff00003f;
|
||||||
|
@ -93,39 +93,39 @@ namespace EfbInterface
|
||||||
val |= (src >> 6) & 0x0003f000; // green
|
val |= (src >> 6) & 0x0003f000; // green
|
||||||
val |= (src >> 8) & 0x00fc0000; // red
|
val |= (src >> 8) & 0x00fc0000; // red
|
||||||
*dst = val;
|
*dst = val;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case PIXELFMT_RGB565_Z16:
|
case PIXELFMT_RGB565_Z16:
|
||||||
{
|
{
|
||||||
INFO_LOG(VIDEO, "PIXELFMT_RGB565_Z16 is not supported correctly yet");
|
INFO_LOG(VIDEO, "PIXELFMT_RGB565_Z16 is not supported correctly yet");
|
||||||
u32 src = *(u32*)rgb;
|
u32 src = *(u32*)rgb;
|
||||||
u32 *dst = (u32*)&efb[offset];
|
u32 *dst = (u32*)&efb[offset];
|
||||||
u32 val = *dst & 0xff000000;
|
u32 val = *dst & 0xff000000;
|
||||||
val |= src >> 8;
|
val |= src >> 8;
|
||||||
*dst = val;
|
*dst = val;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ERROR_LOG(VIDEO, "Unsupported pixel format: %i", bpmem.zcontrol.pixel_format);
|
ERROR_LOG(VIDEO, "Unsupported pixel format: %i", bpmem.zcontrol.pixel_format);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetPixelAlphaColor(u32 offset, u8 *color)
|
void SetPixelAlphaColor(u32 offset, u8 *color)
|
||||||
{
|
{
|
||||||
switch (bpmem.zcontrol.pixel_format)
|
switch (bpmem.zcontrol.pixel_format)
|
||||||
{
|
{
|
||||||
case PIXELFMT_RGB8_Z24:
|
case PIXELFMT_RGB8_Z24:
|
||||||
case PIXELFMT_Z24:
|
case PIXELFMT_Z24:
|
||||||
{
|
{
|
||||||
u32 src = *(u32*)color;
|
u32 src = *(u32*)color;
|
||||||
u32 *dst = (u32*)&efb[offset];
|
u32 *dst = (u32*)&efb[offset];
|
||||||
u32 val = *dst & 0xff000000;
|
u32 val = *dst & 0xff000000;
|
||||||
val |= src >> 8;
|
val |= src >> 8;
|
||||||
*dst = val;
|
*dst = val;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case PIXELFMT_RGBA6_Z24:
|
case PIXELFMT_RGBA6_Z24:
|
||||||
{
|
{
|
||||||
u32 src = *(u32*)color;
|
u32 src = *(u32*)color;
|
||||||
u32 *dst = (u32*)&efb[offset];
|
u32 *dst = (u32*)&efb[offset];
|
||||||
u32 val = *dst & 0xff000000;
|
u32 val = *dst & 0xff000000;
|
||||||
|
@ -134,332 +134,341 @@ namespace EfbInterface
|
||||||
val |= (src >> 6) & 0x0003f000; // green
|
val |= (src >> 6) & 0x0003f000; // green
|
||||||
val |= (src >> 8) & 0x00fc0000; // red
|
val |= (src >> 8) & 0x00fc0000; // red
|
||||||
*dst = val;
|
*dst = val;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case PIXELFMT_RGB565_Z16:
|
case PIXELFMT_RGB565_Z16:
|
||||||
{
|
{
|
||||||
INFO_LOG(VIDEO, "PIXELFMT_RGB565_Z16 is not supported correctly yet");
|
INFO_LOG(VIDEO, "PIXELFMT_RGB565_Z16 is not supported correctly yet");
|
||||||
u32 src = *(u32*)color;
|
u32 src = *(u32*)color;
|
||||||
u32 *dst = (u32*)&efb[offset];
|
u32 *dst = (u32*)&efb[offset];
|
||||||
u32 val = *dst & 0xff000000;
|
u32 val = *dst & 0xff000000;
|
||||||
val |= src >> 8;
|
val |= src >> 8;
|
||||||
*dst = val;
|
*dst = val;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ERROR_LOG(VIDEO, "Unsupported pixel format: %i", bpmem.zcontrol.pixel_format);
|
ERROR_LOG(VIDEO, "Unsupported pixel format: %i", bpmem.zcontrol.pixel_format);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GetPixelColor(u32 offset, u8 *color)
|
void GetPixelColor(u32 offset, u8 *color)
|
||||||
{
|
{
|
||||||
switch (bpmem.zcontrol.pixel_format)
|
switch (bpmem.zcontrol.pixel_format)
|
||||||
{
|
{
|
||||||
case PIXELFMT_RGB8_Z24:
|
case PIXELFMT_RGB8_Z24:
|
||||||
case PIXELFMT_Z24:
|
case PIXELFMT_Z24:
|
||||||
{
|
{
|
||||||
u32 src = *(u32*)&efb[offset];
|
u32 src = *(u32*)&efb[offset];
|
||||||
u32 *dst = (u32*)color;
|
u32 *dst = (u32*)color;
|
||||||
u32 val = 0xff | ((src & 0x00ffffff) << 8);
|
u32 val = 0xff | ((src & 0x00ffffff) << 8);
|
||||||
*dst = val;
|
*dst = val;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case PIXELFMT_RGBA6_Z24:
|
case PIXELFMT_RGBA6_Z24:
|
||||||
{
|
{
|
||||||
u32 src = *(u32*)&efb[offset];
|
u32 src = *(u32*)&efb[offset];
|
||||||
color[ALP_C] = Convert6To8(src & 0x3f);
|
color[ALP_C] = Convert6To8(src & 0x3f);
|
||||||
color[BLU_C] = Convert6To8((src >> 6) & 0x3f);
|
color[BLU_C] = Convert6To8((src >> 6) & 0x3f);
|
||||||
color[GRN_C] = Convert6To8((src >> 12) & 0x3f);
|
color[GRN_C] = Convert6To8((src >> 12) & 0x3f);
|
||||||
color[RED_C] = Convert6To8((src >> 18) & 0x3f);
|
color[RED_C] = Convert6To8((src >> 18) & 0x3f);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case PIXELFMT_RGB565_Z16:
|
case PIXELFMT_RGB565_Z16:
|
||||||
{
|
{
|
||||||
INFO_LOG(VIDEO, "PIXELFMT_RGB565_Z16 is not supported correctly yet");
|
INFO_LOG(VIDEO, "PIXELFMT_RGB565_Z16 is not supported correctly yet");
|
||||||
u32 src = *(u32*)&efb[offset];
|
u32 src = *(u32*)&efb[offset];
|
||||||
u32 *dst = (u32*)color;
|
u32 *dst = (u32*)color;
|
||||||
u32 val = 0xff | ((src & 0x00ffffff) << 8);
|
u32 val = 0xff | ((src & 0x00ffffff) << 8);
|
||||||
*dst = val;
|
*dst = val;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ERROR_LOG(VIDEO, "Unsupported pixel format: %i", bpmem.zcontrol.pixel_format);
|
ERROR_LOG(VIDEO, "Unsupported pixel format: %i", bpmem.zcontrol.pixel_format);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetPixelDepth(u32 offset, u32 depth)
|
void SetPixelDepth(u32 offset, u32 depth)
|
||||||
{
|
{
|
||||||
switch (bpmem.zcontrol.pixel_format)
|
switch (bpmem.zcontrol.pixel_format)
|
||||||
{
|
{
|
||||||
case PIXELFMT_RGB8_Z24:
|
case PIXELFMT_RGB8_Z24:
|
||||||
case PIXELFMT_RGBA6_Z24:
|
case PIXELFMT_RGBA6_Z24:
|
||||||
case PIXELFMT_Z24:
|
case PIXELFMT_Z24:
|
||||||
{
|
{
|
||||||
u32 *dst = (u32*)&efb[offset];
|
u32 *dst = (u32*)&efb[offset];
|
||||||
u32 val = *dst & 0xff000000;
|
u32 val = *dst & 0xff000000;
|
||||||
val |= depth & 0x00ffffff;
|
val |= depth & 0x00ffffff;
|
||||||
*dst = val;
|
*dst = val;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case PIXELFMT_RGB565_Z16:
|
case PIXELFMT_RGB565_Z16:
|
||||||
{
|
{
|
||||||
INFO_LOG(VIDEO, "PIXELFMT_RGB565_Z16 is not supported correctly yet");
|
INFO_LOG(VIDEO, "PIXELFMT_RGB565_Z16 is not supported correctly yet");
|
||||||
u32 *dst = (u32*)&efb[offset];
|
u32 *dst = (u32*)&efb[offset];
|
||||||
u32 val = *dst & 0xff000000;
|
u32 val = *dst & 0xff000000;
|
||||||
val |= depth & 0x00ffffff;
|
val |= depth & 0x00ffffff;
|
||||||
*dst = val;
|
*dst = val;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ERROR_LOG(VIDEO, "Unsupported pixel format: %i", bpmem.zcontrol.pixel_format);
|
ERROR_LOG(VIDEO, "Unsupported pixel format: %i", bpmem.zcontrol.pixel_format);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 GetPixelDepth(u32 offset)
|
u32 GetPixelDepth(u32 offset)
|
||||||
{
|
{
|
||||||
u32 depth = 0;
|
u32 depth = 0;
|
||||||
|
|
||||||
switch (bpmem.zcontrol.pixel_format)
|
switch (bpmem.zcontrol.pixel_format)
|
||||||
{
|
{
|
||||||
case PIXELFMT_RGB8_Z24:
|
case PIXELFMT_RGB8_Z24:
|
||||||
case PIXELFMT_RGBA6_Z24:
|
case PIXELFMT_RGBA6_Z24:
|
||||||
case PIXELFMT_Z24:
|
case PIXELFMT_Z24:
|
||||||
{
|
{
|
||||||
depth = (*(u32*)&efb[offset]) & 0x00ffffff;
|
depth = (*(u32*)&efb[offset]) & 0x00ffffff;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case PIXELFMT_RGB565_Z16:
|
case PIXELFMT_RGB565_Z16:
|
||||||
{
|
{
|
||||||
INFO_LOG(VIDEO, "PIXELFMT_RGB565_Z16 is not supported correctly yet");
|
INFO_LOG(VIDEO, "PIXELFMT_RGB565_Z16 is not supported correctly yet");
|
||||||
depth = (*(u32*)&efb[offset]) & 0x00ffffff;
|
depth = (*(u32*)&efb[offset]) & 0x00ffffff;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ERROR_LOG(VIDEO, "Unsupported pixel format: %i", bpmem.zcontrol.pixel_format);
|
ERROR_LOG(VIDEO, "Unsupported pixel format: %i", bpmem.zcontrol.pixel_format);
|
||||||
}
|
}
|
||||||
|
|
||||||
return depth;
|
return depth;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 GetSourceFactor(u8 *srcClr, u8 *dstClr, int mode)
|
u32 GetSourceFactor(u8 *srcClr, u8 *dstClr, int mode)
|
||||||
{
|
{
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case 0: // zero
|
case 0: // zero
|
||||||
return 0;
|
return 0;
|
||||||
case 1: // one
|
case 1: // one
|
||||||
return 0xffffffff;
|
return 0xffffffff;
|
||||||
case 2: // dstclr
|
case 2: // dstclr
|
||||||
return *(u32*)dstClr;
|
return *(u32*)dstClr;
|
||||||
case 3: // invdstclr
|
case 3: // invdstclr
|
||||||
return 0xffffffff - *(u32*)dstClr;
|
return 0xffffffff - *(u32*)dstClr;
|
||||||
case 4: // srcalpha
|
case 4: // srcalpha
|
||||||
{
|
{
|
||||||
u8 alpha = srcClr[ALP_C];
|
u8 alpha = srcClr[ALP_C];
|
||||||
u32 factor = alpha << 24 | alpha << 16 | alpha << 8 | alpha;
|
u32 factor = alpha << 24 | alpha << 16 | alpha << 8 | alpha;
|
||||||
return factor;
|
return factor;
|
||||||
}
|
}
|
||||||
case 5: // invsrcalpha
|
case 5: // invsrcalpha
|
||||||
{
|
{
|
||||||
u8 alpha = 0xff - srcClr[ALP_C];
|
u8 alpha = 0xff - srcClr[ALP_C];
|
||||||
u32 factor = alpha << 24 | alpha << 16 | alpha << 8 | alpha;
|
u32 factor = alpha << 24 | alpha << 16 | alpha << 8 | alpha;
|
||||||
return factor;
|
return factor;
|
||||||
}
|
}
|
||||||
case 6: // dstalpha
|
case 6: // dstalpha
|
||||||
{
|
{
|
||||||
u8 alpha = dstClr[ALP_C];
|
u8 alpha = dstClr[ALP_C];
|
||||||
u32 factor = alpha << 24 | alpha << 16 | alpha << 8 | alpha;
|
u32 factor = alpha << 24 | alpha << 16 | alpha << 8 | alpha;
|
||||||
return factor;
|
return factor;
|
||||||
}
|
}
|
||||||
case 7: // invdstalpha
|
case 7: // invdstalpha
|
||||||
{
|
{
|
||||||
u8 alpha = 0xff - dstClr[ALP_C];
|
u8 alpha = 0xff - dstClr[ALP_C];
|
||||||
u32 factor = alpha << 24 | alpha << 16 | alpha << 8 | alpha;
|
u32 factor = alpha << 24 | alpha << 16 | alpha << 8 | alpha;
|
||||||
return factor;
|
return factor;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 GetDestinationFactor(u8 *srcClr, u8 *dstClr, int mode)
|
u32 GetDestinationFactor(u8 *srcClr, u8 *dstClr, int mode)
|
||||||
{
|
{
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case 0: // zero
|
case 0: // zero
|
||||||
return 0;
|
return 0;
|
||||||
case 1: // one
|
case 1: // one
|
||||||
return 0xffffffff;
|
return 0xffffffff;
|
||||||
case 2: // srcclr
|
case 2: // srcclr
|
||||||
return *(u32*)srcClr;
|
return *(u32*)srcClr;
|
||||||
case 3: // invsrcclr
|
case 3: // invsrcclr
|
||||||
return 0xffffffff - *(u32*)srcClr;
|
return 0xffffffff - *(u32*)srcClr;
|
||||||
case 4: // srcalpha
|
case 4: // srcalpha
|
||||||
{
|
{
|
||||||
u8 alpha = srcClr[ALP_C];
|
u8 alpha = srcClr[ALP_C];
|
||||||
u32 factor = alpha << 24 | alpha << 16 | alpha << 8 | alpha;
|
u32 factor = alpha << 24 | alpha << 16 | alpha << 8 | alpha;
|
||||||
return factor;
|
return factor;
|
||||||
}
|
}
|
||||||
case 5: // invsrcalpha
|
case 5: // invsrcalpha
|
||||||
{
|
{
|
||||||
u8 alpha = 0xff - srcClr[ALP_C];
|
u8 alpha = 0xff - srcClr[ALP_C];
|
||||||
u32 factor = alpha << 24 | alpha << 16 | alpha << 8 | alpha;
|
u32 factor = alpha << 24 | alpha << 16 | alpha << 8 | alpha;
|
||||||
return factor;
|
return factor;
|
||||||
}
|
}
|
||||||
case 6: // dstalpha
|
case 6: // dstalpha
|
||||||
{
|
{
|
||||||
u8 alpha = dstClr[ALP_C] & 0xff;
|
u8 alpha = dstClr[ALP_C] & 0xff;
|
||||||
u32 factor = alpha << 24 | alpha << 16 | alpha << 8 | alpha;
|
u32 factor = alpha << 24 | alpha << 16 | alpha << 8 | alpha;
|
||||||
return factor;
|
return factor;
|
||||||
}
|
}
|
||||||
case 7: // invdstalpha
|
case 7: // invdstalpha
|
||||||
{
|
{
|
||||||
u8 alpha = 0xff - dstClr[ALP_C];
|
u8 alpha = 0xff - dstClr[ALP_C];
|
||||||
u32 factor = alpha << 24 | alpha << 16 | alpha << 8 | alpha;
|
u32 factor = alpha << 24 | alpha << 16 | alpha << 8 | alpha;
|
||||||
return factor;
|
return factor;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlendColor(u8 *srcClr, u8 *dstClr)
|
void BlendColor(u8 *srcClr, u8 *dstClr)
|
||||||
{
|
{
|
||||||
u32 srcFactor = GetSourceFactor(srcClr, dstClr, bpmem.blendmode.srcfactor);
|
u32 srcFactor = GetSourceFactor(srcClr, dstClr, bpmem.blendmode.srcfactor);
|
||||||
u32 dstFactor = GetDestinationFactor(srcClr, dstClr, bpmem.blendmode.dstfactor);
|
u32 dstFactor = GetDestinationFactor(srcClr, dstClr, bpmem.blendmode.dstfactor);
|
||||||
|
|
||||||
for (int i = 0; i < 4; i++)
|
for (int i = 0; i < 4; i++)
|
||||||
{
|
{
|
||||||
// add MSB of factors to make their range 0 -> 256
|
// add MSB of factors to make their range 0 -> 256
|
||||||
u32 sf = (srcFactor & 0xff);
|
u32 sf = (srcFactor & 0xff);
|
||||||
sf += sf >> 7;
|
sf += sf >> 7;
|
||||||
|
|
||||||
u32 df = (dstFactor & 0xff);
|
|
||||||
df += df >> 7;
|
|
||||||
|
|
||||||
u32 color = (srcClr[i] * sf + dstClr[i] * df) >> 8;
|
u32 df = (dstFactor & 0xff);
|
||||||
dstClr[i] = (color>255)?255:color;
|
df += df >> 7;
|
||||||
|
|
||||||
dstFactor >>= 8;
|
u32 color = (srcClr[i] * sf + dstClr[i] * df) >> 8;
|
||||||
srcFactor >>= 8;
|
dstClr[i] = (color>255)?255:color;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void LogicBlend(u32 srcClr, u32 &dstClr, int op)
|
dstFactor >>= 8;
|
||||||
{
|
srcFactor >>= 8;
|
||||||
switch (op) {
|
}
|
||||||
case 0: // clear
|
}
|
||||||
dstClr = 0;
|
|
||||||
break;
|
void LogicBlend(u32 srcClr, u32 &dstClr, int op)
|
||||||
case 1: // and
|
{
|
||||||
dstClr = srcClr & dstClr;
|
switch (op)
|
||||||
break;
|
{
|
||||||
case 2: // revand
|
case 0: // clear
|
||||||
dstClr = srcClr & (~dstClr);
|
dstClr = 0;
|
||||||
break;
|
break;
|
||||||
case 3: // copy
|
case 1: // and
|
||||||
dstClr = srcClr;
|
dstClr = srcClr & dstClr;
|
||||||
break;
|
break;
|
||||||
case 4: // invand
|
case 2: // revand
|
||||||
dstClr = (~srcClr) & dstClr;
|
dstClr = srcClr & (~dstClr);
|
||||||
break;
|
break;
|
||||||
case 5: // noop
|
case 3: // copy
|
||||||
|
dstClr = srcClr;
|
||||||
|
break;
|
||||||
|
case 4: // invand
|
||||||
|
dstClr = (~srcClr) & dstClr;
|
||||||
|
break;
|
||||||
|
case 5: // noop
|
||||||
// Do nothing
|
// Do nothing
|
||||||
break;
|
break;
|
||||||
case 6: // xor
|
case 6: // xor
|
||||||
dstClr = srcClr ^ dstClr;
|
dstClr = srcClr ^ dstClr;
|
||||||
break;
|
break;
|
||||||
case 7: // or
|
case 7: // or
|
||||||
dstClr = srcClr | dstClr;
|
dstClr = srcClr | dstClr;
|
||||||
break;
|
break;
|
||||||
case 8: // nor
|
case 8: // nor
|
||||||
dstClr = ~(srcClr | dstClr);
|
dstClr = ~(srcClr | dstClr);
|
||||||
break;
|
break;
|
||||||
case 9: // equiv
|
case 9: // equiv
|
||||||
dstClr = ~(srcClr ^ dstClr);
|
dstClr = ~(srcClr ^ dstClr);
|
||||||
break;
|
break;
|
||||||
case 10: // inv
|
case 10: // inv
|
||||||
dstClr = ~dstClr;
|
dstClr = ~dstClr;
|
||||||
break;
|
break;
|
||||||
case 11: // revor
|
case 11: // revor
|
||||||
dstClr = srcClr | (~dstClr);
|
dstClr = srcClr | (~dstClr);
|
||||||
break;
|
break;
|
||||||
case 12: // invcopy
|
case 12: // invcopy
|
||||||
dstClr = ~srcClr;
|
dstClr = ~srcClr;
|
||||||
break;
|
break;
|
||||||
case 13: // invor
|
case 13: // invor
|
||||||
dstClr = (~srcClr) | dstClr;
|
dstClr = (~srcClr) | dstClr;
|
||||||
break;
|
break;
|
||||||
case 14: // nand
|
case 14: // nand
|
||||||
dstClr = ~(srcClr & dstClr);
|
dstClr = ~(srcClr & dstClr);
|
||||||
break;
|
break;
|
||||||
case 15: // set
|
case 15: // set
|
||||||
dstClr = 0xffffffff;
|
dstClr = 0xffffffff;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SubtractBlend(u8 *srcClr, u8 *dstClr)
|
void SubtractBlend(u8 *srcClr, u8 *dstClr)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < 4; i++)
|
for (int i = 0; i < 4; i++)
|
||||||
{
|
{
|
||||||
int c = (int)dstClr[i] - (int)srcClr[i];
|
int c = (int)dstClr[i] - (int)srcClr[i];
|
||||||
dstClr[i] = (c < 0)?0:c;
|
dstClr[i] = (c < 0)?0:c;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlendTev(u16 x, u16 y, u8 *color)
|
void BlendTev(u16 x, u16 y, u8 *color)
|
||||||
{
|
{
|
||||||
u32 dstClr;
|
u32 dstClr;
|
||||||
u32 offset = GetColorOffset(x, y);
|
u32 offset = GetColorOffset(x, y);
|
||||||
|
|
||||||
u8 *dstClrPtr = (u8*)&dstClr;
|
u8 *dstClrPtr = (u8*)&dstClr;
|
||||||
|
|
||||||
GetPixelColor(offset, dstClrPtr);
|
GetPixelColor(offset, dstClrPtr);
|
||||||
|
|
||||||
if (bpmem.blendmode.blendenable)
|
if (bpmem.blendmode.blendenable)
|
||||||
{
|
{
|
||||||
if (bpmem.blendmode.subtract)
|
if (bpmem.blendmode.subtract)
|
||||||
SubtractBlend(color, dstClrPtr);
|
SubtractBlend(color, dstClrPtr);
|
||||||
else
|
else
|
||||||
BlendColor(color, dstClrPtr);
|
BlendColor(color, dstClrPtr);
|
||||||
}
|
}
|
||||||
else if (bpmem.blendmode.logicopenable)
|
else if (bpmem.blendmode.logicopenable)
|
||||||
LogicBlend(*((u32*)color), dstClr, bpmem.blendmode.logicmode);
|
{
|
||||||
else
|
LogicBlend(*((u32*)color), dstClr, bpmem.blendmode.logicmode);
|
||||||
dstClrPtr = color;
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dstClrPtr = color;
|
||||||
|
}
|
||||||
|
|
||||||
if (bpmem.dstalpha.enable)
|
if (bpmem.dstalpha.enable)
|
||||||
dstClrPtr[ALP_C] = bpmem.dstalpha.alpha;
|
dstClrPtr[ALP_C] = bpmem.dstalpha.alpha;
|
||||||
|
|
||||||
if (bpmem.blendmode.colorupdate)
|
if (bpmem.blendmode.colorupdate)
|
||||||
{
|
{
|
||||||
if (bpmem.blendmode.alphaupdate)
|
if (bpmem.blendmode.alphaupdate)
|
||||||
SetPixelAlphaColor(offset, dstClrPtr);
|
SetPixelAlphaColor(offset, dstClrPtr);
|
||||||
else
|
else
|
||||||
SetPixelColorOnly(offset, dstClrPtr);
|
SetPixelColorOnly(offset, dstClrPtr);
|
||||||
}
|
}
|
||||||
else if (bpmem.blendmode.alphaupdate)
|
else if (bpmem.blendmode.alphaupdate)
|
||||||
SetPixelAlphaOnly(offset, dstClrPtr[ALP_C]);
|
{
|
||||||
|
SetPixelAlphaOnly(offset, dstClrPtr[ALP_C]);
|
||||||
|
}
|
||||||
|
|
||||||
// branchless bounding box update
|
// branchless bounding box update
|
||||||
SWPixelEngine::pereg.boxLeft = SWPixelEngine::pereg.boxLeft>x?x:SWPixelEngine::pereg.boxLeft;
|
SWPixelEngine::pereg.boxLeft = SWPixelEngine::pereg.boxLeft>x?x:SWPixelEngine::pereg.boxLeft;
|
||||||
SWPixelEngine::pereg.boxRight = SWPixelEngine::pereg.boxRight<x?x:SWPixelEngine::pereg.boxRight;
|
SWPixelEngine::pereg.boxRight = SWPixelEngine::pereg.boxRight<x?x:SWPixelEngine::pereg.boxRight;
|
||||||
SWPixelEngine::pereg.boxTop = SWPixelEngine::pereg.boxTop>y?y:SWPixelEngine::pereg.boxTop;
|
SWPixelEngine::pereg.boxTop = SWPixelEngine::pereg.boxTop>y?y:SWPixelEngine::pereg.boxTop;
|
||||||
SWPixelEngine::pereg.boxBottom = SWPixelEngine::pereg.boxBottom<y?y:SWPixelEngine::pereg.boxBottom;
|
SWPixelEngine::pereg.boxBottom = SWPixelEngine::pereg.boxBottom<y?y:SWPixelEngine::pereg.boxBottom;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetColor(u16 x, u16 y, u8 *color)
|
void SetColor(u16 x, u16 y, u8 *color)
|
||||||
{
|
{
|
||||||
u32 offset = GetColorOffset(x, y);
|
u32 offset = GetColorOffset(x, y);
|
||||||
if (bpmem.blendmode.colorupdate)
|
if (bpmem.blendmode.colorupdate)
|
||||||
{
|
{
|
||||||
if (bpmem.blendmode.alphaupdate)
|
if (bpmem.blendmode.alphaupdate)
|
||||||
SetPixelAlphaColor(offset, color);
|
SetPixelAlphaColor(offset, color);
|
||||||
else
|
else
|
||||||
SetPixelColorOnly(offset, color);
|
SetPixelColorOnly(offset, color);
|
||||||
}
|
}
|
||||||
else if (bpmem.blendmode.alphaupdate)
|
else if (bpmem.blendmode.alphaupdate)
|
||||||
SetPixelAlphaOnly(offset, color[ALP_C]);
|
{
|
||||||
}
|
SetPixelAlphaOnly(offset, color[ALP_C]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void SetDepth(u16 x, u16 y, u32 depth)
|
void SetDepth(u16 x, u16 y, u32 depth)
|
||||||
{
|
{
|
||||||
|
@ -467,87 +476,87 @@ namespace EfbInterface
|
||||||
SetPixelDepth(GetDepthOffset(x, y), depth);
|
SetPixelDepth(GetDepthOffset(x, y), depth);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GetColor(u16 x, u16 y, u8 *color)
|
void GetColor(u16 x, u16 y, u8 *color)
|
||||||
{
|
{
|
||||||
u32 offset = GetColorOffset(x, y);
|
u32 offset = GetColorOffset(x, y);
|
||||||
GetPixelColor(offset, color);
|
GetPixelColor(offset, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 GetDepth(u16 x, u16 y)
|
u32 GetDepth(u16 x, u16 y)
|
||||||
{
|
{
|
||||||
u32 offset = GetDepthOffset(x, y);
|
u32 offset = GetDepthOffset(x, y);
|
||||||
return GetPixelDepth(offset);
|
return GetPixelDepth(offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 *GetPixelPointer(u16 x, u16 y, bool depth)
|
u8 *GetPixelPointer(u16 x, u16 y, bool depth)
|
||||||
{
|
{
|
||||||
if (depth)
|
if (depth)
|
||||||
return &efb[GetDepthOffset(x, y)];
|
return &efb[GetDepthOffset(x, y)];
|
||||||
return &efb[GetColorOffset(x, y)];
|
return &efb[GetColorOffset(x, y)];
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdateColorTexture()
|
void UpdateColorTexture()
|
||||||
{
|
{
|
||||||
u32 color;
|
u32 color;
|
||||||
u8* colorPtr = (u8*)&color;
|
u8* colorPtr = (u8*)&color;
|
||||||
u32* texturePtr = (u32*)efbColorTexture;
|
u32* texturePtr = (u32*)efbColorTexture;
|
||||||
u32 textureAddress = 0;
|
u32 textureAddress = 0;
|
||||||
u32 efbOffset = 0;
|
u32 efbOffset = 0;
|
||||||
|
|
||||||
for (u16 y = 0; y < EFB_HEIGHT; y++)
|
for (u16 y = 0; y < EFB_HEIGHT; y++)
|
||||||
{
|
{
|
||||||
for (u16 x = 0; x < EFB_WIDTH; x++)
|
for (u16 x = 0; x < EFB_WIDTH; x++)
|
||||||
{
|
{
|
||||||
GetPixelColor(efbOffset, colorPtr);
|
GetPixelColor(efbOffset, colorPtr);
|
||||||
efbOffset += 3;
|
efbOffset += 3;
|
||||||
texturePtr[textureAddress++] = Common::swap32(color); // ABGR->RGBA
|
texturePtr[textureAddress++] = Common::swap32(color); // ABGR->RGBA
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ZCompare(u16 x, u16 y, u32 z)
|
bool ZCompare(u16 x, u16 y, u32 z)
|
||||||
{
|
{
|
||||||
u32 offset = GetDepthOffset(x, y);
|
u32 offset = GetDepthOffset(x, y);
|
||||||
u32 depth = GetPixelDepth(offset);
|
u32 depth = GetPixelDepth(offset);
|
||||||
|
|
||||||
bool pass;
|
bool pass;
|
||||||
|
|
||||||
switch (bpmem.zmode.func)
|
switch (bpmem.zmode.func)
|
||||||
{
|
{
|
||||||
case COMPARE_NEVER:
|
case COMPARE_NEVER:
|
||||||
pass = false;
|
pass = false;
|
||||||
break;
|
break;
|
||||||
case COMPARE_LESS:
|
case COMPARE_LESS:
|
||||||
pass = z < depth;
|
pass = z < depth;
|
||||||
break;
|
break;
|
||||||
case COMPARE_EQUAL:
|
case COMPARE_EQUAL:
|
||||||
pass = z == depth;
|
pass = z == depth;
|
||||||
break;
|
break;
|
||||||
case COMPARE_LEQUAL:
|
case COMPARE_LEQUAL:
|
||||||
pass = z <= depth;
|
pass = z <= depth;
|
||||||
break;
|
break;
|
||||||
case COMPARE_GREATER:
|
case COMPARE_GREATER:
|
||||||
pass = z > depth;
|
pass = z > depth;
|
||||||
break;
|
break;
|
||||||
case COMPARE_NEQUAL:
|
case COMPARE_NEQUAL:
|
||||||
pass = z != depth;
|
pass = z != depth;
|
||||||
break;
|
break;
|
||||||
case COMPARE_GEQUAL:
|
case COMPARE_GEQUAL:
|
||||||
pass = z >= depth;
|
pass = z >= depth;
|
||||||
break;
|
break;
|
||||||
case COMPARE_ALWAYS:
|
case COMPARE_ALWAYS:
|
||||||
pass = true;
|
pass = true;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
pass = false;
|
pass = false;
|
||||||
ERROR_LOG(VIDEO, "Bad Z compare mode %i", bpmem.zmode.func);
|
ERROR_LOG(VIDEO, "Bad Z compare mode %i", bpmem.zmode.func);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pass && bpmem.zmode.updateenable)
|
if (pass && bpmem.zmode.updateenable)
|
||||||
{
|
{
|
||||||
SetPixelDepth(offset, z);
|
SetPixelDepth(offset, z);
|
||||||
}
|
}
|
||||||
|
|
||||||
return pass;
|
return pass;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official Git repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#ifndef _EFB_INTERFACE_H_
|
#ifndef _EFB_INTERFACE_H_
|
||||||
|
@ -22,32 +22,32 @@
|
||||||
|
|
||||||
namespace EfbInterface
|
namespace EfbInterface
|
||||||
{
|
{
|
||||||
const int DEPTH_BUFFER_START = EFB_WIDTH * EFB_HEIGHT * 3;
|
const int DEPTH_BUFFER_START = EFB_WIDTH * EFB_HEIGHT * 3;
|
||||||
|
|
||||||
enum { ALP_C, BLU_C, GRN_C, RED_C };
|
enum { ALP_C, BLU_C, GRN_C, RED_C };
|
||||||
|
|
||||||
// color order is ABGR in order to emulate RGBA on little-endian hardware
|
// color order is ABGR in order to emulate RGBA on little-endian hardware
|
||||||
|
|
||||||
// does full blending of an incoming pixel
|
// does full blending of an incoming pixel
|
||||||
void BlendTev(u16 x, u16 y, u8 *color);
|
void BlendTev(u16 x, u16 y, u8 *color);
|
||||||
|
|
||||||
// compare z at location x,y
|
// compare z at location x,y
|
||||||
// writes it if it passes
|
// writes it if it passes
|
||||||
// returns result of compare.
|
// returns result of compare.
|
||||||
bool ZCompare(u16 x, u16 y, u32 z);
|
bool ZCompare(u16 x, u16 y, u32 z);
|
||||||
|
|
||||||
// sets the color and alpha
|
// sets the color and alpha
|
||||||
void SetColor(u16 x, u16 y, u8 *color);
|
void SetColor(u16 x, u16 y, u8 *color);
|
||||||
void SetDepth(u16 x, u16 y, u32 depth);
|
void SetDepth(u16 x, u16 y, u32 depth);
|
||||||
|
|
||||||
void GetColor(u16 x, u16 y, u8 *color);
|
void GetColor(u16 x, u16 y, u8 *color);
|
||||||
u32 GetDepth(u16 x, u16 y);
|
u32 GetDepth(u16 x, u16 y);
|
||||||
|
|
||||||
u8* GetPixelPointer(u16 x, u16 y, bool depth);
|
u8* GetPixelPointer(u16 x, u16 y, bool depth);
|
||||||
|
|
||||||
void UpdateColorTexture();
|
void UpdateColorTexture();
|
||||||
extern u8 efbColorTexture[EFB_WIDTH*EFB_HEIGHT*4]; // RGBA format
|
extern u8 efbColorTexture[EFB_WIDTH*EFB_HEIGHT*4]; // RGBA format
|
||||||
void DoState(PointerWrap &p);
|
void DoState(PointerWrap &p);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official Git repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
|
@ -369,10 +369,10 @@ namespace HwRasterizer
|
||||||
|
|
||||||
// extra checks cause textures to be reloaded much more
|
// extra checks cause textures to be reloaded much more
|
||||||
if (texUnit.texImage0[0].hex != texImage0.hex ||
|
if (texUnit.texImage0[0].hex != texImage0.hex ||
|
||||||
//texUnit.texImage1[0].hex != texImage1.hex ||
|
// texUnit.texImage1[0].hex != texImage1.hex ||
|
||||||
//texUnit.texImage2[0].hex != texImage2.hex ||
|
// texUnit.texImage2[0].hex != texImage2.hex ||
|
||||||
texUnit.texImage3[0].hex != texImage3.hex ||
|
texUnit.texImage3[0].hex != texImage3.hex ||
|
||||||
texUnit.texTlut[0].hex != texTlut.hex)
|
texUnit.texTlut[0].hex != texTlut.hex)
|
||||||
{
|
{
|
||||||
Destroy();
|
Destroy();
|
||||||
Create();
|
Create();
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official Git repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#ifndef _HW_RASTERIZER_H
|
#ifndef _HW_RASTERIZER_H
|
||||||
|
@ -27,37 +27,37 @@ struct OutputVertexData;
|
||||||
|
|
||||||
namespace HwRasterizer
|
namespace HwRasterizer
|
||||||
{
|
{
|
||||||
void Init();
|
void Init();
|
||||||
void Shutdown();
|
void Shutdown();
|
||||||
|
|
||||||
void Prepare();
|
void Prepare();
|
||||||
|
|
||||||
void BeginTriangles();
|
void BeginTriangles();
|
||||||
void EndTriangles();
|
void EndTriangles();
|
||||||
|
|
||||||
void DrawTriangleFrontFace(OutputVertexData *v0, OutputVertexData *v1, OutputVertexData *v2);
|
void DrawTriangleFrontFace(OutputVertexData *v0, OutputVertexData *v1, OutputVertexData *v2);
|
||||||
|
|
||||||
void Clear();
|
void Clear();
|
||||||
|
|
||||||
struct TexCacheEntry
|
struct TexCacheEntry
|
||||||
{
|
{
|
||||||
TexImage0 texImage0;
|
TexImage0 texImage0;
|
||||||
TexImage1 texImage1;
|
TexImage1 texImage1;
|
||||||
TexImage2 texImage2;
|
TexImage2 texImage2;
|
||||||
TexImage3 texImage3;
|
TexImage3 texImage3;
|
||||||
TexTLUT texTlut;
|
TexTLUT texTlut;
|
||||||
|
|
||||||
GLuint texture;
|
GLuint texture;
|
||||||
|
|
||||||
TexCacheEntry();
|
TexCacheEntry();
|
||||||
|
|
||||||
void Create();
|
void Create();
|
||||||
void Destroy();
|
void Destroy();
|
||||||
void Update();
|
void Update();
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::map<u32, TexCacheEntry> TextureCache;
|
typedef std::map<u32, TexCacheEntry> TextureCache;
|
||||||
static TextureCache textures;
|
static TextureCache textures;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official Git repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#ifndef _NATIVEVERTEXFORMAT_H
|
#ifndef _NATIVEVERTEXFORMAT_H
|
||||||
|
@ -39,13 +39,13 @@ struct Vec4
|
||||||
|
|
||||||
struct InputVertexData
|
struct InputVertexData
|
||||||
{
|
{
|
||||||
u8 posMtx;
|
u8 posMtx;
|
||||||
u8 texMtx[8];
|
u8 texMtx[8];
|
||||||
|
|
||||||
Vec3 position;
|
Vec3 position;
|
||||||
Vec3 normal[3];
|
Vec3 normal[3];
|
||||||
u8 color[2][4];
|
u8 color[2][4];
|
||||||
float texCoords[8][2];
|
float texCoords[8][2];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct OutputVertexData
|
struct OutputVertexData
|
||||||
|
@ -54,45 +54,45 @@ struct OutputVertexData
|
||||||
enum { RED_C, GRN_C, BLU_C, ALP_C };
|
enum { RED_C, GRN_C, BLU_C, ALP_C };
|
||||||
|
|
||||||
Vec3 mvPosition;
|
Vec3 mvPosition;
|
||||||
Vec4 projectedPosition;
|
Vec4 projectedPosition;
|
||||||
Vec3 screenPosition;
|
Vec3 screenPosition;
|
||||||
Vec3 normal[3];
|
Vec3 normal[3];
|
||||||
u8 color[2][4];
|
u8 color[2][4];
|
||||||
Vec3 texCoords[8];
|
Vec3 texCoords[8];
|
||||||
|
|
||||||
void Lerp(float t, OutputVertexData *a, OutputVertexData *b)
|
void Lerp(float t, OutputVertexData *a, OutputVertexData *b)
|
||||||
{
|
{
|
||||||
#define LINTERP(T, OUT, IN) (OUT) + ((IN - OUT) * T)
|
#define LINTERP(T, OUT, IN) (OUT) + ((IN - OUT) * T)
|
||||||
|
|
||||||
#define LINTERP_INT(T, OUT, IN) (OUT) + (((IN - OUT) * T) >> 8)
|
#define LINTERP_INT(T, OUT, IN) (OUT) + (((IN - OUT) * T) >> 8)
|
||||||
|
|
||||||
mvPosition = LINTERP(t, a->mvPosition, b->mvPosition);
|
mvPosition = LINTERP(t, a->mvPosition, b->mvPosition);
|
||||||
|
|
||||||
projectedPosition.x = LINTERP(t, a->projectedPosition.x, b->projectedPosition.x);
|
projectedPosition.x = LINTERP(t, a->projectedPosition.x, b->projectedPosition.x);
|
||||||
projectedPosition.y = LINTERP(t, a->projectedPosition.y, b->projectedPosition.y);
|
projectedPosition.y = LINTERP(t, a->projectedPosition.y, b->projectedPosition.y);
|
||||||
projectedPosition.z = LINTERP(t, a->projectedPosition.z, b->projectedPosition.z);
|
projectedPosition.z = LINTERP(t, a->projectedPosition.z, b->projectedPosition.z);
|
||||||
projectedPosition.w = LINTERP(t, a->projectedPosition.w, b->projectedPosition.w);
|
projectedPosition.w = LINTERP(t, a->projectedPosition.w, b->projectedPosition.w);
|
||||||
|
|
||||||
for (int i = 0; i < 3; ++i)
|
for (int i = 0; i < 3; ++i)
|
||||||
{
|
{
|
||||||
normal[i] = LINTERP(t, a->normal[i], b->normal[i]);
|
normal[i] = LINTERP(t, a->normal[i], b->normal[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
u16 t_int = (u16)(t * 256);
|
u16 t_int = (u16)(t * 256);
|
||||||
for (int i = 0; i < 4; ++i)
|
for (int i = 0; i < 4; ++i)
|
||||||
{
|
{
|
||||||
color[0][i] = LINTERP_INT(t_int, a->color[0][i], b->color[0][i]);
|
color[0][i] = LINTERP_INT(t_int, a->color[0][i], b->color[0][i]);
|
||||||
color[1][i] = LINTERP_INT(t_int, a->color[1][i], b->color[1][i]);
|
color[1][i] = LINTERP_INT(t_int, a->color[1][i], b->color[1][i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < 8; ++i)
|
for (int i = 0; i < 8; ++i)
|
||||||
{
|
{
|
||||||
texCoords[i] = LINTERP(t, a->texCoords[i], b->texCoords[i]);
|
texCoords[i] = LINTERP(t, a->texCoords[i], b->texCoords[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef LINTERP
|
#undef LINTERP
|
||||||
#undef LINTERP_INT
|
#undef LINTERP_INT
|
||||||
}
|
}
|
||||||
void DoState(PointerWrap &p)
|
void DoState(PointerWrap &p)
|
||||||
{
|
{
|
||||||
mvPosition.DoState(p);
|
mvPosition.DoState(p);
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official Git repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
|
@ -61,258 +61,258 @@ void DoState(PointerWrap &p)
|
||||||
|
|
||||||
void DecodePrimitiveStream(u32 iBufferSize)
|
void DecodePrimitiveStream(u32 iBufferSize)
|
||||||
{
|
{
|
||||||
u32 vertexSize = vertexLoader.GetVertexSize();
|
u32 vertexSize = vertexLoader.GetVertexSize();
|
||||||
|
|
||||||
bool skipPrimitives = g_bSkipCurrentFrame ||
|
bool skipPrimitives = g_bSkipCurrentFrame ||
|
||||||
swstats.thisFrame.numDrawnObjects < g_SWVideoConfig.drawStart ||
|
swstats.thisFrame.numDrawnObjects < g_SWVideoConfig.drawStart ||
|
||||||
swstats.thisFrame.numDrawnObjects >= g_SWVideoConfig.drawEnd;
|
swstats.thisFrame.numDrawnObjects >= g_SWVideoConfig.drawEnd;
|
||||||
|
|
||||||
if (skipPrimitives)
|
if (skipPrimitives)
|
||||||
{
|
{
|
||||||
while (streamSize > 0 && iBufferSize >= vertexSize)
|
while (streamSize > 0 && iBufferSize >= vertexSize)
|
||||||
{
|
{
|
||||||
g_pVideoData += vertexSize;
|
g_pVideoData += vertexSize;
|
||||||
iBufferSize -= vertexSize;
|
iBufferSize -= vertexSize;
|
||||||
streamSize--;
|
streamSize--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
while (streamSize > 0 && iBufferSize >= vertexSize)
|
while (streamSize > 0 && iBufferSize >= vertexSize)
|
||||||
{
|
{
|
||||||
vertexLoader.LoadVertex();
|
vertexLoader.LoadVertex();
|
||||||
iBufferSize -= vertexSize;
|
iBufferSize -= vertexSize;
|
||||||
streamSize--;
|
streamSize--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (streamSize == 0)
|
if (streamSize == 0)
|
||||||
{
|
{
|
||||||
// return to normal command processing
|
// return to normal command processing
|
||||||
ResetDecoding();
|
ResetDecoding();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReadXFData(u32 iBufferSize)
|
void ReadXFData(u32 iBufferSize)
|
||||||
{
|
{
|
||||||
_assert_msg_(VIDEO, iBufferSize >= (u32)(streamSize * 4), "Underflow during standard opcode decoding");
|
_assert_msg_(VIDEO, iBufferSize >= (u32)(streamSize * 4), "Underflow during standard opcode decoding");
|
||||||
|
|
||||||
u32 pData[16];
|
u32 pData[16];
|
||||||
for (int i = 0; i < streamSize; i++)
|
for (int i = 0; i < streamSize; i++)
|
||||||
pData[i] = DataReadU32();
|
pData[i] = DataReadU32();
|
||||||
SWLoadXFReg(streamSize, streamAddress, pData);
|
SWLoadXFReg(streamSize, streamAddress, pData);
|
||||||
|
|
||||||
// return to normal command processing
|
// return to normal command processing
|
||||||
ResetDecoding();
|
ResetDecoding();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExecuteDisplayList(u32 addr, u32 count)
|
void ExecuteDisplayList(u32 addr, u32 count)
|
||||||
{
|
{
|
||||||
u8 *videoDataSave = g_pVideoData;
|
u8 *videoDataSave = g_pVideoData;
|
||||||
|
|
||||||
u8 *dlStart = Memory::GetPointer(addr);
|
u8 *dlStart = Memory::GetPointer(addr);
|
||||||
|
|
||||||
g_pVideoData = dlStart;
|
g_pVideoData = dlStart;
|
||||||
|
|
||||||
while (OpcodeDecoder::CommandRunnable(count))
|
while (OpcodeDecoder::CommandRunnable(count))
|
||||||
{
|
{
|
||||||
OpcodeDecoder::Run(count);
|
OpcodeDecoder::Run(count);
|
||||||
|
|
||||||
// if data was read by the opcode decoder then the video data pointer changed
|
// if data was read by the opcode decoder then the video data pointer changed
|
||||||
u32 readCount = (u32)(g_pVideoData - dlStart);
|
u32 readCount = (u32)(g_pVideoData - dlStart);
|
||||||
dlStart = g_pVideoData;
|
dlStart = g_pVideoData;
|
||||||
|
|
||||||
_assert_msg_(VIDEO, count >= readCount, "Display list underrun");
|
_assert_msg_(VIDEO, count >= readCount, "Display list underrun");
|
||||||
|
|
||||||
count -= readCount;
|
count -= readCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_pVideoData = videoDataSave;
|
g_pVideoData = videoDataSave;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DecodeStandard(u32 bufferSize)
|
void DecodeStandard(u32 bufferSize)
|
||||||
{
|
{
|
||||||
_assert_msg_(VIDEO, CommandRunnable(bufferSize), "Underflow during standard opcode decoding");
|
_assert_msg_(VIDEO, CommandRunnable(bufferSize), "Underflow during standard opcode decoding");
|
||||||
|
|
||||||
int Cmd = DataReadU8();
|
int Cmd = DataReadU8();
|
||||||
|
|
||||||
if (Cmd == GX_NOP)
|
if (Cmd == GX_NOP)
|
||||||
return;
|
return;
|
||||||
// Causes a SIGBUS error on Android
|
// Causes a SIGBUS error on Android
|
||||||
// XXX: Investigate
|
// XXX: Investigate
|
||||||
#ifndef ANDROID
|
#ifndef ANDROID
|
||||||
// check if switching in or out of an object
|
// check if switching in or out of an object
|
||||||
// only used for debuggging
|
// only used for debuggging
|
||||||
if (inObjectStream && (Cmd & 0x87) != lastPrimCmd)
|
if (inObjectStream && (Cmd & 0x87) != lastPrimCmd)
|
||||||
{
|
{
|
||||||
inObjectStream = false;
|
inObjectStream = false;
|
||||||
DebugUtil::OnObjectEnd();
|
DebugUtil::OnObjectEnd();
|
||||||
}
|
}
|
||||||
if (Cmd & 0x80 && !inObjectStream)
|
if (Cmd & 0x80 && !inObjectStream)
|
||||||
{
|
{
|
||||||
inObjectStream = true;
|
inObjectStream = true;
|
||||||
lastPrimCmd = Cmd & 0x87;
|
lastPrimCmd = Cmd & 0x87;
|
||||||
DebugUtil::OnObjectBegin();
|
DebugUtil::OnObjectBegin();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
switch(Cmd)
|
switch(Cmd)
|
||||||
{
|
{
|
||||||
case GX_NOP:
|
case GX_NOP:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GX_LOAD_CP_REG: //0x08
|
case GX_LOAD_CP_REG: //0x08
|
||||||
{
|
{
|
||||||
u32 SubCmd = DataReadU8();
|
u32 SubCmd = DataReadU8();
|
||||||
u32 Value = DataReadU32();
|
u32 Value = DataReadU32();
|
||||||
SWLoadCPReg(SubCmd, Value);
|
SWLoadCPReg(SubCmd, Value);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GX_LOAD_XF_REG:
|
case GX_LOAD_XF_REG:
|
||||||
{
|
{
|
||||||
u32 Cmd2 = DataReadU32();
|
u32 Cmd2 = DataReadU32();
|
||||||
streamSize = ((Cmd2 >> 16) & 15) + 1;
|
streamSize = ((Cmd2 >> 16) & 15) + 1;
|
||||||
streamAddress = Cmd2 & 0xFFFF;
|
streamAddress = Cmd2 & 0xFFFF;
|
||||||
currentFunction = ReadXFData;
|
currentFunction = ReadXFData;
|
||||||
minCommandSize = streamSize * 4;
|
minCommandSize = streamSize * 4;
|
||||||
readOpcode = false;
|
readOpcode = false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GX_LOAD_INDX_A: //used for position matrices
|
case GX_LOAD_INDX_A: //used for position matrices
|
||||||
SWLoadIndexedXF(DataReadU32(), 0xC);
|
SWLoadIndexedXF(DataReadU32(), 0xC);
|
||||||
break;
|
break;
|
||||||
case GX_LOAD_INDX_B: //used for normal matrices
|
case GX_LOAD_INDX_B: //used for normal matrices
|
||||||
SWLoadIndexedXF(DataReadU32(), 0xD);
|
SWLoadIndexedXF(DataReadU32(), 0xD);
|
||||||
break;
|
break;
|
||||||
case GX_LOAD_INDX_C: //used for postmatrices
|
case GX_LOAD_INDX_C: //used for postmatrices
|
||||||
SWLoadIndexedXF(DataReadU32(), 0xE);
|
SWLoadIndexedXF(DataReadU32(), 0xE);
|
||||||
break;
|
break;
|
||||||
case GX_LOAD_INDX_D: //used for lights
|
case GX_LOAD_INDX_D: //used for lights
|
||||||
SWLoadIndexedXF(DataReadU32(), 0xF);
|
SWLoadIndexedXF(DataReadU32(), 0xF);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GX_CMD_CALL_DL:
|
case GX_CMD_CALL_DL:
|
||||||
{
|
{
|
||||||
u32 dwAddr = DataReadU32();
|
u32 dwAddr = DataReadU32();
|
||||||
u32 dwCount = DataReadU32();
|
u32 dwCount = DataReadU32();
|
||||||
ExecuteDisplayList(dwAddr, dwCount);
|
ExecuteDisplayList(dwAddr, dwCount);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x44:
|
case 0x44:
|
||||||
// zelda 4 swords calls it and checks the metrics registers after that
|
// zelda 4 swords calls it and checks the metrics registers after that
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GX_CMD_INVL_VC:// Invalidate (vertex cache?)
|
case GX_CMD_INVL_VC:// Invalidate (vertex cache?)
|
||||||
DEBUG_LOG(VIDEO, "Invalidate (vertex cache?)");
|
DEBUG_LOG(VIDEO, "Invalidate (vertex cache?)");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GX_LOAD_BP_REG: //0x61
|
case GX_LOAD_BP_REG: //0x61
|
||||||
{
|
{
|
||||||
u32 cmd = DataReadU32();
|
u32 cmd = DataReadU32();
|
||||||
SWLoadBPReg(cmd);
|
SWLoadBPReg(cmd);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// draw primitives
|
// draw primitives
|
||||||
default:
|
default:
|
||||||
if (Cmd & 0x80)
|
if (Cmd & 0x80)
|
||||||
{
|
{
|
||||||
u8 vatIndex = Cmd & GX_VAT_MASK;
|
u8 vatIndex = Cmd & GX_VAT_MASK;
|
||||||
u8 primitiveType = (Cmd & GX_PRIMITIVE_MASK) >> GX_PRIMITIVE_SHIFT;
|
u8 primitiveType = (Cmd & GX_PRIMITIVE_MASK) >> GX_PRIMITIVE_SHIFT;
|
||||||
vertexLoader.SetFormat(vatIndex, primitiveType);
|
vertexLoader.SetFormat(vatIndex, primitiveType);
|
||||||
|
|
||||||
// switch to primitive processing
|
|
||||||
streamSize = DataReadU16();
|
|
||||||
currentFunction = DecodePrimitiveStream;
|
|
||||||
minCommandSize = vertexLoader.GetVertexSize();
|
|
||||||
readOpcode = false;
|
|
||||||
|
|
||||||
INCSTAT(swstats.thisFrame.numPrimatives);
|
// switch to primitive processing
|
||||||
DEBUG_LOG(VIDEO, "Draw begin");
|
streamSize = DataReadU16();
|
||||||
}
|
currentFunction = DecodePrimitiveStream;
|
||||||
else
|
minCommandSize = vertexLoader.GetVertexSize();
|
||||||
{
|
readOpcode = false;
|
||||||
PanicAlert("GFX: Unknown Opcode (0x%x).\n", Cmd);
|
|
||||||
break;
|
INCSTAT(swstats.thisFrame.numPrimatives);
|
||||||
}
|
DEBUG_LOG(VIDEO, "Draw begin");
|
||||||
break;
|
}
|
||||||
}
|
else
|
||||||
|
{
|
||||||
|
PanicAlert("GFX: Unknown Opcode (0x%x).\n", Cmd);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Init()
|
void Init()
|
||||||
{
|
{
|
||||||
inObjectStream = false;
|
inObjectStream = false;
|
||||||
lastPrimCmd = 0;
|
lastPrimCmd = 0;
|
||||||
ResetDecoding();
|
ResetDecoding();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResetDecoding()
|
void ResetDecoding()
|
||||||
{
|
{
|
||||||
currentFunction = DecodeStandard;
|
currentFunction = DecodeStandard;
|
||||||
minCommandSize = 1;
|
minCommandSize = 1;
|
||||||
readOpcode = true;
|
readOpcode = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CommandRunnable(u32 iBufferSize)
|
bool CommandRunnable(u32 iBufferSize)
|
||||||
{
|
{
|
||||||
if (iBufferSize < minCommandSize)
|
if (iBufferSize < minCommandSize)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (readOpcode)
|
if (readOpcode)
|
||||||
{
|
{
|
||||||
u8 Cmd = DataPeek8(0);
|
u8 Cmd = DataPeek8(0);
|
||||||
u32 minSize = 1;
|
u32 minSize = 1;
|
||||||
|
|
||||||
switch(Cmd)
|
switch(Cmd)
|
||||||
{
|
{
|
||||||
case GX_LOAD_CP_REG: //0x08
|
case GX_LOAD_CP_REG: //0x08
|
||||||
minSize = 6;
|
minSize = 6;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GX_LOAD_XF_REG:
|
case GX_LOAD_XF_REG:
|
||||||
minSize = 5;
|
minSize = 5;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GX_LOAD_INDX_A: //used for position matrices
|
case GX_LOAD_INDX_A: //used for position matrices
|
||||||
minSize = 5;
|
minSize = 5;
|
||||||
break;
|
break;
|
||||||
case GX_LOAD_INDX_B: //used for normal matrices
|
case GX_LOAD_INDX_B: //used for normal matrices
|
||||||
minSize = 5;
|
minSize = 5;
|
||||||
break;
|
break;
|
||||||
case GX_LOAD_INDX_C: //used for postmatrices
|
case GX_LOAD_INDX_C: //used for postmatrices
|
||||||
minSize = 5;
|
minSize = 5;
|
||||||
break;
|
break;
|
||||||
case GX_LOAD_INDX_D: //used for lights
|
case GX_LOAD_INDX_D: //used for lights
|
||||||
minSize = 5;
|
minSize = 5;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GX_CMD_CALL_DL:
|
case GX_CMD_CALL_DL:
|
||||||
minSize = 9;
|
minSize = 9;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GX_LOAD_BP_REG: //0x61
|
case GX_LOAD_BP_REG: //0x61
|
||||||
minSize = 5;
|
minSize = 5;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// draw primitives
|
// draw primitives
|
||||||
default:
|
default:
|
||||||
if (Cmd & 0x80)
|
if (Cmd & 0x80)
|
||||||
minSize = 3;
|
minSize = 3;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (iBufferSize >= minSize);
|
return (iBufferSize >= minSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Run(u32 iBufferSize)
|
void Run(u32 iBufferSize)
|
||||||
{
|
{
|
||||||
currentFunction(iBufferSize);
|
currentFunction(iBufferSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official Git repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
|
|
||||||
|
@ -25,39 +25,39 @@
|
||||||
namespace OpcodeDecoder
|
namespace OpcodeDecoder
|
||||||
{
|
{
|
||||||
|
|
||||||
#define GX_NOP 0x00
|
#define GX_NOP 0x00
|
||||||
|
|
||||||
#define GX_LOAD_BP_REG 0x61
|
#define GX_LOAD_BP_REG 0x61
|
||||||
#define GX_LOAD_CP_REG 0x08
|
#define GX_LOAD_CP_REG 0x08
|
||||||
#define GX_LOAD_XF_REG 0x10
|
#define GX_LOAD_XF_REG 0x10
|
||||||
#define GX_LOAD_INDX_A 0x20
|
#define GX_LOAD_INDX_A 0x20
|
||||||
#define GX_LOAD_INDX_B 0x28
|
#define GX_LOAD_INDX_B 0x28
|
||||||
#define GX_LOAD_INDX_C 0x30
|
#define GX_LOAD_INDX_C 0x30
|
||||||
#define GX_LOAD_INDX_D 0x38
|
#define GX_LOAD_INDX_D 0x38
|
||||||
|
|
||||||
#define GX_CMD_CALL_DL 0x40
|
#define GX_CMD_CALL_DL 0x40
|
||||||
#define GX_CMD_INVL_VC 0x48
|
#define GX_CMD_INVL_VC 0x48
|
||||||
|
|
||||||
#define GX_PRIMITIVE_MASK 0x78
|
#define GX_PRIMITIVE_MASK 0x78
|
||||||
#define GX_PRIMITIVE_SHIFT 3
|
#define GX_PRIMITIVE_SHIFT 3
|
||||||
#define GX_VAT_MASK 0x07
|
#define GX_VAT_MASK 0x07
|
||||||
|
|
||||||
//these are defined 1/8th of their real values and without their top bit
|
//these are defined 1/8th of their real values and without their top bit
|
||||||
#define GX_DRAW_QUADS 0x0 //0x80
|
#define GX_DRAW_QUADS 0x0 //0x80
|
||||||
#define GX_DRAW_TRIANGLES 0x2 //0x90
|
#define GX_DRAW_TRIANGLES 0x2 //0x90
|
||||||
#define GX_DRAW_TRIANGLE_STRIP 0x3 //0x98
|
#define GX_DRAW_TRIANGLE_STRIP 0x3 //0x98
|
||||||
#define GX_DRAW_TRIANGLE_FAN 0x4 //0xA0
|
#define GX_DRAW_TRIANGLE_FAN 0x4 //0xA0
|
||||||
#define GX_DRAW_LINES 0x5 //0xA8
|
#define GX_DRAW_LINES 0x5 //0xA8
|
||||||
#define GX_DRAW_LINE_STRIP 0x6 //0xB0
|
#define GX_DRAW_LINE_STRIP 0x6 //0xB0
|
||||||
#define GX_DRAW_POINTS 0x7 //0xB8
|
#define GX_DRAW_POINTS 0x7 //0xB8
|
||||||
|
|
||||||
void Init();
|
void Init();
|
||||||
|
|
||||||
void ResetDecoding();
|
void ResetDecoding();
|
||||||
|
|
||||||
bool CommandRunnable(u32 iBufferSize);
|
bool CommandRunnable(u32 iBufferSize);
|
||||||
|
|
||||||
void Run(u32 iBufferSize);
|
void Run(u32 iBufferSize);
|
||||||
|
|
||||||
void DoState(PointerWrap &p);
|
void DoState(PointerWrap &p);
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official Git repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#include "../../Plugin_VideoOGL/Src/GLUtil.h"
|
#include "../../Plugin_VideoOGL/Src/GLUtil.h"
|
||||||
|
@ -23,110 +23,112 @@
|
||||||
// globals
|
// globals
|
||||||
|
|
||||||
const GLubyte rasters[][13] = {
|
const GLubyte rasters[][13] = {
|
||||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||||
{0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
|
{0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
|
||||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36},
|
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36},
|
||||||
{0x00, 0x00, 0x00, 0x66, 0x66, 0xff, 0x66, 0x66, 0xff, 0x66, 0x66, 0x00, 0x00},
|
{0x00, 0x00, 0x00, 0x66, 0x66, 0xff, 0x66, 0x66, 0xff, 0x66, 0x66, 0x00, 0x00},
|
||||||
{0x00, 0x00, 0x18, 0x7e, 0xff, 0x1b, 0x1f, 0x7e, 0xf8, 0xd8, 0xff, 0x7e, 0x18},
|
{0x00, 0x00, 0x18, 0x7e, 0xff, 0x1b, 0x1f, 0x7e, 0xf8, 0xd8, 0xff, 0x7e, 0x18},
|
||||||
{0x00, 0x00, 0x0e, 0x1b, 0xdb, 0x6e, 0x30, 0x18, 0x0c, 0x76, 0xdb, 0xd8, 0x70},
|
{0x00, 0x00, 0x0e, 0x1b, 0xdb, 0x6e, 0x30, 0x18, 0x0c, 0x76, 0xdb, 0xd8, 0x70},
|
||||||
{0x00, 0x00, 0x7f, 0xc6, 0xcf, 0xd8, 0x70, 0x70, 0xd8, 0xcc, 0xcc, 0x6c, 0x38},
|
{0x00, 0x00, 0x7f, 0xc6, 0xcf, 0xd8, 0x70, 0x70, 0xd8, 0xcc, 0xcc, 0x6c, 0x38},
|
||||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x1c, 0x0c, 0x0e},
|
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x1c, 0x0c, 0x0e},
|
||||||
{0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x18, 0x0c},
|
{0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x18, 0x0c},
|
||||||
{0x00, 0x00, 0x30, 0x18, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x30},
|
{0x00, 0x00, 0x30, 0x18, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x30},
|
||||||
{0x00, 0x00, 0x00, 0x00, 0x99, 0x5a, 0x3c, 0xff, 0x3c, 0x5a, 0x99, 0x00, 0x00},
|
{0x00, 0x00, 0x00, 0x00, 0x99, 0x5a, 0x3c, 0xff, 0x3c, 0x5a, 0x99, 0x00, 0x00},
|
||||||
{0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0xff, 0xff, 0x18, 0x18, 0x18, 0x00, 0x00},
|
{0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0xff, 0xff, 0x18, 0x18, 0x18, 0x00, 0x00},
|
||||||
{0x00, 0x00, 0x30, 0x18, 0x1c, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
{0x00, 0x00, 0x30, 0x18, 0x1c, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00},
|
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||||
{0x00, 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
{0x00, 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||||
{0x00, 0x60, 0x60, 0x30, 0x30, 0x18, 0x18, 0x0c, 0x0c, 0x06, 0x06, 0x03, 0x03},
|
{0x00, 0x60, 0x60, 0x30, 0x30, 0x18, 0x18, 0x0c, 0x0c, 0x06, 0x06, 0x03, 0x03},
|
||||||
{0x00, 0x00, 0x3c, 0x66, 0xc3, 0xe3, 0xf3, 0xdb, 0xcf, 0xc7, 0xc3, 0x66, 0x3c},
|
{0x00, 0x00, 0x3c, 0x66, 0xc3, 0xe3, 0xf3, 0xdb, 0xcf, 0xc7, 0xc3, 0x66, 0x3c},
|
||||||
{0x00, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78, 0x38, 0x18},
|
{0x00, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78, 0x38, 0x18},
|
||||||
{0x00, 0x00, 0xff, 0xc0, 0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x03, 0xe7, 0x7e},
|
{0x00, 0x00, 0xff, 0xc0, 0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x03, 0xe7, 0x7e},
|
||||||
{0x00, 0x00, 0x7e, 0xe7, 0x03, 0x03, 0x07, 0x7e, 0x07, 0x03, 0x03, 0xe7, 0x7e},
|
{0x00, 0x00, 0x7e, 0xe7, 0x03, 0x03, 0x07, 0x7e, 0x07, 0x03, 0x03, 0xe7, 0x7e},
|
||||||
{0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xff, 0xcc, 0x6c, 0x3c, 0x1c, 0x0c},
|
{0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xff, 0xcc, 0x6c, 0x3c, 0x1c, 0x0c},
|
||||||
{0x00, 0x00, 0x7e, 0xe7, 0x03, 0x03, 0x07, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0, 0xff},
|
{0x00, 0x00, 0x7e, 0xe7, 0x03, 0x03, 0x07, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0, 0xff},
|
||||||
{0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xc7, 0xfe, 0xc0, 0xc0, 0xc0, 0xe7, 0x7e},
|
{0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xc7, 0xfe, 0xc0, 0xc0, 0xc0, 0xe7, 0x7e},
|
||||||
{0x00, 0x00, 0x30, 0x30, 0x30, 0x30, 0x18, 0x0c, 0x06, 0x03, 0x03, 0x03, 0xff},
|
{0x00, 0x00, 0x30, 0x30, 0x30, 0x30, 0x18, 0x0c, 0x06, 0x03, 0x03, 0x03, 0xff},
|
||||||
{0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xe7, 0x7e, 0xe7, 0xc3, 0xc3, 0xe7, 0x7e},
|
{0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xe7, 0x7e, 0xe7, 0xc3, 0xc3, 0xe7, 0x7e},
|
||||||
{0x00, 0x00, 0x7e, 0xe7, 0x03, 0x03, 0x03, 0x7f, 0xe7, 0xc3, 0xc3, 0xe7, 0x7e},
|
{0x00, 0x00, 0x7e, 0xe7, 0x03, 0x03, 0x03, 0x7f, 0xe7, 0xc3, 0xc3, 0xe7, 0x7e},
|
||||||
{0x00, 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, 0x00, 0x00},
|
{0x00, 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, 0x00, 0x00},
|
||||||
{0x00, 0x00, 0x30, 0x18, 0x1c, 0x1c, 0x00, 0x00, 0x1c, 0x1c, 0x00, 0x00, 0x00},
|
{0x00, 0x00, 0x30, 0x18, 0x1c, 0x1c, 0x00, 0x00, 0x1c, 0x1c, 0x00, 0x00, 0x00},
|
||||||
{0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06},
|
{0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06},
|
||||||
{0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00},
|
{0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00},
|
||||||
{0x00, 0x00, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x03, 0x06, 0x0c, 0x18, 0x30, 0x60},
|
{0x00, 0x00, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x03, 0x06, 0x0c, 0x18, 0x30, 0x60},
|
||||||
{0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x18, 0x0c, 0x06, 0x03, 0xc3, 0xc3, 0x7e},
|
{0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x18, 0x0c, 0x06, 0x03, 0xc3, 0xc3, 0x7e},
|
||||||
{0x00, 0x00, 0x3f, 0x60, 0xcf, 0xdb, 0xd3, 0xdd, 0xc3, 0x7e, 0x00, 0x00, 0x00},
|
{0x00, 0x00, 0x3f, 0x60, 0xcf, 0xdb, 0xd3, 0xdd, 0xc3, 0x7e, 0x00, 0x00, 0x00},
|
||||||
{0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xff, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x18},
|
{0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xff, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x18},
|
||||||
{0x00, 0x00, 0xfe, 0xc7, 0xc3, 0xc3, 0xc7, 0xfe, 0xc7, 0xc3, 0xc3, 0xc7, 0xfe},
|
{0x00, 0x00, 0xfe, 0xc7, 0xc3, 0xc3, 0xc7, 0xfe, 0xc7, 0xc3, 0xc3, 0xc7, 0xfe},
|
||||||
{0x00, 0x00, 0x7e, 0xe7, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xe7, 0x7e},
|
{0x00, 0x00, 0x7e, 0xe7, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xe7, 0x7e},
|
||||||
{0x00, 0x00, 0xfc, 0xce, 0xc7, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc7, 0xce, 0xfc},
|
{0x00, 0x00, 0xfc, 0xce, 0xc7, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc7, 0xce, 0xfc},
|
||||||
{0x00, 0x00, 0xff, 0xc0, 0xc0, 0xc0, 0xc0, 0xfc, 0xc0, 0xc0, 0xc0, 0xc0, 0xff},
|
{0x00, 0x00, 0xff, 0xc0, 0xc0, 0xc0, 0xc0, 0xfc, 0xc0, 0xc0, 0xc0, 0xc0, 0xff},
|
||||||
{0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xfc, 0xc0, 0xc0, 0xc0, 0xff},
|
{0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xfc, 0xc0, 0xc0, 0xc0, 0xff},
|
||||||
{0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xcf, 0xc0, 0xc0, 0xc0, 0xc0, 0xe7, 0x7e},
|
{0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xcf, 0xc0, 0xc0, 0xc0, 0xc0, 0xe7, 0x7e},
|
||||||
{0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xff, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3},
|
{0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xff, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3},
|
||||||
{0x00, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e},
|
{0x00, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e},
|
||||||
{0x00, 0x00, 0x7c, 0xee, 0xc6, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06},
|
{0x00, 0x00, 0x7c, 0xee, 0xc6, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06},
|
||||||
{0x00, 0x00, 0xc3, 0xc6, 0xcc, 0xd8, 0xf0, 0xe0, 0xf0, 0xd8, 0xcc, 0xc6, 0xc3},
|
{0x00, 0x00, 0xc3, 0xc6, 0xcc, 0xd8, 0xf0, 0xe0, 0xf0, 0xd8, 0xcc, 0xc6, 0xc3},
|
||||||
{0x00, 0x00, 0xff, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0},
|
{0x00, 0x00, 0xff, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0},
|
||||||
{0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xdb, 0xff, 0xff, 0xe7, 0xc3},
|
{0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xdb, 0xff, 0xff, 0xe7, 0xc3},
|
||||||
{0x00, 0x00, 0xc7, 0xc7, 0xcf, 0xcf, 0xdf, 0xdb, 0xfb, 0xf3, 0xf3, 0xe3, 0xe3},
|
{0x00, 0x00, 0xc7, 0xc7, 0xcf, 0xcf, 0xdf, 0xdb, 0xfb, 0xf3, 0xf3, 0xe3, 0xe3},
|
||||||
{0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xe7, 0x7e},
|
{0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xe7, 0x7e},
|
||||||
{0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xfe, 0xc7, 0xc3, 0xc3, 0xc7, 0xfe},
|
{0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xfe, 0xc7, 0xc3, 0xc3, 0xc7, 0xfe},
|
||||||
{0x00, 0x00, 0x3f, 0x6e, 0xdf, 0xdb, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x3c},
|
{0x00, 0x00, 0x3f, 0x6e, 0xdf, 0xdb, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x3c},
|
||||||
{0x00, 0x00, 0xc3, 0xc6, 0xcc, 0xd8, 0xf0, 0xfe, 0xc7, 0xc3, 0xc3, 0xc7, 0xfe},
|
{0x00, 0x00, 0xc3, 0xc6, 0xcc, 0xd8, 0xf0, 0xfe, 0xc7, 0xc3, 0xc3, 0xc7, 0xfe},
|
||||||
{0x00, 0x00, 0x7e, 0xe7, 0x03, 0x03, 0x07, 0x7e, 0xe0, 0xc0, 0xc0, 0xe7, 0x7e},
|
{0x00, 0x00, 0x7e, 0xe7, 0x03, 0x03, 0x07, 0x7e, 0xe0, 0xc0, 0xc0, 0xe7, 0x7e},
|
||||||
{0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff},
|
{0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff},
|
||||||
{0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3},
|
{0x00, 0x00, 0x7e, 0xe7, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3},
|
||||||
{0x00, 0x00, 0x18, 0x3c, 0x3c, 0x66, 0x66, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3},
|
{0x00, 0x00, 0x18, 0x3c, 0x3c, 0x66, 0x66, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3},
|
||||||
{0x00, 0x00, 0xc3, 0xe7, 0xff, 0xff, 0xdb, 0xdb, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3},
|
{0x00, 0x00, 0xc3, 0xe7, 0xff, 0xff, 0xdb, 0xdb, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3},
|
||||||
{0x00, 0x00, 0xc3, 0x66, 0x66, 0x3c, 0x3c, 0x18, 0x3c, 0x3c, 0x66, 0x66, 0xc3},
|
{0x00, 0x00, 0xc3, 0x66, 0x66, 0x3c, 0x3c, 0x18, 0x3c, 0x3c, 0x66, 0x66, 0xc3},
|
||||||
{0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x3c, 0x66, 0x66, 0xc3},
|
{0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x3c, 0x66, 0x66, 0xc3},
|
||||||
{0x00, 0x00, 0xff, 0xc0, 0xc0, 0x60, 0x30, 0x7e, 0x0c, 0x06, 0x03, 0x03, 0xff},
|
{0x00, 0x00, 0xff, 0xc0, 0xc0, 0x60, 0x30, 0x7e, 0x0c, 0x06, 0x03, 0x03, 0xff},
|
||||||
{0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3c},
|
{0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3c},
|
||||||
{0x00, 0x03, 0x03, 0x06, 0x06, 0x0c, 0x0c, 0x18, 0x18, 0x30, 0x30, 0x60, 0x60},
|
{0x00, 0x03, 0x03, 0x06, 0x06, 0x0c, 0x0c, 0x18, 0x18, 0x30, 0x30, 0x60, 0x60},
|
||||||
{0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c},
|
{0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c},
|
||||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18},
|
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18},
|
||||||
{0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
{0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x38, 0x30, 0x70},
|
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x38, 0x30, 0x70},
|
||||||
{0x00, 0x00, 0x7f, 0xc3, 0xc3, 0x7f, 0x03, 0xc3, 0x7e, 0x00, 0x00, 0x00, 0x00},
|
{0x00, 0x00, 0x7f, 0xc3, 0xc3, 0x7f, 0x03, 0xc3, 0x7e, 0x00, 0x00, 0x00, 0x00},
|
||||||
{0x00, 0x00, 0xfe, 0xc3, 0xc3, 0xc3, 0xc3, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0},
|
{0x00, 0x00, 0xfe, 0xc3, 0xc3, 0xc3, 0xc3, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0},
|
||||||
{0x00, 0x00, 0x7e, 0xc3, 0xc0, 0xc0, 0xc0, 0xc3, 0x7e, 0x00, 0x00, 0x00, 0x00},
|
{0x00, 0x00, 0x7e, 0xc3, 0xc0, 0xc0, 0xc0, 0xc3, 0x7e, 0x00, 0x00, 0x00, 0x00},
|
||||||
{0x00, 0x00, 0x7f, 0xc3, 0xc3, 0xc3, 0xc3, 0x7f, 0x03, 0x03, 0x03, 0x03, 0x03},
|
{0x00, 0x00, 0x7f, 0xc3, 0xc3, 0xc3, 0xc3, 0x7f, 0x03, 0x03, 0x03, 0x03, 0x03},
|
||||||
{0x00, 0x00, 0x7f, 0xc0, 0xc0, 0xfe, 0xc3, 0xc3, 0x7e, 0x00, 0x00, 0x00, 0x00},
|
{0x00, 0x00, 0x7f, 0xc0, 0xc0, 0xfe, 0xc3, 0xc3, 0x7e, 0x00, 0x00, 0x00, 0x00},
|
||||||
{0x00, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x33, 0x1e},
|
{0x00, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x33, 0x1e},
|
||||||
{0x7e, 0xc3, 0x03, 0x03, 0x7f, 0xc3, 0xc3, 0xc3, 0x7e, 0x00, 0x00, 0x00, 0x00},
|
{0x7e, 0xc3, 0x03, 0x03, 0x7f, 0xc3, 0xc3, 0xc3, 0x7e, 0x00, 0x00, 0x00, 0x00},
|
||||||
{0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0},
|
{0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0},
|
||||||
{0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x18, 0x00},
|
{0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x18, 0x00},
|
||||||
{0x38, 0x6c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00, 0x0c, 0x00},
|
{0x38, 0x6c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00, 0x0c, 0x00},
|
||||||
{0x00, 0x00, 0xc6, 0xcc, 0xf8, 0xf0, 0xd8, 0xcc, 0xc6, 0xc0, 0xc0, 0xc0, 0xc0},
|
{0x00, 0x00, 0xc6, 0xcc, 0xf8, 0xf0, 0xd8, 0xcc, 0xc6, 0xc0, 0xc0, 0xc0, 0xc0},
|
||||||
{0x00, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78},
|
{0x00, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78},
|
||||||
{0x00, 0x00, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xfe, 0x00, 0x00, 0x00, 0x00},
|
{0x00, 0x00, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0xfe, 0x00, 0x00, 0x00, 0x00},
|
||||||
{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xfc, 0x00, 0x00, 0x00, 0x00},
|
{0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xfc, 0x00, 0x00, 0x00, 0x00},
|
||||||
{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
|
{0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00},
|
||||||
{0xc0, 0xc0, 0xc0, 0xfe, 0xc3, 0xc3, 0xc3, 0xc3, 0xfe, 0x00, 0x00, 0x00, 0x00},
|
{0xc0, 0xc0, 0xc0, 0xfe, 0xc3, 0xc3, 0xc3, 0xc3, 0xfe, 0x00, 0x00, 0x00, 0x00},
|
||||||
{0x03, 0x03, 0x03, 0x7f, 0xc3, 0xc3, 0xc3, 0xc3, 0x7f, 0x00, 0x00, 0x00, 0x00},
|
{0x03, 0x03, 0x03, 0x7f, 0xc3, 0xc3, 0xc3, 0xc3, 0x7f, 0x00, 0x00, 0x00, 0x00},
|
||||||
{0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xe0, 0xfe, 0x00, 0x00, 0x00, 0x00},
|
{0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xe0, 0xfe, 0x00, 0x00, 0x00, 0x00},
|
||||||
{0x00, 0x00, 0xfe, 0x03, 0x03, 0x7e, 0xc0, 0xc0, 0x7f, 0x00, 0x00, 0x00, 0x00},
|
{0x00, 0x00, 0xfe, 0x03, 0x03, 0x7e, 0xc0, 0xc0, 0x7f, 0x00, 0x00, 0x00, 0x00},
|
||||||
{0x00, 0x00, 0x1c, 0x36, 0x30, 0x30, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x00},
|
{0x00, 0x00, 0x1c, 0x36, 0x30, 0x30, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x00},
|
||||||
{0x00, 0x00, 0x7e, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
|
{0x00, 0x00, 0x7e, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00},
|
||||||
{0x00, 0x00, 0x18, 0x3c, 0x3c, 0x66, 0x66, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00},
|
{0x00, 0x00, 0x18, 0x3c, 0x3c, 0x66, 0x66, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00},
|
||||||
{0x00, 0x00, 0xc3, 0xe7, 0xff, 0xdb, 0xc3, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00},
|
{0x00, 0x00, 0xc3, 0xe7, 0xff, 0xdb, 0xc3, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00},
|
||||||
{0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0xc3, 0x00, 0x00, 0x00, 0x00},
|
{0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0xc3, 0x00, 0x00, 0x00, 0x00},
|
||||||
{0xc0, 0x60, 0x60, 0x30, 0x18, 0x3c, 0x66, 0x66, 0xc3, 0x00, 0x00, 0x00, 0x00},
|
{0xc0, 0x60, 0x60, 0x30, 0x18, 0x3c, 0x66, 0x66, 0xc3, 0x00, 0x00, 0x00, 0x00},
|
||||||
{0x00, 0x00, 0xff, 0x60, 0x30, 0x18, 0x0c, 0x06, 0xff, 0x00, 0x00, 0x00, 0x00},
|
{0x00, 0x00, 0xff, 0x60, 0x30, 0x18, 0x0c, 0x06, 0xff, 0x00, 0x00, 0x00, 0x00},
|
||||||
{0x00, 0x00, 0x0f, 0x18, 0x18, 0x18, 0x38, 0xf0, 0x38, 0x18, 0x18, 0x18, 0x0f},
|
{0x00, 0x00, 0x0f, 0x18, 0x18, 0x18, 0x38, 0xf0, 0x38, 0x18, 0x18, 0x18, 0x0f},
|
||||||
{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
|
{0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
|
||||||
{0x00, 0x00, 0xf0, 0x18, 0x18, 0x18, 0x1c, 0x0f, 0x1c, 0x18, 0x18, 0x18, 0xf0},
|
{0x00, 0x00, 0xf0, 0x18, 0x18, 0x18, 0x1c, 0x0f, 0x1c, 0x18, 0x18, 0x18, 0xf0},
|
||||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x8f, 0xf1, 0x60, 0x00, 0x00, 0x00}
|
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x8f, 0xf1, 0x60, 0x00, 0x00, 0x00}
|
||||||
};
|
};
|
||||||
|
|
||||||
RasterFont::RasterFont()
|
RasterFont::RasterFont()
|
||||||
{
|
{
|
||||||
// set GL modes
|
// set GL modes
|
||||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||||
|
|
||||||
// create the raster font
|
// create the raster font
|
||||||
fontOffset = glGenLists(128);
|
fontOffset = glGenLists(128);
|
||||||
for (int i = 32; i < 127; i++) {
|
for (int i = 32; i < 127; i++)
|
||||||
|
{
|
||||||
glNewList(i + fontOffset, GL_COMPILE);
|
glNewList(i + fontOffset, GL_COMPILE);
|
||||||
glBitmap(8, 13, 0.0f, 2.0f, 10.0f, 0.0f, rasters[i - 32]);
|
glBitmap(8, 13, 0.0f, 2.0f, 10.0f, 0.0f, rasters[i - 32]);
|
||||||
glEndList();
|
glEndList();
|
||||||
|
@ -153,7 +155,8 @@ void RasterFont::printString(const char *s, double x, double y, double z)
|
||||||
char *s2 = temp_buffer;
|
char *s2 = temp_buffer;
|
||||||
memcpy(s2, s, length);
|
memcpy(s2, s, length);
|
||||||
s2[length] = 0;
|
s2[length] = 0;
|
||||||
for (int i = 0; i < length; i++) {
|
for (int i = 0; i < length; i++)
|
||||||
|
{
|
||||||
if (s2[i] < 32 || s2[i] > 126)
|
if (s2[i] < 32 || s2[i] > 126)
|
||||||
s2[i] = '!';
|
s2[i] = '!';
|
||||||
}
|
}
|
||||||
|
@ -209,7 +212,9 @@ void RasterFont::printMultilineText(const char *text, double start_x, double sta
|
||||||
*t++ = ' ';
|
*t++ = ' ';
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
*t++ = *text;
|
*t++ = *text;
|
||||||
|
}
|
||||||
|
|
||||||
text++;
|
text++;
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,30 +12,31 @@
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official Git repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#ifndef _RASTERFONT_H_
|
#ifndef _RASTERFONT_H_
|
||||||
#define _RASTERFONT_H_
|
#define _RASTERFONT_H_
|
||||||
|
|
||||||
class RasterFont {
|
class RasterFont
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
RasterFont();
|
RasterFont();
|
||||||
~RasterFont(void);
|
~RasterFont(void);
|
||||||
static int debug;
|
static int debug;
|
||||||
|
|
||||||
// some useful constants
|
// some useful constants
|
||||||
enum {char_width = 10};
|
enum {char_width = 10};
|
||||||
enum {char_height = 15};
|
enum {char_height = 15};
|
||||||
|
|
||||||
// and the happy helper functions
|
// and the happy helper functions
|
||||||
void printString(const char *s, double x, double y, double z=0.0);
|
void printString(const char *s, double x, double y, double z=0.0);
|
||||||
void printCenteredString(const char *s, double y, int screen_width, double z=0.0);
|
void printCenteredString(const char *s, double y, int screen_width, double z=0.0);
|
||||||
|
|
||||||
void printMultilineText(const char *text, double x, double y, double z, int bbWidth, int bbHeight);
|
void printMultilineText(const char *text, double x, double y, double z, int bbWidth, int bbHeight);
|
||||||
private:
|
private:
|
||||||
int fontOffset;
|
int fontOffset;
|
||||||
char *temp_buffer;
|
char *temp_buffer;
|
||||||
enum {TEMP_BUFFER_SIZE = 64 * 1024};
|
enum {TEMP_BUFFER_SIZE = 64 * 1024};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official Git repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
|
@ -97,34 +97,34 @@ void Init()
|
||||||
|
|
||||||
inline int iround(float x)
|
inline int iround(float x)
|
||||||
{
|
{
|
||||||
int t;
|
int t;
|
||||||
|
|
||||||
#if defined(_WIN32) && !defined(_M_X64)
|
#if defined(_WIN32) && !defined(_M_X64)
|
||||||
__asm
|
__asm
|
||||||
{
|
{
|
||||||
fld x
|
fld x
|
||||||
fistp t
|
fistp t
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
t = (int)x;
|
t = (int)x;
|
||||||
if((x - t) >= 0.5)
|
if((x - t) >= 0.5)
|
||||||
return t + 1;
|
return t + 1;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetScissor()
|
void SetScissor()
|
||||||
{
|
{
|
||||||
int xoff = bpmem.scissorOffset.x * 2 - 342;
|
int xoff = bpmem.scissorOffset.x * 2 - 342;
|
||||||
int yoff = bpmem.scissorOffset.y * 2 - 342;
|
int yoff = bpmem.scissorOffset.y * 2 - 342;
|
||||||
|
|
||||||
scissorLeft = bpmem.scissorTL.x - xoff - 342;
|
scissorLeft = bpmem.scissorTL.x - xoff - 342;
|
||||||
if (scissorLeft < 0) scissorLeft = 0;
|
if (scissorLeft < 0) scissorLeft = 0;
|
||||||
|
|
||||||
scissorTop = bpmem.scissorTL.y - yoff - 342;
|
scissorTop = bpmem.scissorTL.y - yoff - 342;
|
||||||
if (scissorTop < 0) scissorTop = 0;
|
if (scissorTop < 0) scissorTop = 0;
|
||||||
|
|
||||||
scissorRight = bpmem.scissorBR.x - xoff - 341;
|
scissorRight = bpmem.scissorBR.x - xoff - 341;
|
||||||
if (scissorRight > EFB_WIDTH) scissorRight = EFB_WIDTH;
|
if (scissorRight > EFB_WIDTH) scissorRight = EFB_WIDTH;
|
||||||
|
|
||||||
|
@ -134,12 +134,12 @@ void SetScissor()
|
||||||
|
|
||||||
void SetTevReg(int reg, int comp, bool konst, s16 color)
|
void SetTevReg(int reg, int comp, bool konst, s16 color)
|
||||||
{
|
{
|
||||||
tev.SetRegColor(reg, comp, konst, color);
|
tev.SetRegColor(reg, comp, konst, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void Draw(s32 x, s32 y, s32 xi, s32 yi)
|
inline void Draw(s32 x, s32 y, s32 xi, s32 yi)
|
||||||
{
|
{
|
||||||
INCSTAT(swstats.thisFrame.rasterizedPixels);
|
INCSTAT(swstats.thisFrame.rasterizedPixels);
|
||||||
|
|
||||||
float dx = vertexOffsetX + (float)(x - vertex0X);
|
float dx = vertexOffsetX + (float)(x - vertex0X);
|
||||||
float dy = vertexOffsetY + (float)(y - vertex0Y);
|
float dy = vertexOffsetY + (float)(y - vertex0Y);
|
||||||
|
@ -200,14 +200,14 @@ inline void Draw(s32 x, s32 y, s32 xi, s32 yi)
|
||||||
tev.TextureLod[i] = rasterBlock.TextureLod[i];
|
tev.TextureLod[i] = rasterBlock.TextureLod[i];
|
||||||
tev.TextureLinear[i] = rasterBlock.TextureLinear[i];
|
tev.TextureLinear[i] = rasterBlock.TextureLinear[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
tev.Draw();
|
tev.Draw();
|
||||||
}
|
}
|
||||||
|
|
||||||
void InitTriangle(float X1, float Y1, s32 xi, s32 yi)
|
void InitTriangle(float X1, float Y1, s32 xi, s32 yi)
|
||||||
{
|
{
|
||||||
vertex0X = xi;
|
vertex0X = xi;
|
||||||
vertex0Y = yi;
|
vertex0Y = yi;
|
||||||
|
|
||||||
// adjust a little less than 0.5
|
// adjust a little less than 0.5
|
||||||
const float adjust = 0.495f;
|
const float adjust = 0.495f;
|
||||||
|
@ -219,13 +219,13 @@ void InitTriangle(float X1, float Y1, s32 xi, s32 yi)
|
||||||
void InitSlope(Slope *slope, float f1, float f2, float f3, float DX31, float DX12, float DY12, float DY31)
|
void InitSlope(Slope *slope, float f1, float f2, float f3, float DX31, float DX12, float DY12, float DY31)
|
||||||
{
|
{
|
||||||
float DF31 = f3 - f1;
|
float DF31 = f3 - f1;
|
||||||
float DF21 = f2 - f1;
|
float DF21 = f2 - f1;
|
||||||
float a = DF31 * -DY12 - DF21 * DY31;
|
float a = DF31 * -DY12 - DF21 * DY31;
|
||||||
float b = DX31 * DF21 + DX12 * DF31;
|
float b = DX31 * DF21 + DX12 * DF31;
|
||||||
float c = -DX12 * DY31 - DX31 * -DY12;
|
float c = -DX12 * DY31 - DX31 * -DY12;
|
||||||
slope->dfdx = -a / c;
|
slope->dfdx = -a / c;
|
||||||
slope->dfdy = -b / c;
|
slope->dfdy = -b / c;
|
||||||
slope->f0 = f1;
|
slope->f0 = f1;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void CalculateLOD(s32 &lod, bool &linear, u32 texmap, u32 texcoord)
|
inline void CalculateLOD(s32 &lod, bool &linear, u32 texmap, u32 texcoord)
|
||||||
|
@ -332,17 +332,17 @@ void BuildBlock(s32 blockX, s32 blockY)
|
||||||
|
|
||||||
void DrawTriangleFrontFace(OutputVertexData *v0, OutputVertexData *v1, OutputVertexData *v2)
|
void DrawTriangleFrontFace(OutputVertexData *v0, OutputVertexData *v1, OutputVertexData *v2)
|
||||||
{
|
{
|
||||||
INCSTAT(swstats.thisFrame.numTrianglesDrawn);
|
INCSTAT(swstats.thisFrame.numTrianglesDrawn);
|
||||||
|
|
||||||
if (g_SWVideoConfig.bHwRasterizer)
|
if (g_SWVideoConfig.bHwRasterizer)
|
||||||
{
|
{
|
||||||
HwRasterizer::DrawTriangleFrontFace(v0, v1, v2);
|
HwRasterizer::DrawTriangleFrontFace(v0, v1, v2);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// adapted from http://www.devmaster.net/forums/showthread.php?t=1884
|
// adapted from http://www.devmaster.net/forums/showthread.php?t=1884
|
||||||
|
|
||||||
// 28.4 fixed-pou32 coordinates. rounded to nearest and adjusted to match hardware output
|
// 28.4 fixed-pou32 coordinates. rounded to nearest and adjusted to match hardware output
|
||||||
// could also take floor and adjust -8
|
// could also take floor and adjust -8
|
||||||
const s32 Y1 = iround(16.0f * v0->screenPosition[1]) - 9;
|
const s32 Y1 = iround(16.0f * v0->screenPosition[1]) - 9;
|
||||||
const s32 Y2 = iround(16.0f * v1->screenPosition[1]) - 9;
|
const s32 Y2 = iround(16.0f * v1->screenPosition[1]) - 9;
|
||||||
|
@ -352,161 +352,160 @@ void DrawTriangleFrontFace(OutputVertexData *v0, OutputVertexData *v1, OutputVer
|
||||||
const s32 X2 = iround(16.0f * v1->screenPosition[0]) - 9;
|
const s32 X2 = iround(16.0f * v1->screenPosition[0]) - 9;
|
||||||
const s32 X3 = iround(16.0f * v2->screenPosition[0]) - 9;
|
const s32 X3 = iround(16.0f * v2->screenPosition[0]) - 9;
|
||||||
|
|
||||||
// Deltas
|
// Deltas
|
||||||
const s32 DX12 = X1 - X2;
|
const s32 DX12 = X1 - X2;
|
||||||
const s32 DX23 = X2 - X3;
|
const s32 DX23 = X2 - X3;
|
||||||
const s32 DX31 = X3 - X1;
|
const s32 DX31 = X3 - X1;
|
||||||
|
|
||||||
const s32 DY12 = Y1 - Y2;
|
const s32 DY12 = Y1 - Y2;
|
||||||
const s32 DY23 = Y2 - Y3;
|
const s32 DY23 = Y2 - Y3;
|
||||||
const s32 DY31 = Y3 - Y1;
|
const s32 DY31 = Y3 - Y1;
|
||||||
|
|
||||||
// Fixed-pos32 deltas
|
// Fixed-pos32 deltas
|
||||||
const s32 FDX12 = DX12 << 4;
|
const s32 FDX12 = DX12 << 4;
|
||||||
const s32 FDX23 = DX23 << 4;
|
const s32 FDX23 = DX23 << 4;
|
||||||
const s32 FDX31 = DX31 << 4;
|
const s32 FDX31 = DX31 << 4;
|
||||||
|
|
||||||
const s32 FDY12 = DY12 << 4;
|
const s32 FDY12 = DY12 << 4;
|
||||||
const s32 FDY23 = DY23 << 4;
|
const s32 FDY23 = DY23 << 4;
|
||||||
const s32 FDY31 = DY31 << 4;
|
const s32 FDY31 = DY31 << 4;
|
||||||
|
|
||||||
// Bounding rectangle
|
// Bounding rectangle
|
||||||
s32 minx = (min(min(X1, X2), X3) + 0xF) >> 4;
|
s32 minx = (min(min(X1, X2), X3) + 0xF) >> 4;
|
||||||
s32 maxx = (max(max(X1, X2), X3) + 0xF) >> 4;
|
s32 maxx = (max(max(X1, X2), X3) + 0xF) >> 4;
|
||||||
s32 miny = (min(min(Y1, Y2), Y3) + 0xF) >> 4;
|
s32 miny = (min(min(Y1, Y2), Y3) + 0xF) >> 4;
|
||||||
s32 maxy = (max(max(Y1, Y2), Y3) + 0xF) >> 4;
|
s32 maxy = (max(max(Y1, Y2), Y3) + 0xF) >> 4;
|
||||||
|
|
||||||
// scissor
|
// scissor
|
||||||
minx = max(minx, scissorLeft);
|
minx = max(minx, scissorLeft);
|
||||||
maxx = min(maxx, scissorRight);
|
maxx = min(maxx, scissorRight);
|
||||||
miny = max(miny, scissorTop);
|
miny = max(miny, scissorTop);
|
||||||
maxy = min(maxy, scissorBottom);
|
maxy = min(maxy, scissorBottom);
|
||||||
|
|
||||||
if (minx >= maxx || miny >= maxy)
|
if (minx >= maxx || miny >= maxy)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Setup slopes
|
// Setup slopes
|
||||||
float fltx1 = v0->screenPosition.x;
|
float fltx1 = v0->screenPosition.x;
|
||||||
float flty1 = v0->screenPosition.y;
|
float flty1 = v0->screenPosition.y;
|
||||||
float fltdx31 = v2->screenPosition.x - fltx1;
|
float fltdx31 = v2->screenPosition.x - fltx1;
|
||||||
float fltdx12 = fltx1 - v1->screenPosition.x;
|
float fltdx12 = fltx1 - v1->screenPosition.x;
|
||||||
float fltdy12 = flty1 - v1->screenPosition.y;
|
float fltdy12 = flty1 - v1->screenPosition.y;
|
||||||
float fltdy31 = v2->screenPosition.y - flty1;
|
float fltdy31 = v2->screenPosition.y - flty1;
|
||||||
|
|
||||||
InitTriangle(fltx1, flty1, (X1 + 0xF) >> 4, (Y1 + 0xF) >> 4);
|
InitTriangle(fltx1, flty1, (X1 + 0xF) >> 4, (Y1 + 0xF) >> 4);
|
||||||
|
|
||||||
float w[3] = { 1.0f / v0->projectedPosition.w, 1.0f / v1->projectedPosition.w, 1.0f / v2->projectedPosition.w };
|
float w[3] = { 1.0f / v0->projectedPosition.w, 1.0f / v1->projectedPosition.w, 1.0f / v2->projectedPosition.w };
|
||||||
InitSlope(&WSlope, w[0], w[1], w[2], fltdx31, fltdx12, fltdy12, fltdy31);
|
InitSlope(&WSlope, w[0], w[1], w[2], fltdx31, fltdx12, fltdy12, fltdy31);
|
||||||
|
|
||||||
if (!bpmem.genMode.zfreeze || !g_SWVideoConfig.bZFreeze)
|
if (!bpmem.genMode.zfreeze || !g_SWVideoConfig.bZFreeze)
|
||||||
InitSlope(&ZSlope, v0->screenPosition[2], v1->screenPosition[2], v2->screenPosition[2], fltdx31, fltdx12, fltdy12, fltdy31);
|
InitSlope(&ZSlope, v0->screenPosition[2], v1->screenPosition[2], v2->screenPosition[2], fltdx31, fltdx12, fltdy12, fltdy31);
|
||||||
|
|
||||||
for(unsigned int i = 0; i < bpmem.genMode.numcolchans; i++)
|
for(unsigned int i = 0; i < bpmem.genMode.numcolchans; i++)
|
||||||
{
|
{
|
||||||
for(int comp = 0; comp < 4; comp++)
|
for(int comp = 0; comp < 4; comp++)
|
||||||
InitSlope(&ColorSlopes[i][comp], v0->color[i][comp], v1->color[i][comp], v2->color[i][comp], fltdx31, fltdx12, fltdy12, fltdy31);
|
InitSlope(&ColorSlopes[i][comp], v0->color[i][comp], v1->color[i][comp], v2->color[i][comp], fltdx31, fltdx12, fltdy12, fltdy31);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(unsigned int i = 0; i < bpmem.genMode.numtexgens; i++)
|
for(unsigned int i = 0; i < bpmem.genMode.numtexgens; i++)
|
||||||
{
|
{
|
||||||
for(int comp = 0; comp < 3; comp++)
|
for(int comp = 0; comp < 3; comp++)
|
||||||
InitSlope(&TexSlopes[i][comp], v0->texCoords[i][comp] * w[0], v1->texCoords[i][comp] * w[1], v2->texCoords[i][comp] * w[2], fltdx31, fltdx12, fltdy12, fltdy31);
|
InitSlope(&TexSlopes[i][comp], v0->texCoords[i][comp] * w[0], v1->texCoords[i][comp] * w[1], v2->texCoords[i][comp] * w[2], fltdx31, fltdx12, fltdy12, fltdy31);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start in corner of 8x8 block
|
// Start in corner of 8x8 block
|
||||||
minx &= ~(BLOCK_SIZE - 1);
|
minx &= ~(BLOCK_SIZE - 1);
|
||||||
miny &= ~(BLOCK_SIZE - 1);
|
miny &= ~(BLOCK_SIZE - 1);
|
||||||
|
|
||||||
// Half-edge constants
|
|
||||||
s32 C1 = DY12 * X1 - DX12 * Y1;
|
|
||||||
s32 C2 = DY23 * X2 - DX23 * Y2;
|
|
||||||
s32 C3 = DY31 * X3 - DX31 * Y3;
|
|
||||||
|
|
||||||
// Correct for fill convention
|
// Half-edge constants
|
||||||
if(DY12 < 0 || (DY12 == 0 && DX12 > 0)) C1++;
|
s32 C1 = DY12 * X1 - DX12 * Y1;
|
||||||
if(DY23 < 0 || (DY23 == 0 && DX23 > 0)) C2++;
|
s32 C2 = DY23 * X2 - DX23 * Y2;
|
||||||
if(DY31 < 0 || (DY31 == 0 && DX31 > 0)) C3++;
|
s32 C3 = DY31 * X3 - DX31 * Y3;
|
||||||
|
|
||||||
// Loop through blocks
|
// Correct for fill convention
|
||||||
for(s32 y = miny; y < maxy; y += BLOCK_SIZE)
|
if(DY12 < 0 || (DY12 == 0 && DX12 > 0)) C1++;
|
||||||
{
|
if(DY23 < 0 || (DY23 == 0 && DX23 > 0)) C2++;
|
||||||
for(s32 x = minx; x < maxx; x += BLOCK_SIZE)
|
if(DY31 < 0 || (DY31 == 0 && DX31 > 0)) C3++;
|
||||||
{
|
|
||||||
// Corners of block
|
|
||||||
s32 x0 = x << 4;
|
|
||||||
s32 x1 = (x + BLOCK_SIZE - 1) << 4;
|
|
||||||
s32 y0 = y << 4;
|
|
||||||
s32 y1 = (y + BLOCK_SIZE - 1) << 4;
|
|
||||||
|
|
||||||
// Evaluate half-space functions
|
// Loop through blocks
|
||||||
bool a00 = C1 + DX12 * y0 - DY12 * x0 > 0;
|
for(s32 y = miny; y < maxy; y += BLOCK_SIZE)
|
||||||
bool a10 = C1 + DX12 * y0 - DY12 * x1 > 0;
|
{
|
||||||
bool a01 = C1 + DX12 * y1 - DY12 * x0 > 0;
|
for(s32 x = minx; x < maxx; x += BLOCK_SIZE)
|
||||||
bool a11 = C1 + DX12 * y1 - DY12 * x1 > 0;
|
{
|
||||||
int a = (a00 << 0) | (a10 << 1) | (a01 << 2) | (a11 << 3);
|
// Corners of block
|
||||||
|
s32 x0 = x << 4;
|
||||||
bool b00 = C2 + DX23 * y0 - DY23 * x0 > 0;
|
s32 x1 = (x + BLOCK_SIZE - 1) << 4;
|
||||||
bool b10 = C2 + DX23 * y0 - DY23 * x1 > 0;
|
s32 y0 = y << 4;
|
||||||
bool b01 = C2 + DX23 * y1 - DY23 * x0 > 0;
|
s32 y1 = (y + BLOCK_SIZE - 1) << 4;
|
||||||
bool b11 = C2 + DX23 * y1 - DY23 * x1 > 0;
|
|
||||||
int b = (b00 << 0) | (b10 << 1) | (b01 << 2) | (b11 << 3);
|
|
||||||
|
|
||||||
bool c00 = C3 + DX31 * y0 - DY31 * x0 > 0;
|
|
||||||
bool c10 = C3 + DX31 * y0 - DY31 * x1 > 0;
|
|
||||||
bool c01 = C3 + DX31 * y1 - DY31 * x0 > 0;
|
|
||||||
bool c11 = C3 + DX31 * y1 - DY31 * x1 > 0;
|
|
||||||
int c = (c00 << 0) | (c10 << 1) | (c01 << 2) | (c11 << 3);
|
|
||||||
|
|
||||||
// Skip block when outside an edge
|
// Evaluate half-space functions
|
||||||
if(a == 0x0 || b == 0x0 || c == 0x0) continue;
|
bool a00 = C1 + DX12 * y0 - DY12 * x0 > 0;
|
||||||
|
bool a10 = C1 + DX12 * y0 - DY12 * x1 > 0;
|
||||||
|
bool a01 = C1 + DX12 * y1 - DY12 * x0 > 0;
|
||||||
|
bool a11 = C1 + DX12 * y1 - DY12 * x1 > 0;
|
||||||
|
int a = (a00 << 0) | (a10 << 1) | (a01 << 2) | (a11 << 3);
|
||||||
|
|
||||||
|
bool b00 = C2 + DX23 * y0 - DY23 * x0 > 0;
|
||||||
|
bool b10 = C2 + DX23 * y0 - DY23 * x1 > 0;
|
||||||
|
bool b01 = C2 + DX23 * y1 - DY23 * x0 > 0;
|
||||||
|
bool b11 = C2 + DX23 * y1 - DY23 * x1 > 0;
|
||||||
|
int b = (b00 << 0) | (b10 << 1) | (b01 << 2) | (b11 << 3);
|
||||||
|
|
||||||
|
bool c00 = C3 + DX31 * y0 - DY31 * x0 > 0;
|
||||||
|
bool c10 = C3 + DX31 * y0 - DY31 * x1 > 0;
|
||||||
|
bool c01 = C3 + DX31 * y1 - DY31 * x0 > 0;
|
||||||
|
bool c11 = C3 + DX31 * y1 - DY31 * x1 > 0;
|
||||||
|
int c = (c00 << 0) | (c10 << 1) | (c01 << 2) | (c11 << 3);
|
||||||
|
|
||||||
|
// Skip block when outside an edge
|
||||||
|
if(a == 0x0 || b == 0x0 || c == 0x0)
|
||||||
|
continue;
|
||||||
|
|
||||||
BuildBlock(x, y);
|
BuildBlock(x, y);
|
||||||
|
|
||||||
// Accept whole block when totally covered
|
// Accept whole block when totally covered
|
||||||
if(a == 0xF && b == 0xF && c == 0xF)
|
if(a == 0xF && b == 0xF && c == 0xF)
|
||||||
{
|
{
|
||||||
for(s32 iy = 0; iy < BLOCK_SIZE; iy++)
|
for(s32 iy = 0; iy < BLOCK_SIZE; iy++)
|
||||||
{
|
{
|
||||||
for(s32 ix = 0; ix < BLOCK_SIZE; ix++)
|
for(s32 ix = 0; ix < BLOCK_SIZE; ix++)
|
||||||
{
|
{
|
||||||
Draw(x + ix, y + iy, ix, iy);
|
Draw(x + ix, y + iy, ix, iy);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else // Partially covered block
|
else // Partially covered block
|
||||||
{
|
{
|
||||||
s32 CY1 = C1 + DX12 * y0 - DY12 * x0;
|
s32 CY1 = C1 + DX12 * y0 - DY12 * x0;
|
||||||
s32 CY2 = C2 + DX23 * y0 - DY23 * x0;
|
s32 CY2 = C2 + DX23 * y0 - DY23 * x0;
|
||||||
s32 CY3 = C3 + DX31 * y0 - DY31 * x0;
|
s32 CY3 = C3 + DX31 * y0 - DY31 * x0;
|
||||||
|
|
||||||
for(s32 iy = 0; iy < BLOCK_SIZE; iy++)
|
for(s32 iy = 0; iy < BLOCK_SIZE; iy++)
|
||||||
{
|
{
|
||||||
s32 CX1 = CY1;
|
s32 CX1 = CY1;
|
||||||
s32 CX2 = CY2;
|
s32 CX2 = CY2;
|
||||||
s32 CX3 = CY3;
|
s32 CX3 = CY3;
|
||||||
|
|
||||||
for(s32 ix = 0; ix < BLOCK_SIZE; ix++)
|
for(s32 ix = 0; ix < BLOCK_SIZE; ix++)
|
||||||
{
|
{
|
||||||
if(CX1 > 0 && CX2 > 0 && CX3 > 0)
|
if(CX1 > 0 && CX2 > 0 && CX3 > 0)
|
||||||
{
|
{
|
||||||
Draw(x + ix, y + iy, ix, iy);
|
Draw(x + ix, y + iy, ix, iy);
|
||||||
}
|
}
|
||||||
|
|
||||||
CX1 -= FDY12;
|
CX1 -= FDY12;
|
||||||
CX2 -= FDY23;
|
CX2 -= FDY23;
|
||||||
CX3 -= FDY31;
|
CX3 -= FDY31;
|
||||||
}
|
}
|
||||||
|
|
||||||
CY1 += FDX12;
|
|
||||||
CY2 += FDX23;
|
|
||||||
CY3 += FDX31;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
CY1 += FDX12;
|
||||||
|
CY2 += FDX23;
|
||||||
|
CY3 += FDX31;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official Git repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#ifndef _RASTERIZER_H_
|
#ifndef _RASTERIZER_H_
|
||||||
|
@ -23,19 +23,19 @@
|
||||||
|
|
||||||
namespace Rasterizer
|
namespace Rasterizer
|
||||||
{
|
{
|
||||||
void Init();
|
void Init();
|
||||||
|
|
||||||
void DrawTriangleFrontFace(OutputVertexData *v0, OutputVertexData *v1, OutputVertexData *v2);
|
void DrawTriangleFrontFace(OutputVertexData *v0, OutputVertexData *v1, OutputVertexData *v2);
|
||||||
|
|
||||||
void SetScissor();
|
void SetScissor();
|
||||||
|
|
||||||
void SetTevReg(int reg, int comp, bool konst, s16 color);
|
void SetTevReg(int reg, int comp, bool konst, s16 color);
|
||||||
|
|
||||||
struct Slope
|
struct Slope
|
||||||
{
|
{
|
||||||
float dfdx;
|
float dfdx;
|
||||||
float dfdy;
|
float dfdy;
|
||||||
float f0;
|
float f0;
|
||||||
|
|
||||||
float GetValue(float dx, float dy) { return f0 + (dfdx * dx) + (dfdy * dy); }
|
float GetValue(float dx, float dy) { return f0 + (dfdx * dx) + (dfdy * dy); }
|
||||||
void DoState(PointerWrap &p)
|
void DoState(PointerWrap &p)
|
||||||
|
@ -44,7 +44,7 @@ namespace Rasterizer
|
||||||
p.Do(dfdy);
|
p.Do(dfdy);
|
||||||
p.Do(f0);
|
p.Do(f0);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct RasterBlockPixel
|
struct RasterBlockPixel
|
||||||
{
|
{
|
||||||
|
@ -62,7 +62,6 @@ namespace Rasterizer
|
||||||
};
|
};
|
||||||
|
|
||||||
void DoState(PointerWrap &p);
|
void DoState(PointerWrap &p);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official Git repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
|
@ -37,7 +37,7 @@ namespace SWCommandProcessor
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
GATHER_PIPE_SIZE = 32,
|
GATHER_PIPE_SIZE = 32,
|
||||||
INT_CAUSE_CP = 0x800
|
INT_CAUSE_CP = 0x800
|
||||||
};
|
};
|
||||||
|
|
||||||
// STATE_TO_SAVE
|
// STATE_TO_SAVE
|
||||||
|
@ -83,17 +83,17 @@ void UpdateInterrupts_Wrapper(u64 userdata, int cyclesLate)
|
||||||
|
|
||||||
inline bool AtBreakpoint()
|
inline bool AtBreakpoint()
|
||||||
{
|
{
|
||||||
return cpreg.ctrl.BPEnable && (cpreg.readptr == cpreg.breakpt);
|
return cpreg.ctrl.BPEnable && (cpreg.readptr == cpreg.breakpt);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Init()
|
void Init()
|
||||||
{
|
{
|
||||||
cpreg.status.Hex = 0;
|
cpreg.status.Hex = 0;
|
||||||
cpreg.status.CommandIdle = 1;
|
cpreg.status.CommandIdle = 1;
|
||||||
cpreg.status.ReadIdle = 1;
|
cpreg.status.ReadIdle = 1;
|
||||||
|
|
||||||
cpreg.ctrl.Hex = 0;
|
cpreg.ctrl.Hex = 0;
|
||||||
cpreg.clear.Hex = 0;
|
cpreg.clear.Hex = 0;
|
||||||
|
|
||||||
cpreg.bboxleft = 0;
|
cpreg.bboxleft = 0;
|
||||||
cpreg.bboxtop = 0;
|
cpreg.bboxtop = 0;
|
||||||
|
@ -104,15 +104,15 @@ void Init()
|
||||||
|
|
||||||
et_UpdateInterrupts = CoreTiming::RegisterEvent("UpdateInterrupts", UpdateInterrupts_Wrapper);
|
et_UpdateInterrupts = CoreTiming::RegisterEvent("UpdateInterrupts", UpdateInterrupts_Wrapper);
|
||||||
|
|
||||||
// internal buffer position
|
// internal buffer position
|
||||||
readPos = 0;
|
readPos = 0;
|
||||||
writePos = 0;
|
writePos = 0;
|
||||||
|
|
||||||
interruptSet = false;
|
interruptSet = false;
|
||||||
interruptWaiting = false;
|
interruptWaiting = false;
|
||||||
|
|
||||||
g_pVideoData = 0;
|
g_pVideoData = 0;
|
||||||
g_bSkipCurrentFrame = false;
|
g_bSkipCurrentFrame = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shutdown()
|
void Shutdown()
|
||||||
|
@ -121,31 +121,32 @@ void Shutdown()
|
||||||
|
|
||||||
void RunGpu()
|
void RunGpu()
|
||||||
{
|
{
|
||||||
if (!SConfig::GetInstance().m_LocalCoreStartupParameter.bCPUThread)
|
if (!SConfig::GetInstance().m_LocalCoreStartupParameter.bCPUThread)
|
||||||
{
|
{
|
||||||
// We are going to do FP math on the main thread so have to save the current state
|
// We are going to do FP math on the main thread so have to save the current state
|
||||||
FPURoundMode::SaveSIMDState();
|
FPURoundMode::SaveSIMDState();
|
||||||
FPURoundMode::LoadDefaultSIMDState();
|
FPURoundMode::LoadDefaultSIMDState();
|
||||||
|
|
||||||
// run the opcode decoder
|
|
||||||
do {
|
|
||||||
RunBuffer();
|
|
||||||
} while (cpreg.ctrl.GPReadEnable && !AtBreakpoint() && cpreg.readptr != cpreg.writeptr);
|
|
||||||
|
|
||||||
FPURoundMode::LoadSIMDState();
|
// run the opcode decoder
|
||||||
}
|
do
|
||||||
|
{
|
||||||
|
RunBuffer();
|
||||||
|
} while (cpreg.ctrl.GPReadEnable && !AtBreakpoint() && cpreg.readptr != cpreg.writeptr);
|
||||||
|
|
||||||
|
FPURoundMode::LoadSIMDState();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Read16(u16& _rReturnValue, const u32 _Address)
|
void Read16(u16& _rReturnValue, const u32 _Address)
|
||||||
{
|
{
|
||||||
u32 regAddr = (_Address & 0xFFF) >> 1;
|
u32 regAddr = (_Address & 0xFFF) >> 1;
|
||||||
|
|
||||||
DEBUG_LOG(COMMANDPROCESSOR, "(r): 0x%08x : 0x%08x", _Address, ((u16*)&cpreg)[regAddr]);
|
DEBUG_LOG(COMMANDPROCESSOR, "(r): 0x%08x : 0x%08x", _Address, ((u16*)&cpreg)[regAddr]);
|
||||||
|
|
||||||
if (regAddr < 0x20)
|
if (regAddr < 0x20)
|
||||||
_rReturnValue = ((u16*)&cpreg)[regAddr];
|
_rReturnValue = ((u16*)&cpreg)[regAddr];
|
||||||
else
|
else
|
||||||
_rReturnValue = 0;
|
_rReturnValue = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Write16(const u16 _Value, const u32 _Address)
|
void Write16(const u16 _Value, const u32 _Address)
|
||||||
|
@ -162,14 +163,14 @@ void Write16(const u16 _Value, const u32 _Address)
|
||||||
|
|
||||||
case CTRL_REGISTER:
|
case CTRL_REGISTER:
|
||||||
{
|
{
|
||||||
cpreg.ctrl.Hex = _Value;
|
cpreg.ctrl.Hex = _Value;
|
||||||
|
|
||||||
DEBUG_LOG(COMMANDPROCESSOR,"\t write to CTRL_REGISTER : %04x", _Value);
|
DEBUG_LOG(COMMANDPROCESSOR,"\t write to CTRL_REGISTER : %04x", _Value);
|
||||||
DEBUG_LOG(COMMANDPROCESSOR, "\t GPREAD %s | CPULINK %s | BP %s || BPIntEnable %s | OvF %s | UndF %s"
|
DEBUG_LOG(COMMANDPROCESSOR, "\t GPREAD %s | CPULINK %s | BP %s || BPIntEnable %s | OvF %s | UndF %s"
|
||||||
, cpreg.ctrl.GPReadEnable ? "ON" : "OFF"
|
, cpreg.ctrl.GPReadEnable ? "ON" : "OFF"
|
||||||
, cpreg.ctrl.GPLinkEnable ? "ON" : "OFF"
|
, cpreg.ctrl.GPLinkEnable ? "ON" : "OFF"
|
||||||
, cpreg.ctrl.BPEnable ? "ON" : "OFF"
|
, cpreg.ctrl.BPEnable ? "ON" : "OFF"
|
||||||
, cpreg.ctrl.BreakPointIntEnable ? "ON" : "OFF"
|
, cpreg.ctrl.BreakPointIntEnable ? "ON" : "OFF"
|
||||||
, cpreg.ctrl.FifoOverflowIntEnable ? "ON" : "OFF"
|
, cpreg.ctrl.FifoOverflowIntEnable ? "ON" : "OFF"
|
||||||
, cpreg.ctrl.FifoUnderflowIntEnable ? "ON" : "OFF"
|
, cpreg.ctrl.FifoUnderflowIntEnable ? "ON" : "OFF"
|
||||||
);
|
);
|
||||||
|
@ -178,14 +179,14 @@ void Write16(const u16 _Value, const u32 _Address)
|
||||||
|
|
||||||
case CLEAR_REGISTER:
|
case CLEAR_REGISTER:
|
||||||
{
|
{
|
||||||
UCPClearReg tmpClear(_Value);
|
UCPClearReg tmpClear(_Value);
|
||||||
|
|
||||||
if (tmpClear.ClearFifoOverflow)
|
if (tmpClear.ClearFifoOverflow)
|
||||||
cpreg.status.OverflowHiWatermark = 0;
|
cpreg.status.OverflowHiWatermark = 0;
|
||||||
if (tmpClear.ClearFifoUnderflow)
|
if (tmpClear.ClearFifoUnderflow)
|
||||||
cpreg.status.UnderflowLoWatermark = 0;
|
cpreg.status.UnderflowLoWatermark = 0;
|
||||||
|
|
||||||
INFO_LOG(COMMANDPROCESSOR,"\t write to CLEAR_REGISTER : %04x",_Value);
|
INFO_LOG(COMMANDPROCESSOR,"\t write to CLEAR_REGISTER : %04x",_Value);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -195,77 +196,77 @@ void Write16(const u16 _Value, const u32 _Address)
|
||||||
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_TOKEN_REGISTER : %04x", _Value);
|
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_TOKEN_REGISTER : %04x", _Value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FIFO_BASE_LO:
|
case FIFO_BASE_LO:
|
||||||
WriteLow ((u32 &)cpreg.fifobase, _Value & 0xFFE0);
|
WriteLow ((u32 &)cpreg.fifobase, _Value & 0xFFE0);
|
||||||
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_BASE_LO. FIFO base is : %08x", cpreg.fifobase);
|
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_BASE_LO. FIFO base is : %08x", cpreg.fifobase);
|
||||||
break;
|
break;
|
||||||
case FIFO_BASE_HI:
|
case FIFO_BASE_HI:
|
||||||
WriteHigh((u32 &)cpreg.fifobase, _Value);
|
WriteHigh((u32 &)cpreg.fifobase, _Value);
|
||||||
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_BASE_HI. FIFO base is : %08x", cpreg.fifobase);
|
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_BASE_HI. FIFO base is : %08x", cpreg.fifobase);
|
||||||
break;
|
break;
|
||||||
case FIFO_END_LO:
|
case FIFO_END_LO:
|
||||||
WriteLow ((u32 &)cpreg.fifoend, _Value & 0xFFE0);
|
WriteLow ((u32 &)cpreg.fifoend, _Value & 0xFFE0);
|
||||||
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_END_LO. FIFO end is : %08x", cpreg.fifoend);
|
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_END_LO. FIFO end is : %08x", cpreg.fifoend);
|
||||||
break;
|
break;
|
||||||
case FIFO_END_HI:
|
case FIFO_END_HI:
|
||||||
WriteHigh((u32 &)cpreg.fifoend, _Value);
|
WriteHigh((u32 &)cpreg.fifoend, _Value);
|
||||||
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_END_HI. FIFO end is : %08x", cpreg.fifoend);
|
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_END_HI. FIFO end is : %08x", cpreg.fifoend);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FIFO_WRITE_POINTER_LO:
|
case FIFO_WRITE_POINTER_LO:
|
||||||
WriteLow ((u32 &)cpreg.writeptr, _Value & 0xFFE0);
|
WriteLow ((u32 &)cpreg.writeptr, _Value & 0xFFE0);
|
||||||
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_WRITE_POINTER_LO. write ptr is : %08x", cpreg.writeptr);
|
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_WRITE_POINTER_LO. write ptr is : %08x", cpreg.writeptr);
|
||||||
break;
|
break;
|
||||||
case FIFO_WRITE_POINTER_HI:
|
case FIFO_WRITE_POINTER_HI:
|
||||||
WriteHigh ((u32 &)cpreg.writeptr, _Value);
|
WriteHigh ((u32 &)cpreg.writeptr, _Value);
|
||||||
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_WRITE_POINTER_HI. write ptr is : %08x", cpreg.writeptr);
|
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_WRITE_POINTER_HI. write ptr is : %08x", cpreg.writeptr);
|
||||||
break;
|
break;
|
||||||
case FIFO_READ_POINTER_LO:
|
case FIFO_READ_POINTER_LO:
|
||||||
WriteLow ((u32 &)cpreg.readptr, _Value & 0xFFE0);
|
WriteLow ((u32 &)cpreg.readptr, _Value & 0xFFE0);
|
||||||
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_READ_POINTER_LO. read ptr is : %08x", cpreg.readptr);
|
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_READ_POINTER_LO. read ptr is : %08x", cpreg.readptr);
|
||||||
break;
|
break;
|
||||||
case FIFO_READ_POINTER_HI:
|
case FIFO_READ_POINTER_HI:
|
||||||
WriteHigh ((u32 &)cpreg.readptr, _Value);
|
WriteHigh ((u32 &)cpreg.readptr, _Value);
|
||||||
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_READ_POINTER_HI. read ptr is : %08x", cpreg.readptr);
|
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_READ_POINTER_HI. read ptr is : %08x", cpreg.readptr);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FIFO_HI_WATERMARK_LO:
|
case FIFO_HI_WATERMARK_LO:
|
||||||
WriteLow ((u32 &)cpreg.hiwatermark, _Value);
|
WriteLow ((u32 &)cpreg.hiwatermark, _Value);
|
||||||
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_HI_WATERMARK_LO. hiwatermark is : %08x", cpreg.hiwatermark);
|
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_HI_WATERMARK_LO. hiwatermark is : %08x", cpreg.hiwatermark);
|
||||||
break;
|
break;
|
||||||
case FIFO_HI_WATERMARK_HI:
|
case FIFO_HI_WATERMARK_HI:
|
||||||
WriteHigh ((u32 &)cpreg.hiwatermark, _Value);
|
WriteHigh ((u32 &)cpreg.hiwatermark, _Value);
|
||||||
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_HI_WATERMARK_HI. hiwatermark is : %08x", cpreg.hiwatermark);
|
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_HI_WATERMARK_HI. hiwatermark is : %08x", cpreg.hiwatermark);
|
||||||
break;
|
break;
|
||||||
case FIFO_LO_WATERMARK_LO:
|
case FIFO_LO_WATERMARK_LO:
|
||||||
WriteLow ((u32 &)cpreg.lowatermark, _Value);
|
WriteLow ((u32 &)cpreg.lowatermark, _Value);
|
||||||
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_LO_WATERMARK_LO. lowatermark is : %08x", cpreg.lowatermark);
|
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_LO_WATERMARK_LO. lowatermark is : %08x", cpreg.lowatermark);
|
||||||
break;
|
break;
|
||||||
case FIFO_LO_WATERMARK_HI:
|
case FIFO_LO_WATERMARK_HI:
|
||||||
WriteHigh ((u32 &)cpreg.lowatermark, _Value);
|
WriteHigh ((u32 &)cpreg.lowatermark, _Value);
|
||||||
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_LO_WATERMARK_HI. lowatermark is : %08x", cpreg.lowatermark);
|
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_LO_WATERMARK_HI. lowatermark is : %08x", cpreg.lowatermark);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FIFO_BP_LO:
|
case FIFO_BP_LO:
|
||||||
WriteLow ((u32 &)cpreg.breakpt, _Value & 0xFFE0);
|
WriteLow ((u32 &)cpreg.breakpt, _Value & 0xFFE0);
|
||||||
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_BP_LO. breakpt is : %08x", cpreg.breakpt);
|
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_BP_LO. breakpoint is : %08x", cpreg.breakpt);
|
||||||
break;
|
break;
|
||||||
case FIFO_BP_HI:
|
case FIFO_BP_HI:
|
||||||
WriteHigh ((u32 &)cpreg.breakpt, _Value);
|
WriteHigh ((u32 &)cpreg.breakpt, _Value);
|
||||||
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_BP_HI. breakpt is : %08x", cpreg.breakpt);
|
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_BP_HI. breakpoint is : %08x", cpreg.breakpt);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FIFO_RW_DISTANCE_LO:
|
case FIFO_RW_DISTANCE_LO:
|
||||||
WriteLow ((u32 &)cpreg.rwdistance, _Value & 0xFFE0);
|
WriteLow ((u32 &)cpreg.rwdistance, _Value & 0xFFE0);
|
||||||
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_RW_DISTANCE_LO. rwdistance is : %08x", cpreg.rwdistance);
|
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_RW_DISTANCE_LO. rwdistance is : %08x", cpreg.rwdistance);
|
||||||
break;
|
break;
|
||||||
case FIFO_RW_DISTANCE_HI:
|
case FIFO_RW_DISTANCE_HI:
|
||||||
WriteHigh ((u32 &)cpreg.rwdistance, _Value);
|
WriteHigh ((u32 &)cpreg.rwdistance, _Value);
|
||||||
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_RW_DISTANCE_HI. rwdistance is : %08x", cpreg.rwdistance);
|
DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_RW_DISTANCE_HI. rwdistance is : %08x", cpreg.rwdistance);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
RunGpu();
|
RunGpu();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Read32(u32& _rReturnValue, const u32 _Address)
|
void Read32(u32& _rReturnValue, const u32 _Address)
|
||||||
|
@ -282,35 +283,35 @@ void Write32(const u32 _Data, const u32 _Address)
|
||||||
void STACKALIGN GatherPipeBursted()
|
void STACKALIGN GatherPipeBursted()
|
||||||
{
|
{
|
||||||
if (cpreg.ctrl.GPLinkEnable)
|
if (cpreg.ctrl.GPLinkEnable)
|
||||||
{
|
{
|
||||||
DEBUG_LOG(COMMANDPROCESSOR,"\t WGP burst. write thru : %08x", cpreg.writeptr);
|
DEBUG_LOG(COMMANDPROCESSOR,"\t WGP burst. write thru : %08x", cpreg.writeptr);
|
||||||
|
|
||||||
if (cpreg.writeptr == cpreg.fifoend)
|
if (cpreg.writeptr == cpreg.fifoend)
|
||||||
cpreg.writeptr = cpreg.fifobase;
|
cpreg.writeptr = cpreg.fifobase;
|
||||||
else
|
else
|
||||||
cpreg.writeptr += GATHER_PIPE_SIZE;
|
cpreg.writeptr += GATHER_PIPE_SIZE;
|
||||||
|
|
||||||
Common::AtomicAdd(cpreg.rwdistance, GATHER_PIPE_SIZE);
|
Common::AtomicAdd(cpreg.rwdistance, GATHER_PIPE_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
RunGpu();
|
RunGpu();
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdateInterrupts(u64 userdata)
|
void UpdateInterrupts(u64 userdata)
|
||||||
{
|
{
|
||||||
if (userdata)
|
if (userdata)
|
||||||
{
|
{
|
||||||
interruptSet = true;
|
interruptSet = true;
|
||||||
INFO_LOG(COMMANDPROCESSOR,"Interrupt set");
|
INFO_LOG(COMMANDPROCESSOR,"Interrupt set");
|
||||||
ProcessorInterface::SetInterrupt(INT_CAUSE_CP, true);
|
ProcessorInterface::SetInterrupt(INT_CAUSE_CP, true);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
interruptSet = false;
|
interruptSet = false;
|
||||||
INFO_LOG(COMMANDPROCESSOR,"Interrupt cleared");
|
INFO_LOG(COMMANDPROCESSOR,"Interrupt cleared");
|
||||||
ProcessorInterface::SetInterrupt(INT_CAUSE_CP, false);
|
ProcessorInterface::SetInterrupt(INT_CAUSE_CP, false);
|
||||||
}
|
}
|
||||||
interruptWaiting = false;
|
interruptWaiting = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdateInterruptsFromVideoBackend(u64 userdata)
|
void UpdateInterruptsFromVideoBackend(u64 userdata)
|
||||||
|
@ -320,136 +321,138 @@ void UpdateInterruptsFromVideoBackend(u64 userdata)
|
||||||
|
|
||||||
void ReadFifo()
|
void ReadFifo()
|
||||||
{
|
{
|
||||||
bool canRead = cpreg.readptr != cpreg.writeptr && writePos < (int)maxCommandBufferWrite;
|
bool canRead = cpreg.readptr != cpreg.writeptr && writePos < (int)maxCommandBufferWrite;
|
||||||
bool atBreakpoint = AtBreakpoint();
|
bool atBreakpoint = AtBreakpoint();
|
||||||
|
|
||||||
if (canRead && !atBreakpoint)
|
if (canRead && !atBreakpoint)
|
||||||
{
|
{
|
||||||
// read from fifo
|
// read from fifo
|
||||||
u8 *ptr = Memory::GetPointer(cpreg.readptr);
|
u8 *ptr = Memory::GetPointer(cpreg.readptr);
|
||||||
int bytesRead = 0;
|
int bytesRead = 0;
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
// copy to buffer
|
// copy to buffer
|
||||||
memcpy(&commandBuffer[writePos], ptr, GATHER_PIPE_SIZE);
|
memcpy(&commandBuffer[writePos], ptr, GATHER_PIPE_SIZE);
|
||||||
writePos += GATHER_PIPE_SIZE;
|
writePos += GATHER_PIPE_SIZE;
|
||||||
bytesRead += GATHER_PIPE_SIZE;
|
bytesRead += GATHER_PIPE_SIZE;
|
||||||
|
|
||||||
if (cpreg.readptr == cpreg.fifoend)
|
if (cpreg.readptr == cpreg.fifoend)
|
||||||
{
|
{
|
||||||
cpreg.readptr = cpreg.fifobase;
|
cpreg.readptr = cpreg.fifobase;
|
||||||
ptr = Memory::GetPointer(cpreg.readptr);
|
ptr = Memory::GetPointer(cpreg.readptr);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
cpreg.readptr += GATHER_PIPE_SIZE;
|
cpreg.readptr += GATHER_PIPE_SIZE;
|
||||||
ptr += GATHER_PIPE_SIZE;
|
ptr += GATHER_PIPE_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
canRead = cpreg.readptr != cpreg.writeptr && writePos < (int)maxCommandBufferWrite;
|
canRead = cpreg.readptr != cpreg.writeptr && writePos < (int)maxCommandBufferWrite;
|
||||||
atBreakpoint = AtBreakpoint();
|
atBreakpoint = AtBreakpoint();
|
||||||
} while (canRead && !atBreakpoint);
|
} while (canRead && !atBreakpoint);
|
||||||
|
|
||||||
Common::AtomicAdd(cpreg.rwdistance, -bytesRead);
|
Common::AtomicAdd(cpreg.rwdistance, -bytesRead);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetStatus()
|
void SetStatus()
|
||||||
{
|
{
|
||||||
// overflow check
|
// overflow check
|
||||||
if (cpreg.rwdistance > cpreg.hiwatermark)
|
if (cpreg.rwdistance > cpreg.hiwatermark)
|
||||||
cpreg.status.OverflowHiWatermark = 1;
|
cpreg.status.OverflowHiWatermark = 1;
|
||||||
|
|
||||||
// underflow check
|
// underflow check
|
||||||
if (cpreg.rwdistance < cpreg.lowatermark)
|
if (cpreg.rwdistance < cpreg.lowatermark)
|
||||||
cpreg.status.UnderflowLoWatermark = 1;
|
cpreg.status.UnderflowLoWatermark = 1;
|
||||||
|
|
||||||
// breakpoint
|
// breakpoint
|
||||||
if (cpreg.ctrl.BPEnable)
|
if (cpreg.ctrl.BPEnable)
|
||||||
{
|
{
|
||||||
if (cpreg.breakpt == cpreg.readptr)
|
if (cpreg.breakpt == cpreg.readptr)
|
||||||
{
|
{
|
||||||
if (!cpreg.status.Breakpoint)
|
if (!cpreg.status.Breakpoint)
|
||||||
INFO_LOG(COMMANDPROCESSOR, "Hit breakpoint at %x", cpreg.readptr);
|
INFO_LOG(COMMANDPROCESSOR, "Hit breakpoint at %x", cpreg.readptr);
|
||||||
cpreg.status.Breakpoint = 1;
|
cpreg.status.Breakpoint = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (cpreg.status.Breakpoint)
|
if (cpreg.status.Breakpoint)
|
||||||
INFO_LOG(COMMANDPROCESSOR, "Cleared breakpoint at %x", cpreg.readptr);
|
INFO_LOG(COMMANDPROCESSOR, "Cleared breakpoint at %x", cpreg.readptr);
|
||||||
cpreg.status.Breakpoint = 0;
|
cpreg.status.Breakpoint = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
cpreg.status.ReadIdle = cpreg.readptr == cpreg.writeptr;
|
cpreg.status.ReadIdle = cpreg.readptr == cpreg.writeptr;
|
||||||
|
|
||||||
bool bpInt = cpreg.status.Breakpoint && cpreg.ctrl.BreakPointIntEnable;
|
bool bpInt = cpreg.status.Breakpoint && cpreg.ctrl.BreakPointIntEnable;
|
||||||
bool ovfInt = cpreg.status.OverflowHiWatermark && cpreg.ctrl.FifoOverflowIntEnable;
|
bool ovfInt = cpreg.status.OverflowHiWatermark && cpreg.ctrl.FifoOverflowIntEnable;
|
||||||
bool undfInt = cpreg.status.UnderflowLoWatermark && cpreg.ctrl.FifoUnderflowIntEnable;
|
bool undfInt = cpreg.status.UnderflowLoWatermark && cpreg.ctrl.FifoUnderflowIntEnable;
|
||||||
|
|
||||||
bool interrupt = bpInt || ovfInt || undfInt;
|
bool interrupt = bpInt || ovfInt || undfInt;
|
||||||
|
|
||||||
if (interrupt != interruptSet && !interruptWaiting)
|
if (interrupt != interruptSet && !interruptWaiting)
|
||||||
{
|
{
|
||||||
u64 userdata = interrupt?1:0;
|
u64 userdata = interrupt?1:0;
|
||||||
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bCPUThread)
|
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bCPUThread)
|
||||||
{
|
{
|
||||||
interruptWaiting = true;
|
interruptWaiting = true;
|
||||||
SWCommandProcessor::UpdateInterruptsFromVideoBackend(userdata);
|
SWCommandProcessor::UpdateInterruptsFromVideoBackend(userdata);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
SWCommandProcessor::UpdateInterrupts(userdata);
|
{
|
||||||
}
|
SWCommandProcessor::UpdateInterrupts(userdata);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RunBuffer()
|
bool RunBuffer()
|
||||||
{
|
{
|
||||||
// fifo is read 32 bytes at a time
|
// fifo is read 32 bytes at a time
|
||||||
// read fifo data to internal buffer
|
// read fifo data to internal buffer
|
||||||
if (cpreg.ctrl.GPReadEnable)
|
if (cpreg.ctrl.GPReadEnable)
|
||||||
ReadFifo();
|
ReadFifo();
|
||||||
|
|
||||||
SetStatus();
|
SetStatus();
|
||||||
|
|
||||||
_dbg_assert_(COMMANDPROCESSOR, writePos >= readPos);
|
|
||||||
|
|
||||||
g_pVideoData = &commandBuffer[readPos];
|
|
||||||
|
|
||||||
u32 availableBytes = writePos - readPos;
|
_dbg_assert_(COMMANDPROCESSOR, writePos >= readPos);
|
||||||
|
|
||||||
while (OpcodeDecoder::CommandRunnable(availableBytes))
|
g_pVideoData = &commandBuffer[readPos];
|
||||||
{
|
|
||||||
cpreg.status.CommandIdle = 0;
|
|
||||||
|
|
||||||
OpcodeDecoder::Run(availableBytes);
|
u32 availableBytes = writePos - readPos;
|
||||||
|
|
||||||
// if data was read by the opcode decoder then the video data pointer changed
|
while (OpcodeDecoder::CommandRunnable(availableBytes))
|
||||||
readPos = (u32)(g_pVideoData - &commandBuffer[0]);
|
{
|
||||||
_dbg_assert_(VIDEO, writePos >= readPos);
|
cpreg.status.CommandIdle = 0;
|
||||||
availableBytes = writePos - readPos;
|
|
||||||
}
|
|
||||||
|
|
||||||
cpreg.status.CommandIdle = 1;
|
OpcodeDecoder::Run(availableBytes);
|
||||||
|
|
||||||
bool ranDecoder = false;
|
// if data was read by the opcode decoder then the video data pointer changed
|
||||||
|
readPos = (u32)(g_pVideoData - &commandBuffer[0]);
|
||||||
// move data remaing in command buffer
|
_dbg_assert_(VIDEO, writePos >= readPos);
|
||||||
if (readPos > 0)
|
availableBytes = writePos - readPos;
|
||||||
{
|
}
|
||||||
memmove(&commandBuffer[0], &commandBuffer[readPos], availableBytes);
|
|
||||||
writePos -= readPos;
|
|
||||||
readPos = 0;
|
|
||||||
|
|
||||||
ranDecoder = true;
|
cpreg.status.CommandIdle = 1;
|
||||||
}
|
|
||||||
|
|
||||||
return ranDecoder;
|
bool ranDecoder = false;
|
||||||
|
|
||||||
|
// move data remaing in command buffer
|
||||||
|
if (readPos > 0)
|
||||||
|
{
|
||||||
|
memmove(&commandBuffer[0], &commandBuffer[readPos], availableBytes);
|
||||||
|
writePos -= readPos;
|
||||||
|
readPos = 0;
|
||||||
|
|
||||||
|
ranDecoder = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ranDecoder;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetRendering(bool enabled)
|
void SetRendering(bool enabled)
|
||||||
{
|
{
|
||||||
g_bSkipCurrentFrame = !enabled;
|
g_bSkipCurrentFrame = !enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // end of namespace SWCommandProcessor
|
} // end of namespace SWCommandProcessor
|
||||||
|
|
|
@ -12,12 +12,12 @@
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official Git repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#ifndef _COMMANDPROCESSOR_H_
|
#ifndef _COMMANDPROCESSOR_H_
|
||||||
#define _COMMANDPROCESSOR_H_
|
#define _COMMANDPROCESSOR_H_
|
||||||
|
|
||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
|
|
||||||
class PointerWrap;
|
class PointerWrap;
|
||||||
|
@ -27,128 +27,128 @@ extern u8* g_pVideoData;
|
||||||
|
|
||||||
namespace SWCommandProcessor
|
namespace SWCommandProcessor
|
||||||
{
|
{
|
||||||
// internal hardware addresses
|
// internal hardware addresses
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
STATUS_REGISTER = 0x00,
|
STATUS_REGISTER = 0x00,
|
||||||
CTRL_REGISTER = 0x02,
|
CTRL_REGISTER = 0x02,
|
||||||
CLEAR_REGISTER = 0x04,
|
CLEAR_REGISTER = 0x04,
|
||||||
FIFO_TOKEN_REGISTER = 0x0E,
|
FIFO_TOKEN_REGISTER = 0x0E,
|
||||||
FIFO_BOUNDING_BOX_LEFT = 0x10,
|
FIFO_BOUNDING_BOX_LEFT = 0x10,
|
||||||
FIFO_BOUNDING_BOX_RIGHT = 0x12,
|
FIFO_BOUNDING_BOX_RIGHT = 0x12,
|
||||||
FIFO_BOUNDING_BOX_TOP = 0x14,
|
FIFO_BOUNDING_BOX_TOP = 0x14,
|
||||||
FIFO_BOUNDING_BOX_BOTTOM = 0x16,
|
FIFO_BOUNDING_BOX_BOTTOM = 0x16,
|
||||||
FIFO_BASE_LO = 0x20,
|
FIFO_BASE_LO = 0x20,
|
||||||
FIFO_BASE_HI = 0x22,
|
FIFO_BASE_HI = 0x22,
|
||||||
FIFO_END_LO = 0x24,
|
FIFO_END_LO = 0x24,
|
||||||
FIFO_END_HI = 0x26,
|
FIFO_END_HI = 0x26,
|
||||||
FIFO_HI_WATERMARK_LO = 0x28,
|
FIFO_HI_WATERMARK_LO = 0x28,
|
||||||
FIFO_HI_WATERMARK_HI = 0x2a,
|
FIFO_HI_WATERMARK_HI = 0x2a,
|
||||||
FIFO_LO_WATERMARK_LO = 0x2c,
|
FIFO_LO_WATERMARK_LO = 0x2c,
|
||||||
FIFO_LO_WATERMARK_HI = 0x2e,
|
FIFO_LO_WATERMARK_HI = 0x2e,
|
||||||
FIFO_RW_DISTANCE_LO = 0x30,
|
FIFO_RW_DISTANCE_LO = 0x30,
|
||||||
FIFO_RW_DISTANCE_HI = 0x32,
|
FIFO_RW_DISTANCE_HI = 0x32,
|
||||||
FIFO_WRITE_POINTER_LO = 0x34,
|
FIFO_WRITE_POINTER_LO = 0x34,
|
||||||
FIFO_WRITE_POINTER_HI = 0x36,
|
FIFO_WRITE_POINTER_HI = 0x36,
|
||||||
FIFO_READ_POINTER_LO = 0x38,
|
FIFO_READ_POINTER_LO = 0x38,
|
||||||
FIFO_READ_POINTER_HI = 0x3A,
|
FIFO_READ_POINTER_HI = 0x3A,
|
||||||
FIFO_BP_LO = 0x3C,
|
FIFO_BP_LO = 0x3C,
|
||||||
FIFO_BP_HI = 0x3E
|
FIFO_BP_HI = 0x3E
|
||||||
};
|
};
|
||||||
|
|
||||||
// Fifo Status Register
|
// Fifo Status Register
|
||||||
union UCPStatusReg
|
union UCPStatusReg
|
||||||
{
|
{
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
u16 OverflowHiWatermark : 1;
|
u16 OverflowHiWatermark : 1;
|
||||||
u16 UnderflowLoWatermark: 1;
|
u16 UnderflowLoWatermark: 1;
|
||||||
u16 ReadIdle : 1; // done reading
|
u16 ReadIdle : 1; // done reading
|
||||||
u16 CommandIdle : 1; // done processing commands
|
u16 CommandIdle : 1; // done processing commands
|
||||||
u16 Breakpoint : 1;
|
u16 Breakpoint : 1;
|
||||||
u16 : 11;
|
u16 : 11;
|
||||||
};
|
};
|
||||||
u16 Hex;
|
u16 Hex;
|
||||||
UCPStatusReg() {Hex = 0; }
|
UCPStatusReg() {Hex = 0; }
|
||||||
UCPStatusReg(u16 _hex) {Hex = _hex; }
|
UCPStatusReg(u16 _hex) {Hex = _hex; }
|
||||||
};
|
};
|
||||||
|
|
||||||
// Fifo Control Register
|
// Fifo Control Register
|
||||||
union UCPCtrlReg
|
union UCPCtrlReg
|
||||||
{
|
{
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
u16 GPReadEnable : 1;
|
u16 GPReadEnable : 1;
|
||||||
u16 BPEnable : 1;
|
u16 BPEnable : 1;
|
||||||
u16 FifoOverflowIntEnable : 1;
|
u16 FifoOverflowIntEnable : 1;
|
||||||
u16 FifoUnderflowIntEnable : 1;
|
u16 FifoUnderflowIntEnable : 1;
|
||||||
u16 GPLinkEnable : 1;
|
u16 GPLinkEnable : 1;
|
||||||
u16 BreakPointIntEnable : 1;
|
u16 BreakPointIntEnable : 1;
|
||||||
u16 : 10;
|
u16 : 10;
|
||||||
};
|
};
|
||||||
u16 Hex;
|
u16 Hex;
|
||||||
UCPCtrlReg() {Hex = 0; }
|
UCPCtrlReg() {Hex = 0; }
|
||||||
UCPCtrlReg(u16 _hex) {Hex = _hex; }
|
UCPCtrlReg(u16 _hex) {Hex = _hex; }
|
||||||
};
|
};
|
||||||
|
|
||||||
// Fifo Control Register
|
// Fifo Control Register
|
||||||
union UCPClearReg
|
union UCPClearReg
|
||||||
{
|
{
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
u16 ClearFifoOverflow : 1;
|
u16 ClearFifoOverflow : 1;
|
||||||
u16 ClearFifoUnderflow : 1;
|
u16 ClearFifoUnderflow : 1;
|
||||||
u16 ClearMetrices : 1;
|
u16 ClearMetrices : 1;
|
||||||
u16 : 13;
|
u16 : 13;
|
||||||
};
|
};
|
||||||
u16 Hex;
|
u16 Hex;
|
||||||
UCPClearReg() {Hex = 0; }
|
UCPClearReg() {Hex = 0; }
|
||||||
UCPClearReg(u16 _hex) {Hex = _hex; }
|
UCPClearReg(u16 _hex) {Hex = _hex; }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CPReg
|
struct CPReg
|
||||||
{
|
{
|
||||||
UCPStatusReg status; // 0x00
|
UCPStatusReg status; // 0x00
|
||||||
UCPCtrlReg ctrl; // 0x02
|
UCPCtrlReg ctrl; // 0x02
|
||||||
UCPClearReg clear; // 0x04
|
UCPClearReg clear; // 0x04
|
||||||
u32 unk0; // 0x06
|
u32 unk0; // 0x06
|
||||||
u32 unk1; // 0x0a
|
u32 unk1; // 0x0a
|
||||||
u16 token; // 0x0e
|
u16 token; // 0x0e
|
||||||
u16 bboxleft; // 0x10
|
u16 bboxleft; // 0x10
|
||||||
u16 bboxtop; // 0x12
|
u16 bboxtop; // 0x12
|
||||||
u16 bboxright; // 0x14
|
u16 bboxright; // 0x14
|
||||||
u16 bboxbottom; // 0x16
|
u16 bboxbottom; // 0x16
|
||||||
u16 unk2; // 0x18
|
u16 unk2; // 0x18
|
||||||
u32 fifobase; // 0x20
|
u32 fifobase; // 0x20
|
||||||
u32 fifoend; // 0x24
|
u32 fifoend; // 0x24
|
||||||
u32 hiwatermark; // 0x28
|
u32 hiwatermark; // 0x28
|
||||||
u32 lowatermark; // 0x2c
|
u32 lowatermark; // 0x2c
|
||||||
u32 rwdistance; // 0x30
|
u32 rwdistance; // 0x30
|
||||||
u32 writeptr; // 0x34
|
u32 writeptr; // 0x34
|
||||||
u32 readptr; // 0x38
|
u32 readptr; // 0x38
|
||||||
u32 breakpt; // 0x3c
|
u32 breakpt; // 0x3c
|
||||||
};
|
};
|
||||||
|
|
||||||
extern CPReg cpreg;
|
extern CPReg cpreg;
|
||||||
|
|
||||||
// Init
|
// Init
|
||||||
void Init();
|
void Init();
|
||||||
void Shutdown();
|
void Shutdown();
|
||||||
void DoState(PointerWrap &p);
|
void DoState(PointerWrap &p);
|
||||||
|
|
||||||
bool RunBuffer();
|
bool RunBuffer();
|
||||||
void RunGpu();
|
void RunGpu();
|
||||||
|
|
||||||
// Read
|
// Read
|
||||||
void Read16(u16& _rReturnValue, const u32 _Address);
|
void Read16(u16& _rReturnValue, const u32 _Address);
|
||||||
void Write16(const u16 _Data, const u32 _Address);
|
void Write16(const u16 _Data, const u32 _Address);
|
||||||
void Read32(u32& _rReturnValue, const u32 _Address);
|
void Read32(u32& _rReturnValue, const u32 _Address);
|
||||||
void Write32(const u32 _Data, const u32 _Address);
|
void Write32(const u32 _Data, const u32 _Address);
|
||||||
|
|
||||||
// for CGPFIFO
|
// for CGPFIFO
|
||||||
void GatherPipeBursted();
|
void GatherPipeBursted();
|
||||||
void UpdateInterrupts(u64 userdata);
|
void UpdateInterrupts(u64 userdata);
|
||||||
void UpdateInterruptsFromVideoBackend(u64 userdata);
|
void UpdateInterruptsFromVideoBackend(u64 userdata);
|
||||||
|
|
||||||
void SetRendering(bool enabled);
|
void SetRendering(bool enabled);
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official Git repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
|
|
||||||
|
@ -35,8 +35,8 @@ namespace SWPixelEngine
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
INT_CAUSE_PE_TOKEN = 0x200, // GP Token
|
INT_CAUSE_PE_TOKEN = 0x200, // GP Token
|
||||||
INT_CAUSE_PE_FINISH = 0x400, // GP Finished
|
INT_CAUSE_PE_FINISH = 0x400, // GP Finished
|
||||||
};
|
};
|
||||||
|
|
||||||
// STATE_TO_SAVE
|
// STATE_TO_SAVE
|
||||||
|
@ -50,7 +50,7 @@ static int et_SetFinishOnMainThread;
|
||||||
|
|
||||||
void DoState(PointerWrap &p)
|
void DoState(PointerWrap &p)
|
||||||
{
|
{
|
||||||
p.DoPOD(pereg);
|
p.DoPOD(pereg);
|
||||||
p.Do(g_bSignalTokenInterrupt);
|
p.Do(g_bSignalTokenInterrupt);
|
||||||
p.Do(g_bSignalFinishInterrupt);
|
p.Do(g_bSignalFinishInterrupt);
|
||||||
p.Do(et_SetTokenOnMainThread);
|
p.Do(et_SetTokenOnMainThread);
|
||||||
|
@ -64,10 +64,10 @@ void SetFinish_OnMainThread(u64 userdata, int cyclesLate);
|
||||||
|
|
||||||
void Init()
|
void Init()
|
||||||
{
|
{
|
||||||
memset(&pereg, 0, sizeof(pereg));
|
memset(&pereg, 0, sizeof(pereg));
|
||||||
|
|
||||||
et_SetTokenOnMainThread = false;
|
et_SetTokenOnMainThread = false;
|
||||||
g_bSignalFinishInterrupt = false;
|
g_bSignalFinishInterrupt = false;
|
||||||
|
|
||||||
et_SetTokenOnMainThread = CoreTiming::RegisterEvent("SetToken", SetToken_OnMainThread);
|
et_SetTokenOnMainThread = CoreTiming::RegisterEvent("SetToken", SetToken_OnMainThread);
|
||||||
et_SetFinishOnMainThread = CoreTiming::RegisterEvent("SetFinish", SetFinish_OnMainThread);
|
et_SetFinishOnMainThread = CoreTiming::RegisterEvent("SetFinish", SetFinish_OnMainThread);
|
||||||
|
@ -77,10 +77,10 @@ void Read16(u16& _uReturnValue, const u32 _iAddress)
|
||||||
{
|
{
|
||||||
DEBUG_LOG(PIXELENGINE, "(r16): 0x%08x", _iAddress);
|
DEBUG_LOG(PIXELENGINE, "(r16): 0x%08x", _iAddress);
|
||||||
|
|
||||||
u16 address = _iAddress & 0xFFF;
|
u16 address = _iAddress & 0xFFF;
|
||||||
|
|
||||||
if (address <= 0x2e)
|
if (address <= 0x2e)
|
||||||
_uReturnValue = ((u16*)&pereg)[address >> 1];
|
_uReturnValue = ((u16*)&pereg)[address >> 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
void Write32(const u32 _iValue, const u32 _iAddress)
|
void Write32(const u32 _iValue, const u32 _iAddress)
|
||||||
|
@ -92,7 +92,7 @@ void Write16(const u16 _iValue, const u32 _iAddress)
|
||||||
{
|
{
|
||||||
u16 address = _iAddress & 0xFFF;
|
u16 address = _iAddress & 0xFFF;
|
||||||
|
|
||||||
switch (address)
|
switch (address)
|
||||||
{
|
{
|
||||||
case PE_CTRL_REGISTER:
|
case PE_CTRL_REGISTER:
|
||||||
{
|
{
|
||||||
|
@ -101,7 +101,7 @@ void Write16(const u16 _iValue, const u32 _iAddress)
|
||||||
if (tmpCtrl.PEToken) g_bSignalTokenInterrupt = false;
|
if (tmpCtrl.PEToken) g_bSignalTokenInterrupt = false;
|
||||||
if (tmpCtrl.PEFinish) g_bSignalFinishInterrupt = false;
|
if (tmpCtrl.PEFinish) g_bSignalFinishInterrupt = false;
|
||||||
|
|
||||||
pereg.ctrl.PETokenEnable = tmpCtrl.PETokenEnable;
|
pereg.ctrl.PETokenEnable = tmpCtrl.PETokenEnable;
|
||||||
pereg.ctrl.PEFinishEnable = tmpCtrl.PEFinishEnable;
|
pereg.ctrl.PEFinishEnable = tmpCtrl.PEFinishEnable;
|
||||||
pereg.ctrl.PEToken = 0; // this flag is write only
|
pereg.ctrl.PEToken = 0; // this flag is write only
|
||||||
pereg.ctrl.PEFinish = 0; // this flag is write only
|
pereg.ctrl.PEFinish = 0; // this flag is write only
|
||||||
|
@ -112,7 +112,7 @@ void Write16(const u16 _iValue, const u32 _iAddress)
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (address <= 0x2e)
|
if (address <= 0x2e)
|
||||||
((u16*)&pereg)[address >> 1] = _iValue;
|
((u16*)&pereg)[address >> 1] = _iValue;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -125,13 +125,13 @@ bool AllowIdleSkipping()
|
||||||
void UpdateInterrupts()
|
void UpdateInterrupts()
|
||||||
{
|
{
|
||||||
// check if there is a token-interrupt
|
// check if there is a token-interrupt
|
||||||
if (g_bSignalTokenInterrupt & pereg.ctrl.PETokenEnable)
|
if (g_bSignalTokenInterrupt & pereg.ctrl.PETokenEnable)
|
||||||
ProcessorInterface::SetInterrupt(INT_CAUSE_PE_TOKEN, true);
|
ProcessorInterface::SetInterrupt(INT_CAUSE_PE_TOKEN, true);
|
||||||
else
|
else
|
||||||
ProcessorInterface::SetInterrupt(INT_CAUSE_PE_TOKEN, false);
|
ProcessorInterface::SetInterrupt(INT_CAUSE_PE_TOKEN, false);
|
||||||
|
|
||||||
// check if there is a finish-interrupt
|
// check if there is a finish-interrupt
|
||||||
if (g_bSignalFinishInterrupt & pereg.ctrl.PEFinishEnable)
|
if (g_bSignalFinishInterrupt & pereg.ctrl.PEFinishEnable)
|
||||||
ProcessorInterface::SetInterrupt(INT_CAUSE_PE_FINISH, true);
|
ProcessorInterface::SetInterrupt(INT_CAUSE_PE_FINISH, true);
|
||||||
else
|
else
|
||||||
ProcessorInterface::SetInterrupt(INT_CAUSE_PE_FINISH, false);
|
ProcessorInterface::SetInterrupt(INT_CAUSE_PE_FINISH, false);
|
||||||
|
@ -142,7 +142,7 @@ void UpdateInterrupts()
|
||||||
void SetToken_OnMainThread(u64 userdata, int cyclesLate)
|
void SetToken_OnMainThread(u64 userdata, int cyclesLate)
|
||||||
{
|
{
|
||||||
g_bSignalTokenInterrupt = true;
|
g_bSignalTokenInterrupt = true;
|
||||||
INFO_LOG(PIXELENGINE, "VIDEO Backend raises INT_CAUSE_PE_TOKEN (btw, token: %04x)", pereg.token);
|
INFO_LOG(PIXELENGINE, "VIDEO Backend raises INT_CAUSE_PE_TOKEN (btw, token: %04x)", pereg.token);
|
||||||
UpdateInterrupts();
|
UpdateInterrupts();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -157,7 +157,7 @@ void SetFinish_OnMainThread(u64 userdata, int cyclesLate)
|
||||||
void SetToken(const u16 _token, const int _bSetTokenAcknowledge)
|
void SetToken(const u16 _token, const int _bSetTokenAcknowledge)
|
||||||
{
|
{
|
||||||
pereg.token = _token;
|
pereg.token = _token;
|
||||||
if (_bSetTokenAcknowledge) // set token INT
|
if (_bSetTokenAcknowledge) // set token INT
|
||||||
{
|
{
|
||||||
CoreTiming::ScheduleEvent_Threadsafe(0, et_SetTokenOnMainThread,
|
CoreTiming::ScheduleEvent_Threadsafe(0, et_SetTokenOnMainThread,
|
||||||
_token | (_bSetTokenAcknowledge << 16));
|
_token | (_bSetTokenAcknowledge << 16));
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official Git repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
#ifndef _PIXELENGINE_H
|
#ifndef _PIXELENGINE_H
|
||||||
#define _PIXELENGINE_H
|
#define _PIXELENGINE_H
|
||||||
|
@ -24,20 +24,20 @@ class PointerWrap;
|
||||||
|
|
||||||
namespace SWPixelEngine
|
namespace SWPixelEngine
|
||||||
{
|
{
|
||||||
// internal hardware addresses
|
// internal hardware addresses
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
PE_ZCONF = 0x000, // Z Config
|
PE_ZCONF = 0x000, // Z Config
|
||||||
PE_ALPHACONF = 0x002, // Alpha Config
|
PE_ALPHACONF = 0x002, // Alpha Config
|
||||||
PE_DSTALPHACONF = 0x004, // Destination Alpha Config
|
PE_DSTALPHACONF = 0x004, // Destination Alpha Config
|
||||||
PE_ALPHAMODE = 0x006, // Alpha Mode Config
|
PE_ALPHAMODE = 0x006, // Alpha Mode Config
|
||||||
PE_ALPHAREAD = 0x008, // Alpha Read
|
PE_ALPHAREAD = 0x008, // Alpha Read
|
||||||
PE_CTRL_REGISTER = 0x00a, // Control
|
PE_CTRL_REGISTER = 0x00a, // Control
|
||||||
PE_TOKEN_REG = 0x00e, // Token
|
PE_TOKEN_REG = 0x00e, // Token
|
||||||
PE_BBOX_LEFT = 0x010, // Flip Left
|
PE_BBOX_LEFT = 0x010, // Flip Left
|
||||||
PE_BBOX_RIGHT = 0x012, // Flip Right
|
PE_BBOX_RIGHT = 0x012, // Flip Right
|
||||||
PE_BBOX_TOP = 0x014, // Flip Top
|
PE_BBOX_TOP = 0x014, // Flip Top
|
||||||
PE_BBOX_BOTTOM = 0x016, // Flip Bottom
|
PE_BBOX_BOTTOM = 0x016, // Flip Bottom
|
||||||
|
|
||||||
// NOTE: Order not verified
|
// NOTE: Order not verified
|
||||||
// These indicate the number of quads that are being used as input/output for each particular stage
|
// These indicate the number of quads that are being used as input/output for each particular stage
|
||||||
|
@ -53,98 +53,98 @@ namespace SWPixelEngine
|
||||||
PE_PERF_BLEND_INPUT_H = 0x2a,
|
PE_PERF_BLEND_INPUT_H = 0x2a,
|
||||||
PE_PERF_EFB_COPY_CLOCKS_L = 0x2c,
|
PE_PERF_EFB_COPY_CLOCKS_L = 0x2c,
|
||||||
PE_PERF_EFB_COPY_CLOCKS_H = 0x2e,
|
PE_PERF_EFB_COPY_CLOCKS_H = 0x2e,
|
||||||
};
|
};
|
||||||
|
|
||||||
union UPEZConfReg
|
union UPEZConfReg
|
||||||
{
|
{
|
||||||
u16 Hex;
|
u16 Hex;
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
u16 ZCompEnable : 1; // Z Comparator Enable
|
u16 ZCompEnable : 1; // Z Comparator Enable
|
||||||
u16 Function : 3;
|
u16 Function : 3;
|
||||||
u16 ZUpdEnable : 1;
|
u16 ZUpdEnable : 1;
|
||||||
u16 : 11;
|
u16 : 11;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
union UPEAlphaConfReg
|
union UPEAlphaConfReg
|
||||||
{
|
{
|
||||||
u16 Hex;
|
u16 Hex;
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
u16 BMMath : 1; // GX_BM_BLEND || GX_BM_SUBSTRACT
|
u16 BMMath : 1; // GX_BM_BLEND || GX_BM_SUBSTRACT
|
||||||
u16 BMLogic : 1; // GX_BM_LOGIC
|
u16 BMLogic : 1; // GX_BM_LOGIC
|
||||||
u16 Dither : 1;
|
u16 Dither : 1;
|
||||||
u16 ColorUpdEnable : 1;
|
u16 ColorUpdEnable : 1;
|
||||||
u16 AlphaUpdEnable : 1;
|
u16 AlphaUpdEnable : 1;
|
||||||
u16 DstFactor : 3;
|
u16 DstFactor : 3;
|
||||||
u16 SrcFactor : 3;
|
u16 SrcFactor : 3;
|
||||||
u16 Substract : 1; // Additive mode by default
|
u16 Substract : 1; // Additive mode by default
|
||||||
u16 BlendOperator : 4;
|
u16 BlendOperator : 4;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
union UPEDstAlphaConfReg
|
union UPEDstAlphaConfReg
|
||||||
{
|
{
|
||||||
u16 Hex;
|
u16 Hex;
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
u16 DstAlpha : 8;
|
u16 DstAlpha : 8;
|
||||||
u16 Enable : 1;
|
u16 Enable : 1;
|
||||||
u16 : 7;
|
u16 : 7;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
union UPEAlphaModeConfReg
|
union UPEAlphaModeConfReg
|
||||||
{
|
{
|
||||||
u16 Hex;
|
u16 Hex;
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
u16 Threshold : 8;
|
u16 Threshold : 8;
|
||||||
u16 CompareMode : 8;
|
u16 CompareMode : 8;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
union UPEAlphaReadReg
|
union UPEAlphaReadReg
|
||||||
{
|
{
|
||||||
u16 Hex;
|
u16 Hex;
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
u16 ReadMode : 3;
|
u16 ReadMode : 3;
|
||||||
u16 : 13;
|
u16 : 13;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
union UPECtrlReg
|
union UPECtrlReg
|
||||||
{
|
{
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
u16 PETokenEnable : 1;
|
u16 PETokenEnable : 1;
|
||||||
u16 PEFinishEnable : 1;
|
u16 PEFinishEnable : 1;
|
||||||
u16 PEToken : 1; // write only
|
u16 PEToken : 1; // write only
|
||||||
u16 PEFinish : 1; // write only
|
u16 PEFinish : 1; // write only
|
||||||
u16 : 12;
|
u16 : 12;
|
||||||
};
|
};
|
||||||
u16 Hex;
|
u16 Hex;
|
||||||
UPECtrlReg() {Hex = 0; }
|
UPECtrlReg() {Hex = 0; }
|
||||||
UPECtrlReg(u16 _hex) {Hex = _hex; }
|
UPECtrlReg(u16 _hex) {Hex = _hex; }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PEReg
|
struct PEReg
|
||||||
{
|
{
|
||||||
UPEZConfReg zconf;
|
UPEZConfReg zconf;
|
||||||
UPEAlphaConfReg alphaConf;
|
UPEAlphaConfReg alphaConf;
|
||||||
UPEDstAlphaConfReg dstAlpha;
|
UPEDstAlphaConfReg dstAlpha;
|
||||||
UPEAlphaModeConfReg alphaMode;
|
UPEAlphaModeConfReg alphaMode;
|
||||||
UPEAlphaReadReg alphaRead;
|
UPEAlphaReadReg alphaRead;
|
||||||
UPECtrlReg ctrl;
|
UPECtrlReg ctrl;
|
||||||
u16 unk0;
|
u16 unk0;
|
||||||
u16 token;
|
u16 token;
|
||||||
|
|
||||||
u16 boxLeft;
|
u16 boxLeft;
|
||||||
u16 boxRight;
|
u16 boxRight;
|
||||||
u16 boxTop;
|
u16 boxTop;
|
||||||
u16 boxBottom;
|
u16 boxBottom;
|
||||||
|
|
||||||
u16 perfZcompInputZcomplocLo;
|
u16 perfZcompInputZcomplocLo;
|
||||||
u16 perfZcompInputZcomplocHi;
|
u16 perfZcompInputZcomplocHi;
|
||||||
|
@ -206,24 +206,24 @@ namespace SWPixelEngine
|
||||||
if (++perfBlendInputLo == 0)
|
if (++perfBlendInputLo == 0)
|
||||||
perfBlendInputHi++;
|
perfBlendInputHi++;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
extern PEReg pereg;
|
extern PEReg pereg;
|
||||||
|
|
||||||
void Init();
|
void Init();
|
||||||
void DoState(PointerWrap &p);
|
void DoState(PointerWrap &p);
|
||||||
|
|
||||||
// Read
|
// Read
|
||||||
void Read16(u16& _uReturnValue, const u32 _iAddress);
|
void Read16(u16& _uReturnValue, const u32 _iAddress);
|
||||||
|
|
||||||
// Write
|
// Write
|
||||||
void Write16(const u16 _iValue, const u32 _iAddress);
|
void Write16(const u16 _iValue, const u32 _iAddress);
|
||||||
void Write32(const u32 _iValue, const u32 _iAddress);
|
void Write32(const u32 _iValue, const u32 _iAddress);
|
||||||
|
|
||||||
// gfx backend support
|
// gfx backend support
|
||||||
void SetToken(const u16 _token, const int _bSetTokenAcknowledge);
|
void SetToken(const u16 _token, const int _bSetTokenAcknowledge);
|
||||||
void SetFinish(void);
|
void SetFinish(void);
|
||||||
bool AllowIdleSkipping();
|
bool AllowIdleSkipping();
|
||||||
|
|
||||||
} // end of namespace SWPixelEngine
|
} // end of namespace SWPixelEngine
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official Git repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
|
@ -118,20 +118,20 @@ void SWRenderer::DrawDebugText()
|
||||||
|
|
||||||
if (g_SWVideoConfig.bShowStats)
|
if (g_SWVideoConfig.bShowStats)
|
||||||
{
|
{
|
||||||
p+=sprintf(p,"Objects: %i\n",swstats.thisFrame.numDrawnObjects);
|
p+=sprintf(p,"Objects: %i\n",swstats.thisFrame.numDrawnObjects);
|
||||||
p+=sprintf(p,"Primitives: %i\n",swstats.thisFrame.numPrimatives);
|
p+=sprintf(p,"Primitives: %i\n",swstats.thisFrame.numPrimatives);
|
||||||
p+=sprintf(p,"Vertices Loaded: %i\n",swstats.thisFrame.numVerticesLoaded);
|
p+=sprintf(p,"Vertices Loaded: %i\n",swstats.thisFrame.numVerticesLoaded);
|
||||||
|
|
||||||
p+=sprintf(p,"Triangles Input: %i\n",swstats.thisFrame.numTrianglesIn);
|
p+=sprintf(p,"Triangles Input: %i\n",swstats.thisFrame.numTrianglesIn);
|
||||||
p+=sprintf(p,"Triangles Rejected: %i\n",swstats.thisFrame.numTrianglesRejected);
|
p+=sprintf(p,"Triangles Rejected: %i\n",swstats.thisFrame.numTrianglesRejected);
|
||||||
p+=sprintf(p,"Triangles Culled: %i\n",swstats.thisFrame.numTrianglesCulled);
|
p+=sprintf(p,"Triangles Culled: %i\n",swstats.thisFrame.numTrianglesCulled);
|
||||||
p+=sprintf(p,"Triangles Clipped: %i\n",swstats.thisFrame.numTrianglesClipped);
|
p+=sprintf(p,"Triangles Clipped: %i\n",swstats.thisFrame.numTrianglesClipped);
|
||||||
p+=sprintf(p,"Triangles Drawn: %i\n",swstats.thisFrame.numTrianglesDrawn);
|
p+=sprintf(p,"Triangles Drawn: %i\n",swstats.thisFrame.numTrianglesDrawn);
|
||||||
|
|
||||||
p+=sprintf(p,"Rasterized Pix: %i\n",swstats.thisFrame.rasterizedPixels);
|
p+=sprintf(p,"Rasterized Pix: %i\n",swstats.thisFrame.rasterizedPixels);
|
||||||
p+=sprintf(p,"TEV Pix In: %i\n",swstats.thisFrame.tevPixelsIn);
|
p+=sprintf(p,"TEV Pix In: %i\n",swstats.thisFrame.tevPixelsIn);
|
||||||
p+=sprintf(p,"TEV Pix Out: %i\n",swstats.thisFrame.tevPixelsOut);
|
p+=sprintf(p,"TEV Pix Out: %i\n",swstats.thisFrame.tevPixelsOut);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render a shadow, and then the text.
|
// Render a shadow, and then the text.
|
||||||
SWRenderer::RenderText(debugtext_buffer, 21, 21, 0xDD000000);
|
SWRenderer::RenderText(debugtext_buffer, 21, 21, 0xDD000000);
|
||||||
|
@ -171,9 +171,9 @@ void SWRenderer::DrawTexture(u8 *texture, int width, int height)
|
||||||
glVertexAttribPointer(attr_tex, 2, GL_FLOAT, GL_FALSE, 0, texverts);
|
glVertexAttribPointer(attr_tex, 2, GL_FLOAT, GL_FALSE, 0, texverts);
|
||||||
glEnableVertexAttribArray(attr_pos);
|
glEnableVertexAttribArray(attr_pos);
|
||||||
glEnableVertexAttribArray(attr_tex);
|
glEnableVertexAttribArray(attr_tex);
|
||||||
glUniform1i(uni_tex, 0);
|
glUniform1i(uni_tex, 0);
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||||
glDisableVertexAttribArray(attr_pos);
|
glDisableVertexAttribArray(attr_pos);
|
||||||
glDisableVertexAttribArray(attr_tex);
|
glDisableVertexAttribArray(attr_tex);
|
||||||
|
|
||||||
|
@ -191,7 +191,7 @@ void SWRenderer::SwapBuffer()
|
||||||
glFlush();
|
glFlush();
|
||||||
|
|
||||||
GLInterface->Swap();
|
GLInterface->Swap();
|
||||||
|
|
||||||
swstats.ResetFrame();
|
swstats.ResetFrame();
|
||||||
|
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official Git repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#ifndef _RENDERER_H_
|
#ifndef _RENDERER_H_
|
||||||
|
@ -22,16 +22,16 @@
|
||||||
|
|
||||||
namespace SWRenderer
|
namespace SWRenderer
|
||||||
{
|
{
|
||||||
void Init();
|
void Init();
|
||||||
void Prepare();
|
void Prepare();
|
||||||
void Shutdown();
|
void Shutdown();
|
||||||
|
|
||||||
void RenderText(const char* pstr, int left, int top, u32 color);
|
void RenderText(const char* pstr, int left, int top, u32 color);
|
||||||
void DrawDebugText();
|
void DrawDebugText();
|
||||||
|
|
||||||
void DrawTexture(u8 *texture, int width, int height);
|
void DrawTexture(u8 *texture, int width, int height);
|
||||||
|
|
||||||
void SwapBuffer();
|
void SwapBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official Git repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#include "SWStatistics.h"
|
#include "SWStatistics.h"
|
||||||
|
@ -29,7 +29,7 @@ void Xchg(T& a, T&b)
|
||||||
|
|
||||||
SWStatistics::SWStatistics()
|
SWStatistics::SWStatistics()
|
||||||
{
|
{
|
||||||
frameCount = 0;
|
frameCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SWStatistics::ResetFrame()
|
void SWStatistics::ResetFrame()
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official Git repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#include "CommonTypes.h"
|
#include "CommonTypes.h"
|
||||||
|
@ -23,29 +23,29 @@
|
||||||
|
|
||||||
struct SWStatistics
|
struct SWStatistics
|
||||||
{
|
{
|
||||||
struct ThisFrame
|
struct ThisFrame
|
||||||
{
|
{
|
||||||
u32 numDrawnObjects;
|
u32 numDrawnObjects;
|
||||||
u32 numPrimatives;
|
u32 numPrimatives;
|
||||||
u32 numVerticesLoaded;
|
u32 numVerticesLoaded;
|
||||||
u32 numVerticesOut;
|
u32 numVerticesOut;
|
||||||
|
|
||||||
u32 numTrianglesIn;
|
u32 numTrianglesIn;
|
||||||
u32 numTrianglesRejected;
|
u32 numTrianglesRejected;
|
||||||
u32 numTrianglesCulled;
|
u32 numTrianglesCulled;
|
||||||
u32 numTrianglesClipped;
|
u32 numTrianglesClipped;
|
||||||
u32 numTrianglesDrawn;
|
u32 numTrianglesDrawn;
|
||||||
|
|
||||||
u32 rasterizedPixels;
|
u32 rasterizedPixels;
|
||||||
u32 tevPixelsIn;
|
u32 tevPixelsIn;
|
||||||
u32 tevPixelsOut;
|
u32 tevPixelsOut;
|
||||||
};
|
};
|
||||||
|
|
||||||
u32 frameCount;
|
u32 frameCount;
|
||||||
SWStatistics();
|
SWStatistics();
|
||||||
|
|
||||||
ThisFrame thisFrame;
|
ThisFrame thisFrame;
|
||||||
void ResetFrame();
|
void ResetFrame();
|
||||||
};
|
};
|
||||||
|
|
||||||
extern SWStatistics swstats;
|
extern SWStatistics swstats;
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official Git repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
|
@ -41,72 +41,74 @@ extern float tcScale[8];
|
||||||
|
|
||||||
|
|
||||||
SWVertexLoader::SWVertexLoader() :
|
SWVertexLoader::SWVertexLoader() :
|
||||||
m_VertexSize(0),
|
m_VertexSize(0),
|
||||||
m_NumAttributeLoaders(0)
|
m_NumAttributeLoaders(0)
|
||||||
{
|
{
|
||||||
VertexLoader_Normal::Init();
|
VertexLoader_Normal::Init();
|
||||||
VertexLoader_Position::Init();
|
VertexLoader_Position::Init();
|
||||||
VertexLoader_TextCoord::Init();
|
VertexLoader_TextCoord::Init();
|
||||||
|
|
||||||
m_SetupUnit = new SetupUnit;
|
m_SetupUnit = new SetupUnit;
|
||||||
}
|
}
|
||||||
|
|
||||||
SWVertexLoader::~SWVertexLoader()
|
SWVertexLoader::~SWVertexLoader()
|
||||||
{
|
{
|
||||||
delete m_SetupUnit;
|
delete m_SetupUnit;
|
||||||
m_SetupUnit = NULL;
|
m_SetupUnit = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SWVertexLoader::SetFormat(u8 attributeIndex, u8 primitiveType)
|
void SWVertexLoader::SetFormat(u8 attributeIndex, u8 primitiveType)
|
||||||
{
|
{
|
||||||
m_CurrentVat = &g_VtxAttr[attributeIndex];
|
m_CurrentVat = &g_VtxAttr[attributeIndex];
|
||||||
|
|
||||||
posScale = 1.0f / float(1 << m_CurrentVat->g0.PosFrac);
|
posScale = 1.0f / float(1 << m_CurrentVat->g0.PosFrac);
|
||||||
tcScale[0] = 1.0f / float(1 << m_CurrentVat->g0.Tex0Frac);
|
tcScale[0] = 1.0f / float(1 << m_CurrentVat->g0.Tex0Frac);
|
||||||
tcScale[1] = 1.0f / float(1 << m_CurrentVat->g1.Tex1Frac);
|
tcScale[1] = 1.0f / float(1 << m_CurrentVat->g1.Tex1Frac);
|
||||||
tcScale[2] = 1.0f / float(1 << m_CurrentVat->g1.Tex2Frac);
|
tcScale[2] = 1.0f / float(1 << m_CurrentVat->g1.Tex2Frac);
|
||||||
tcScale[3] = 1.0f / float(1 << m_CurrentVat->g1.Tex3Frac);
|
tcScale[3] = 1.0f / float(1 << m_CurrentVat->g1.Tex3Frac);
|
||||||
tcScale[4] = 1.0f / float(1 << m_CurrentVat->g2.Tex4Frac);
|
tcScale[4] = 1.0f / float(1 << m_CurrentVat->g2.Tex4Frac);
|
||||||
tcScale[5] = 1.0f / float(1 << m_CurrentVat->g2.Tex5Frac);
|
tcScale[5] = 1.0f / float(1 << m_CurrentVat->g2.Tex5Frac);
|
||||||
tcScale[6] = 1.0f / float(1 << m_CurrentVat->g2.Tex6Frac);
|
tcScale[6] = 1.0f / float(1 << m_CurrentVat->g2.Tex6Frac);
|
||||||
tcScale[7] = 1.0f / float(1 << m_CurrentVat->g2.Tex7Frac);
|
tcScale[7] = 1.0f / float(1 << m_CurrentVat->g2.Tex7Frac);
|
||||||
|
|
||||||
//TexMtx
|
//TexMtx
|
||||||
const u32 tmDesc[8] = {
|
const u32 tmDesc[8] = {
|
||||||
g_VtxDesc.Tex0MatIdx, g_VtxDesc.Tex1MatIdx, g_VtxDesc.Tex2MatIdx, g_VtxDesc.Tex3MatIdx,
|
g_VtxDesc.Tex0MatIdx, g_VtxDesc.Tex1MatIdx, g_VtxDesc.Tex2MatIdx, g_VtxDesc.Tex3MatIdx,
|
||||||
g_VtxDesc.Tex4MatIdx, g_VtxDesc.Tex5MatIdx, g_VtxDesc.Tex6MatIdx, g_VtxDesc.Tex7MatIdx
|
g_VtxDesc.Tex4MatIdx, g_VtxDesc.Tex5MatIdx, g_VtxDesc.Tex6MatIdx, g_VtxDesc.Tex7MatIdx
|
||||||
};
|
};
|
||||||
// Colors
|
|
||||||
|
// Colors
|
||||||
const u32 colDesc[2] = {g_VtxDesc.Color0, g_VtxDesc.Color1};
|
const u32 colDesc[2] = {g_VtxDesc.Color0, g_VtxDesc.Color1};
|
||||||
colElements[0] = m_CurrentVat->g0.Color0Elements;
|
colElements[0] = m_CurrentVat->g0.Color0Elements;
|
||||||
colElements[1] = m_CurrentVat->g0.Color1Elements;
|
colElements[1] = m_CurrentVat->g0.Color1Elements;
|
||||||
const u32 colComp[2] = {m_CurrentVat->g0.Color0Comp, m_CurrentVat->g0.Color1Comp};
|
const u32 colComp[2] = {m_CurrentVat->g0.Color0Comp, m_CurrentVat->g0.Color1Comp};
|
||||||
|
|
||||||
// TextureCoord
|
// TextureCoord
|
||||||
const u32 tcDesc[8] = {
|
const u32 tcDesc[8] = {
|
||||||
g_VtxDesc.Tex0Coord, g_VtxDesc.Tex1Coord, g_VtxDesc.Tex2Coord, g_VtxDesc.Tex3Coord,
|
g_VtxDesc.Tex0Coord, g_VtxDesc.Tex1Coord, g_VtxDesc.Tex2Coord, g_VtxDesc.Tex3Coord,
|
||||||
g_VtxDesc.Tex4Coord, g_VtxDesc.Tex5Coord, g_VtxDesc.Tex6Coord, (const u32)((g_VtxDesc.Hex >> 31) & 3)
|
g_VtxDesc.Tex4Coord, g_VtxDesc.Tex5Coord, g_VtxDesc.Tex6Coord, (const u32)((g_VtxDesc.Hex >> 31) & 3)
|
||||||
};
|
};
|
||||||
const u32 tcElements[8] = {
|
const u32 tcElements[8] = {
|
||||||
m_CurrentVat->g0.Tex0CoordElements, m_CurrentVat->g1.Tex1CoordElements, m_CurrentVat->g1.Tex2CoordElements,
|
m_CurrentVat->g0.Tex0CoordElements, m_CurrentVat->g1.Tex1CoordElements, m_CurrentVat->g1.Tex2CoordElements,
|
||||||
m_CurrentVat->g1.Tex3CoordElements, m_CurrentVat->g1.Tex4CoordElements, m_CurrentVat->g2.Tex5CoordElements,
|
m_CurrentVat->g1.Tex3CoordElements, m_CurrentVat->g1.Tex4CoordElements, m_CurrentVat->g2.Tex5CoordElements,
|
||||||
m_CurrentVat->g2.Tex6CoordElements, m_CurrentVat->g2.Tex7CoordElements
|
m_CurrentVat->g2.Tex6CoordElements, m_CurrentVat->g2.Tex7CoordElements
|
||||||
};
|
};
|
||||||
|
|
||||||
const u32 tcFormat[8] = {
|
const u32 tcFormat[8] = {
|
||||||
m_CurrentVat->g0.Tex0CoordFormat, m_CurrentVat->g1.Tex1CoordFormat, m_CurrentVat->g1.Tex2CoordFormat,
|
m_CurrentVat->g0.Tex0CoordFormat, m_CurrentVat->g1.Tex1CoordFormat, m_CurrentVat->g1.Tex2CoordFormat,
|
||||||
m_CurrentVat->g1.Tex3CoordFormat, m_CurrentVat->g1.Tex4CoordFormat, m_CurrentVat->g2.Tex5CoordFormat,
|
m_CurrentVat->g1.Tex3CoordFormat, m_CurrentVat->g1.Tex4CoordFormat, m_CurrentVat->g2.Tex5CoordFormat,
|
||||||
m_CurrentVat->g2.Tex6CoordFormat, m_CurrentVat->g2.Tex7CoordFormat
|
m_CurrentVat->g2.Tex6CoordFormat, m_CurrentVat->g2.Tex7CoordFormat
|
||||||
};
|
};
|
||||||
|
|
||||||
|
m_VertexSize = 0;
|
||||||
|
|
||||||
m_VertexSize = 0;
|
|
||||||
|
|
||||||
// Reset pipeline
|
// Reset pipeline
|
||||||
m_positionLoader = NULL;
|
m_positionLoader = NULL;
|
||||||
m_normalLoader = NULL;
|
m_normalLoader = NULL;
|
||||||
m_NumAttributeLoaders = 0;
|
m_NumAttributeLoaders = 0;
|
||||||
|
|
||||||
// Reset vertex
|
// Reset vertex
|
||||||
// matrix index from xf regs or cp memory?
|
// matrix index from xf regs or cp memory?
|
||||||
if (swxfregs.MatrixIndexA.PosNormalMtxIdx != MatrixIndexA.PosNormalMtxIdx ||
|
if (swxfregs.MatrixIndexA.PosNormalMtxIdx != MatrixIndexA.PosNormalMtxIdx ||
|
||||||
swxfregs.MatrixIndexA.Tex0MtxIdx != MatrixIndexA.Tex0MtxIdx ||
|
swxfregs.MatrixIndexA.Tex0MtxIdx != MatrixIndexA.Tex0MtxIdx ||
|
||||||
swxfregs.MatrixIndexA.Tex1MtxIdx != MatrixIndexA.Tex1MtxIdx ||
|
swxfregs.MatrixIndexA.Tex1MtxIdx != MatrixIndexA.Tex1MtxIdx ||
|
||||||
|
@ -126,39 +128,41 @@ void SWVertexLoader::SetFormat(u8 attributeIndex, u8 primitiveType)
|
||||||
}
|
}
|
||||||
|
|
||||||
#if(1)
|
#if(1)
|
||||||
m_Vertex.posMtx = swxfregs.MatrixIndexA.PosNormalMtxIdx;
|
m_Vertex.posMtx = swxfregs.MatrixIndexA.PosNormalMtxIdx;
|
||||||
m_Vertex.texMtx[0] = swxfregs.MatrixIndexA.Tex0MtxIdx;
|
m_Vertex.texMtx[0] = swxfregs.MatrixIndexA.Tex0MtxIdx;
|
||||||
m_Vertex.texMtx[1] = swxfregs.MatrixIndexA.Tex1MtxIdx;
|
m_Vertex.texMtx[1] = swxfregs.MatrixIndexA.Tex1MtxIdx;
|
||||||
m_Vertex.texMtx[2] = swxfregs.MatrixIndexA.Tex2MtxIdx;
|
m_Vertex.texMtx[2] = swxfregs.MatrixIndexA.Tex2MtxIdx;
|
||||||
m_Vertex.texMtx[3] = swxfregs.MatrixIndexA.Tex3MtxIdx;
|
m_Vertex.texMtx[3] = swxfregs.MatrixIndexA.Tex3MtxIdx;
|
||||||
m_Vertex.texMtx[4] = swxfregs.MatrixIndexB.Tex4MtxIdx;
|
m_Vertex.texMtx[4] = swxfregs.MatrixIndexB.Tex4MtxIdx;
|
||||||
m_Vertex.texMtx[5] = swxfregs.MatrixIndexB.Tex5MtxIdx;
|
m_Vertex.texMtx[5] = swxfregs.MatrixIndexB.Tex5MtxIdx;
|
||||||
m_Vertex.texMtx[6] = swxfregs.MatrixIndexB.Tex6MtxIdx;
|
m_Vertex.texMtx[6] = swxfregs.MatrixIndexB.Tex6MtxIdx;
|
||||||
m_Vertex.texMtx[7] = swxfregs.MatrixIndexB.Tex7MtxIdx;
|
m_Vertex.texMtx[7] = swxfregs.MatrixIndexB.Tex7MtxIdx;
|
||||||
#else
|
#else
|
||||||
m_Vertex.posMtx = MatrixIndexA.PosNormalMtxIdx;
|
m_Vertex.posMtx = MatrixIndexA.PosNormalMtxIdx;
|
||||||
m_Vertex.texMtx[0] = MatrixIndexA.Tex0MtxIdx;
|
m_Vertex.texMtx[0] = MatrixIndexA.Tex0MtxIdx;
|
||||||
m_Vertex.texMtx[1] = MatrixIndexA.Tex1MtxIdx;
|
m_Vertex.texMtx[1] = MatrixIndexA.Tex1MtxIdx;
|
||||||
m_Vertex.texMtx[2] = MatrixIndexA.Tex2MtxIdx;
|
m_Vertex.texMtx[2] = MatrixIndexA.Tex2MtxIdx;
|
||||||
m_Vertex.texMtx[3] = MatrixIndexA.Tex3MtxIdx;
|
m_Vertex.texMtx[3] = MatrixIndexA.Tex3MtxIdx;
|
||||||
m_Vertex.texMtx[4] = MatrixIndexB.Tex4MtxIdx;
|
m_Vertex.texMtx[4] = MatrixIndexB.Tex4MtxIdx;
|
||||||
m_Vertex.texMtx[5] = MatrixIndexB.Tex5MtxIdx;
|
m_Vertex.texMtx[5] = MatrixIndexB.Tex5MtxIdx;
|
||||||
m_Vertex.texMtx[6] = MatrixIndexB.Tex6MtxIdx;
|
m_Vertex.texMtx[6] = MatrixIndexB.Tex6MtxIdx;
|
||||||
m_Vertex.texMtx[7] = MatrixIndexB.Tex7MtxIdx;
|
m_Vertex.texMtx[7] = MatrixIndexB.Tex7MtxIdx;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (g_VtxDesc.PosMatIdx != NOT_PRESENT) {
|
if (g_VtxDesc.PosMatIdx != NOT_PRESENT)
|
||||||
AddAttributeLoader(LoadPosMtx);
|
{
|
||||||
m_VertexSize++;
|
AddAttributeLoader(LoadPosMtx);
|
||||||
}
|
m_VertexSize++;
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < 8; ++i) {
|
for (int i = 0; i < 8; ++i)
|
||||||
if (tmDesc[i] != NOT_PRESENT)
|
{
|
||||||
{
|
if (tmDesc[i] != NOT_PRESENT)
|
||||||
AddAttributeLoader(LoadTexMtx, i);
|
{
|
||||||
m_VertexSize++;
|
AddAttributeLoader(LoadTexMtx, i);
|
||||||
}
|
m_VertexSize++;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Write vertex position loader
|
// Write vertex position loader
|
||||||
m_positionLoader = VertexLoader_Position::GetFunction(g_VtxDesc.Position, m_CurrentVat->g0.PosFormat, m_CurrentVat->g0.PosElements);
|
m_positionLoader = VertexLoader_Position::GetFunction(g_VtxDesc.Position, m_CurrentVat->g0.PosFormat, m_CurrentVat->g0.PosElements);
|
||||||
|
@ -178,14 +182,15 @@ void SWVertexLoader::SetFormat(u8 attributeIndex, u8 primitiveType)
|
||||||
{
|
{
|
||||||
ERROR_LOG(VIDEO, "VertexLoader_Normal::GetFunction returned zero!");
|
ERROR_LOG(VIDEO, "VertexLoader_Normal::GetFunction returned zero!");
|
||||||
}
|
}
|
||||||
AddAttributeLoader(LoadNormal);
|
AddAttributeLoader(LoadNormal);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < 2; i++) {
|
for (int i = 0; i < 2; i++)
|
||||||
|
{
|
||||||
switch (colDesc[i])
|
switch (colDesc[i])
|
||||||
{
|
{
|
||||||
case NOT_PRESENT:
|
case NOT_PRESENT:
|
||||||
m_colorLoader[i] = NULL;
|
m_colorLoader[i] = NULL;
|
||||||
break;
|
break;
|
||||||
case DIRECT:
|
case DIRECT:
|
||||||
switch (colComp[i])
|
switch (colComp[i])
|
||||||
|
@ -198,7 +203,7 @@ void SWVertexLoader::SetFormat(u8 attributeIndex, u8 primitiveType)
|
||||||
case FORMAT_32B_8888: m_VertexSize += 4; m_colorLoader[i] = (Color_ReadDirect_32b_8888); break;
|
case FORMAT_32B_8888: m_VertexSize += 4; m_colorLoader[i] = (Color_ReadDirect_32b_8888); break;
|
||||||
default: _assert_(0); break;
|
default: _assert_(0); break;
|
||||||
}
|
}
|
||||||
AddAttributeLoader(LoadColor, i);
|
AddAttributeLoader(LoadColor, i);
|
||||||
break;
|
break;
|
||||||
case INDEX8:
|
case INDEX8:
|
||||||
m_VertexSize += 1;
|
m_VertexSize += 1;
|
||||||
|
@ -212,7 +217,7 @@ void SWVertexLoader::SetFormat(u8 attributeIndex, u8 primitiveType)
|
||||||
case FORMAT_32B_8888: m_colorLoader[i] = (Color_ReadIndex8_32b_8888); break;
|
case FORMAT_32B_8888: m_colorLoader[i] = (Color_ReadIndex8_32b_8888); break;
|
||||||
default: _assert_(0); break;
|
default: _assert_(0); break;
|
||||||
}
|
}
|
||||||
AddAttributeLoader(LoadColor, i);
|
AddAttributeLoader(LoadColor, i);
|
||||||
break;
|
break;
|
||||||
case INDEX16:
|
case INDEX16:
|
||||||
m_VertexSize += 2;
|
m_VertexSize += 2;
|
||||||
|
@ -226,13 +231,14 @@ void SWVertexLoader::SetFormat(u8 attributeIndex, u8 primitiveType)
|
||||||
case FORMAT_32B_8888: m_colorLoader[i] = (Color_ReadIndex16_32b_8888); break;
|
case FORMAT_32B_8888: m_colorLoader[i] = (Color_ReadIndex16_32b_8888); break;
|
||||||
default: _assert_(0); break;
|
default: _assert_(0); break;
|
||||||
}
|
}
|
||||||
AddAttributeLoader(LoadColor, i);
|
AddAttributeLoader(LoadColor, i);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Texture matrix indices (remove if corresponding texture coordinate isn't enabled)
|
// Texture matrix indices (remove if corresponding texture coordinate isn't enabled)
|
||||||
for (int i = 0; i < 8; i++) {
|
for (int i = 0; i < 8; i++)
|
||||||
|
{
|
||||||
const int desc = tcDesc[i];
|
const int desc = tcDesc[i];
|
||||||
const int format = tcFormat[i];
|
const int format = tcFormat[i];
|
||||||
const int elements = tcElements[i];
|
const int elements = tcElements[i];
|
||||||
|
@ -244,7 +250,7 @@ void SWVertexLoader::SetFormat(u8 attributeIndex, u8 primitiveType)
|
||||||
m_VertexSize += VertexLoader_TextCoord::GetSize(desc, format, elements);
|
m_VertexSize += VertexLoader_TextCoord::GetSize(desc, format, elements);
|
||||||
if (m_texCoordLoader[i])
|
if (m_texCoordLoader[i])
|
||||||
AddAttributeLoader(LoadTexCoord, i);
|
AddAttributeLoader(LoadTexCoord, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
// special case if only pos and tex coord 0 and tex coord input is AB11
|
// special case if only pos and tex coord 0 and tex coord input is AB11
|
||||||
m_TexGenSpecialCase =
|
m_TexGenSpecialCase =
|
||||||
|
@ -252,80 +258,79 @@ void SWVertexLoader::SetFormat(u8 attributeIndex, u8 primitiveType)
|
||||||
(g_VtxDesc.Tex0Coord != NOT_PRESENT) &&
|
(g_VtxDesc.Tex0Coord != NOT_PRESENT) &&
|
||||||
(swxfregs.texMtxInfo[0].projection == XF_TEXPROJ_ST);
|
(swxfregs.texMtxInfo[0].projection == XF_TEXPROJ_ST);
|
||||||
|
|
||||||
|
m_SetupUnit->Init(primitiveType);
|
||||||
m_SetupUnit->Init(primitiveType);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void SWVertexLoader::LoadVertex()
|
void SWVertexLoader::LoadVertex()
|
||||||
{
|
{
|
||||||
for (int i = 0; i < m_NumAttributeLoaders; i++)
|
for (int i = 0; i < m_NumAttributeLoaders; i++)
|
||||||
m_AttributeLoaders[i].loader(this, &m_Vertex, m_AttributeLoaders[i].index);
|
m_AttributeLoaders[i].loader(this, &m_Vertex, m_AttributeLoaders[i].index);
|
||||||
|
|
||||||
OutputVertexData* outVertex = m_SetupUnit->GetVertex();
|
OutputVertexData* outVertex = m_SetupUnit->GetVertex();
|
||||||
|
|
||||||
// transform input data
|
// transform input data
|
||||||
TransformUnit::TransformPosition(&m_Vertex, outVertex);
|
TransformUnit::TransformPosition(&m_Vertex, outVertex);
|
||||||
|
|
||||||
if (g_VtxDesc.Normal != NOT_PRESENT)
|
if (g_VtxDesc.Normal != NOT_PRESENT)
|
||||||
{
|
{
|
||||||
TransformUnit::TransformNormal(&m_Vertex, m_CurrentVat->g0.NormalElements, outVertex);
|
TransformUnit::TransformNormal(&m_Vertex, m_CurrentVat->g0.NormalElements, outVertex);
|
||||||
}
|
}
|
||||||
|
|
||||||
TransformUnit::TransformColor(&m_Vertex, outVertex);
|
TransformUnit::TransformColor(&m_Vertex, outVertex);
|
||||||
|
|
||||||
TransformUnit::TransformTexCoord(&m_Vertex, outVertex, m_TexGenSpecialCase);
|
TransformUnit::TransformTexCoord(&m_Vertex, outVertex, m_TexGenSpecialCase);
|
||||||
|
|
||||||
m_SetupUnit->SetupVertex();
|
m_SetupUnit->SetupVertex();
|
||||||
|
|
||||||
INCSTAT(swstats.thisFrame.numVerticesLoaded)
|
INCSTAT(swstats.thisFrame.numVerticesLoaded)
|
||||||
}
|
}
|
||||||
|
|
||||||
void SWVertexLoader::AddAttributeLoader(AttributeLoader loader, u8 index)
|
void SWVertexLoader::AddAttributeLoader(AttributeLoader loader, u8 index)
|
||||||
{
|
{
|
||||||
_assert_msg_(VIDEO, m_NumAttributeLoaders < 21, "Too many attribute loaders");
|
_assert_msg_(VIDEO, m_NumAttributeLoaders < 21, "Too many attribute loaders");
|
||||||
m_AttributeLoaders[m_NumAttributeLoaders].loader = loader;
|
m_AttributeLoaders[m_NumAttributeLoaders].loader = loader;
|
||||||
m_AttributeLoaders[m_NumAttributeLoaders++].index = index;
|
m_AttributeLoaders[m_NumAttributeLoaders++].index = index;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SWVertexLoader::LoadPosMtx(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 unused)
|
void SWVertexLoader::LoadPosMtx(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 unused)
|
||||||
{
|
{
|
||||||
vertex->posMtx = DataReadU8() & 0x3f;
|
vertex->posMtx = DataReadU8() & 0x3f;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SWVertexLoader::LoadTexMtx(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 index)
|
void SWVertexLoader::LoadTexMtx(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 index)
|
||||||
{
|
{
|
||||||
vertex->texMtx[index] = DataReadU8() & 0x3f;
|
vertex->texMtx[index] = DataReadU8() & 0x3f;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SWVertexLoader::LoadPosition(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 unused)
|
void SWVertexLoader::LoadPosition(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 unused)
|
||||||
{
|
{
|
||||||
VertexManager::s_pCurBufferPointer = (u8*)&vertex->position;
|
VertexManager::s_pCurBufferPointer = (u8*)&vertex->position;
|
||||||
vertexLoader->m_positionLoader();
|
vertexLoader->m_positionLoader();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SWVertexLoader::LoadNormal(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 unused)
|
void SWVertexLoader::LoadNormal(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 unused)
|
||||||
{
|
{
|
||||||
VertexManager::s_pCurBufferPointer = (u8*)&vertex->normal;
|
VertexManager::s_pCurBufferPointer = (u8*)&vertex->normal;
|
||||||
vertexLoader->m_normalLoader();
|
vertexLoader->m_normalLoader();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SWVertexLoader::LoadColor(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 index)
|
void SWVertexLoader::LoadColor(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 index)
|
||||||
{
|
{
|
||||||
u32 color;
|
u32 color;
|
||||||
VertexManager::s_pCurBufferPointer = (u8*)&color;
|
VertexManager::s_pCurBufferPointer = (u8*)&color;
|
||||||
colIndex = index;
|
colIndex = index;
|
||||||
vertexLoader->m_colorLoader[index]();
|
vertexLoader->m_colorLoader[index]();
|
||||||
|
|
||||||
// rgba -> abgr
|
// rgba -> abgr
|
||||||
*(u32*)vertex->color[index] = Common::swap32(color);
|
*(u32*)vertex->color[index] = Common::swap32(color);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SWVertexLoader::LoadTexCoord(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 index)
|
void SWVertexLoader::LoadTexCoord(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 index)
|
||||||
{
|
{
|
||||||
VertexManager::s_pCurBufferPointer = (u8*)&vertex->texCoords[index];
|
VertexManager::s_pCurBufferPointer = (u8*)&vertex->texCoords[index];
|
||||||
tcIndex = index;
|
tcIndex = index;
|
||||||
vertexLoader->m_texCoordLoader[index]();
|
vertexLoader->m_texCoordLoader[index]();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SWVertexLoader::DoState(PointerWrap &p)
|
void SWVertexLoader::DoState(PointerWrap &p)
|
||||||
|
@ -339,4 +344,4 @@ void SWVertexLoader::DoState(PointerWrap &p)
|
||||||
p.Do(m_NumAttributeLoaders);
|
p.Do(m_NumAttributeLoaders);
|
||||||
m_SetupUnit->DoState(p);
|
m_SetupUnit->DoState(p);
|
||||||
p.Do(m_TexGenSpecialCase);
|
p.Do(m_TexGenSpecialCase);
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official Git repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#ifndef _VERTEXLOADER_H_
|
#ifndef _VERTEXLOADER_H_
|
||||||
|
@ -28,48 +28,48 @@ class SetupUnit;
|
||||||
|
|
||||||
class SWVertexLoader
|
class SWVertexLoader
|
||||||
{
|
{
|
||||||
u32 m_VertexSize;
|
u32 m_VertexSize;
|
||||||
|
|
||||||
VAT* m_CurrentVat;
|
VAT* m_CurrentVat;
|
||||||
|
|
||||||
TPipelineFunction m_positionLoader;
|
|
||||||
TPipelineFunction m_normalLoader;
|
|
||||||
TPipelineFunction m_colorLoader[2];
|
|
||||||
TPipelineFunction m_texCoordLoader[8];
|
|
||||||
|
|
||||||
InputVertexData m_Vertex;
|
TPipelineFunction m_positionLoader;
|
||||||
|
TPipelineFunction m_normalLoader;
|
||||||
|
TPipelineFunction m_colorLoader[2];
|
||||||
|
TPipelineFunction m_texCoordLoader[8];
|
||||||
|
|
||||||
typedef void (*AttributeLoader)(SWVertexLoader*, InputVertexData*, u8);
|
InputVertexData m_Vertex;
|
||||||
struct AttrLoaderCall
|
|
||||||
{
|
|
||||||
AttributeLoader loader;
|
|
||||||
u8 index;
|
|
||||||
};
|
|
||||||
AttrLoaderCall m_AttributeLoaders[1+8+1+1+2+8];
|
|
||||||
int m_NumAttributeLoaders;
|
|
||||||
void AddAttributeLoader(AttributeLoader loader, u8 index=0);
|
|
||||||
|
|
||||||
// attribute loader functions
|
typedef void (*AttributeLoader)(SWVertexLoader*, InputVertexData*, u8);
|
||||||
static void LoadPosMtx(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 unused);
|
struct AttrLoaderCall
|
||||||
static void LoadTexMtx(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 index);
|
{
|
||||||
static void LoadPosition(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 unused);
|
AttributeLoader loader;
|
||||||
static void LoadNormal(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 unused);
|
u8 index;
|
||||||
static void LoadColor(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 index);
|
};
|
||||||
static void LoadTexCoord(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 index);
|
AttrLoaderCall m_AttributeLoaders[1+8+1+1+2+8];
|
||||||
|
int m_NumAttributeLoaders;
|
||||||
|
void AddAttributeLoader(AttributeLoader loader, u8 index=0);
|
||||||
|
|
||||||
SetupUnit *m_SetupUnit;
|
// attribute loader functions
|
||||||
|
static void LoadPosMtx(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 unused);
|
||||||
|
static void LoadTexMtx(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 index);
|
||||||
|
static void LoadPosition(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 unused);
|
||||||
|
static void LoadNormal(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 unused);
|
||||||
|
static void LoadColor(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 index);
|
||||||
|
static void LoadTexCoord(SWVertexLoader *vertexLoader, InputVertexData *vertex, u8 index);
|
||||||
|
|
||||||
|
SetupUnit *m_SetupUnit;
|
||||||
|
|
||||||
bool m_TexGenSpecialCase;
|
bool m_TexGenSpecialCase;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SWVertexLoader();
|
SWVertexLoader();
|
||||||
~SWVertexLoader();
|
~SWVertexLoader();
|
||||||
|
|
||||||
void SetFormat(u8 attributeIndex, u8 primitiveType);
|
void SetFormat(u8 attributeIndex, u8 primitiveType);
|
||||||
|
|
||||||
u32 GetVertexSize() { return m_VertexSize; }
|
u32 GetVertexSize() { return m_VertexSize; }
|
||||||
|
|
||||||
void LoadVertex();
|
void LoadVertex();
|
||||||
void DoState(PointerWrap &p);
|
void DoState(PointerWrap &p);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official Git repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#include "FileUtil.h"
|
#include "FileUtil.h"
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official Git repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#ifndef _VIDEOSOFTWARE_CONFIG_H_
|
#ifndef _VIDEOSOFTWARE_CONFIG_H_
|
||||||
|
@ -25,14 +25,14 @@
|
||||||
// NEVER inherit from this class.
|
// NEVER inherit from this class.
|
||||||
struct SWVideoConfig : NonCopyable
|
struct SWVideoConfig : NonCopyable
|
||||||
{
|
{
|
||||||
SWVideoConfig();
|
SWVideoConfig();
|
||||||
void Load(const char* ini_file);
|
void Load(const char* ini_file);
|
||||||
void Save(const char* ini_file);
|
void Save(const char* ini_file);
|
||||||
|
|
||||||
// General
|
// General
|
||||||
bool bFullscreen;
|
bool bFullscreen;
|
||||||
bool bHideCursor;
|
bool bHideCursor;
|
||||||
bool renderToMainframe;
|
bool renderToMainframe;
|
||||||
|
|
||||||
bool bHwRasterizer;
|
bool bHwRasterizer;
|
||||||
|
|
||||||
|
@ -40,18 +40,18 @@ struct SWVideoConfig : NonCopyable
|
||||||
bool bZComploc;
|
bool bZComploc;
|
||||||
bool bZFreeze;
|
bool bZFreeze;
|
||||||
|
|
||||||
bool bShowStats;
|
bool bShowStats;
|
||||||
|
|
||||||
bool bDumpTextures;
|
bool bDumpTextures;
|
||||||
bool bDumpObjects;
|
bool bDumpObjects;
|
||||||
bool bDumpFrames;
|
bool bDumpFrames;
|
||||||
|
|
||||||
// Debug only
|
// Debug only
|
||||||
bool bDumpTevStages;
|
bool bDumpTevStages;
|
||||||
bool bDumpTevTextureFetches;
|
bool bDumpTevTextureFetches;
|
||||||
|
|
||||||
u32 drawStart;
|
u32 drawStart;
|
||||||
u32 drawEnd;
|
u32 drawEnd;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern SWVideoConfig g_SWVideoConfig;
|
extern SWVideoConfig g_SWVideoConfig;
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official Git repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
|
|
||||||
|
@ -213,30 +213,32 @@ u32 VideoSoftware::Video_AccessEFB(EFBAccessType type, u32 x, u32 y, u32 InputDa
|
||||||
{
|
{
|
||||||
u32 value = 0;
|
u32 value = 0;
|
||||||
|
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case PEEK_Z:
|
case PEEK_Z:
|
||||||
{
|
{
|
||||||
value = EfbInterface::GetDepth(x, y);
|
value = EfbInterface::GetDepth(x, y);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case POKE_Z:
|
|
||||||
break;
|
|
||||||
case PEEK_COLOR:
|
|
||||||
{
|
|
||||||
u32 color = 0;
|
|
||||||
EfbInterface::GetColor(x, y, (u8*)&color);
|
|
||||||
|
|
||||||
// rgba to argb
|
case POKE_Z:
|
||||||
value = (color >> 8) | (color & 0xff) << 24;
|
break;
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case POKE_COLOR:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return value;
|
case PEEK_COLOR:
|
||||||
|
{
|
||||||
|
u32 color = 0;
|
||||||
|
EfbInterface::GetColor(x, y, (u8*)&color);
|
||||||
|
|
||||||
|
// rgba to argb
|
||||||
|
value = (color >> 8) | (color & 0xff) << 24;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case POKE_COLOR:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 VideoSoftware::Video_GetQueryResult(PerfQueryType type)
|
u32 VideoSoftware::Video_GetQueryResult(PerfQueryType type)
|
||||||
|
@ -256,7 +258,7 @@ bool VideoSoftware::Video_Screenshot(const char *_szFilename)
|
||||||
void VideoSoftware::Video_EnterLoop()
|
void VideoSoftware::Video_EnterLoop()
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lk(m_csSWVidOccupied);
|
std::lock_guard<std::mutex> lk(m_csSWVidOccupied);
|
||||||
fifoStateRun = true;
|
fifoStateRun = true;
|
||||||
|
|
||||||
while (fifoStateRun)
|
while (fifoStateRun)
|
||||||
{
|
{
|
||||||
|
@ -279,7 +281,7 @@ void VideoSoftware::Video_EnterLoop()
|
||||||
|
|
||||||
void VideoSoftware::Video_ExitLoop()
|
void VideoSoftware::Video_ExitLoop()
|
||||||
{
|
{
|
||||||
fifoStateRun = false;
|
fifoStateRun = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO : could use the OSD class in video common, we would need to implement the Renderer class
|
// TODO : could use the OSD class in video common, we would need to implement the Renderer class
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official Git repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#include "SetupUnit.h"
|
#include "SetupUnit.h"
|
||||||
|
@ -27,7 +27,7 @@ void SetupUnit::Init(u8 primitiveType)
|
||||||
{
|
{
|
||||||
m_PrimType = primitiveType;
|
m_PrimType = primitiveType;
|
||||||
|
|
||||||
m_VertexCounter = 0;
|
m_VertexCounter = 0;
|
||||||
m_VertPointer[0] = &m_Vertices[0];
|
m_VertPointer[0] = &m_Vertices[0];
|
||||||
m_VertPointer[1] = &m_Vertices[1];
|
m_VertPointer[1] = &m_Vertices[1];
|
||||||
m_VertPointer[2] = &m_Vertices[2];
|
m_VertPointer[2] = &m_Vertices[2];
|
||||||
|
@ -36,130 +36,130 @@ void SetupUnit::Init(u8 primitiveType)
|
||||||
|
|
||||||
void SetupUnit::SetupVertex()
|
void SetupUnit::SetupVertex()
|
||||||
{
|
{
|
||||||
switch(m_PrimType)
|
switch(m_PrimType)
|
||||||
{
|
{
|
||||||
case GX_DRAW_QUADS:
|
case GX_DRAW_QUADS:
|
||||||
SetupQuad();
|
SetupQuad();
|
||||||
break;
|
break;
|
||||||
case GX_DRAW_TRIANGLES:
|
case GX_DRAW_TRIANGLES:
|
||||||
SetupTriangle();
|
SetupTriangle();
|
||||||
break;
|
break;
|
||||||
case GX_DRAW_TRIANGLE_STRIP:
|
case GX_DRAW_TRIANGLE_STRIP:
|
||||||
SetupTriStrip();
|
SetupTriStrip();
|
||||||
break;
|
break;
|
||||||
case GX_DRAW_TRIANGLE_FAN:
|
case GX_DRAW_TRIANGLE_FAN:
|
||||||
SetupTriFan();
|
SetupTriFan();
|
||||||
break;
|
break;
|
||||||
case GX_DRAW_LINES:
|
case GX_DRAW_LINES:
|
||||||
SetupLine();
|
SetupLine();
|
||||||
break;
|
break;
|
||||||
case GX_DRAW_LINE_STRIP:
|
case GX_DRAW_LINE_STRIP:
|
||||||
SetupLineStrip();
|
SetupLineStrip();
|
||||||
break;
|
break;
|
||||||
case GX_DRAW_POINTS:
|
case GX_DRAW_POINTS:
|
||||||
SetupPoint();
|
SetupPoint();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void SetupUnit::SetupQuad()
|
void SetupUnit::SetupQuad()
|
||||||
{
|
{
|
||||||
if (m_VertexCounter < 2)
|
if (m_VertexCounter < 2)
|
||||||
{
|
{
|
||||||
m_VertexCounter++;
|
m_VertexCounter++;
|
||||||
m_VertWritePointer = m_VertPointer[m_VertexCounter];
|
m_VertWritePointer = m_VertPointer[m_VertexCounter];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Clipper::ProcessTriangle(m_VertPointer[0], m_VertPointer[1], m_VertPointer[2]);
|
Clipper::ProcessTriangle(m_VertPointer[0], m_VertPointer[1], m_VertPointer[2]);
|
||||||
|
|
||||||
m_VertexCounter++;
|
m_VertexCounter++;
|
||||||
m_VertexCounter &= 3;
|
m_VertexCounter &= 3;
|
||||||
m_VertWritePointer = &m_Vertices[m_VertexCounter & 1];
|
m_VertWritePointer = &m_Vertices[m_VertexCounter & 1];
|
||||||
OutputVertexData* temp = m_VertPointer[1];
|
OutputVertexData* temp = m_VertPointer[1];
|
||||||
m_VertPointer[1] = m_VertPointer[2];
|
m_VertPointer[1] = m_VertPointer[2];
|
||||||
m_VertPointer[2] = temp;
|
m_VertPointer[2] = temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetupUnit::SetupTriangle()
|
void SetupUnit::SetupTriangle()
|
||||||
{
|
{
|
||||||
if (m_VertexCounter < 2)
|
if (m_VertexCounter < 2)
|
||||||
{
|
{
|
||||||
m_VertexCounter++;
|
m_VertexCounter++;
|
||||||
m_VertWritePointer = m_VertPointer[m_VertexCounter];
|
m_VertWritePointer = m_VertPointer[m_VertexCounter];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Clipper::ProcessTriangle(m_VertPointer[0], m_VertPointer[1], m_VertPointer[2]);
|
Clipper::ProcessTriangle(m_VertPointer[0], m_VertPointer[1], m_VertPointer[2]);
|
||||||
|
|
||||||
m_VertexCounter = 0;
|
m_VertexCounter = 0;
|
||||||
m_VertWritePointer = m_VertPointer[0];
|
m_VertWritePointer = m_VertPointer[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetupUnit::SetupTriStrip()
|
void SetupUnit::SetupTriStrip()
|
||||||
{
|
{
|
||||||
if (m_VertexCounter < 2)
|
if (m_VertexCounter < 2)
|
||||||
{
|
{
|
||||||
m_VertexCounter++;
|
m_VertexCounter++;
|
||||||
m_VertWritePointer = m_VertPointer[m_VertexCounter];
|
m_VertWritePointer = m_VertPointer[m_VertexCounter];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Clipper::ProcessTriangle(m_VertPointer[0], m_VertPointer[1], m_VertPointer[2]);
|
Clipper::ProcessTriangle(m_VertPointer[0], m_VertPointer[1], m_VertPointer[2]);
|
||||||
|
|
||||||
m_VertexCounter++;
|
m_VertexCounter++;
|
||||||
m_VertPointer[2 - (m_VertexCounter & 1)] = m_VertPointer[0];
|
m_VertPointer[2 - (m_VertexCounter & 1)] = m_VertPointer[0];
|
||||||
m_VertWritePointer = m_VertPointer[0];
|
m_VertWritePointer = m_VertPointer[0];
|
||||||
|
|
||||||
m_VertPointer[0] = &m_Vertices[(m_VertexCounter + 1) % 3];
|
m_VertPointer[0] = &m_Vertices[(m_VertexCounter + 1) % 3];
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetupUnit::SetupTriFan()
|
void SetupUnit::SetupTriFan()
|
||||||
{
|
{
|
||||||
if (m_VertexCounter < 2)
|
if (m_VertexCounter < 2)
|
||||||
{
|
{
|
||||||
m_VertexCounter++;
|
m_VertexCounter++;
|
||||||
m_VertWritePointer = m_VertPointer[m_VertexCounter];
|
m_VertWritePointer = m_VertPointer[m_VertexCounter];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Clipper::ProcessTriangle(m_VertPointer[0], m_VertPointer[1], m_VertPointer[2]);
|
Clipper::ProcessTriangle(m_VertPointer[0], m_VertPointer[1], m_VertPointer[2]);
|
||||||
|
|
||||||
m_VertexCounter++;
|
m_VertexCounter++;
|
||||||
m_VertPointer[1] = m_VertPointer[2];
|
m_VertPointer[1] = m_VertPointer[2];
|
||||||
m_VertPointer[2] = &m_Vertices[2 - (m_VertexCounter & 1)];
|
m_VertPointer[2] = &m_Vertices[2 - (m_VertexCounter & 1)];
|
||||||
|
|
||||||
m_VertWritePointer = m_VertPointer[2];
|
m_VertWritePointer = m_VertPointer[2];
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetupUnit::SetupLine()
|
void SetupUnit::SetupLine()
|
||||||
{
|
{
|
||||||
if (m_VertexCounter < 1)
|
if (m_VertexCounter < 1)
|
||||||
{
|
{
|
||||||
m_VertexCounter++;
|
m_VertexCounter++;
|
||||||
m_VertWritePointer = m_VertPointer[m_VertexCounter];
|
m_VertWritePointer = m_VertPointer[m_VertexCounter];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Clipper::ProcessLine(m_VertPointer[0], m_VertPointer[1]);
|
Clipper::ProcessLine(m_VertPointer[0], m_VertPointer[1]);
|
||||||
|
|
||||||
m_VertexCounter = 0;
|
m_VertexCounter = 0;
|
||||||
m_VertWritePointer = m_VertPointer[0];
|
m_VertWritePointer = m_VertPointer[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetupUnit::SetupLineStrip()
|
void SetupUnit::SetupLineStrip()
|
||||||
{
|
{
|
||||||
if (m_VertexCounter < 1)
|
if (m_VertexCounter < 1)
|
||||||
{
|
{
|
||||||
m_VertexCounter++;
|
m_VertexCounter++;
|
||||||
m_VertWritePointer = m_VertPointer[m_VertexCounter];
|
m_VertWritePointer = m_VertPointer[m_VertexCounter];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_VertexCounter++;
|
m_VertexCounter++;
|
||||||
|
|
||||||
Clipper::ProcessLine(m_VertPointer[0], m_VertPointer[1]);
|
Clipper::ProcessLine(m_VertPointer[0], m_VertPointer[1]);
|
||||||
|
|
||||||
m_VertWritePointer = m_VertPointer[0];
|
m_VertWritePointer = m_VertPointer[0];
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official Git repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
|
|
||||||
|
@ -25,27 +25,27 @@
|
||||||
|
|
||||||
class SetupUnit
|
class SetupUnit
|
||||||
{
|
{
|
||||||
u8 m_PrimType;
|
u8 m_PrimType;
|
||||||
int m_VertexCounter;
|
int m_VertexCounter;
|
||||||
|
|
||||||
OutputVertexData m_Vertices[3];
|
OutputVertexData m_Vertices[3];
|
||||||
OutputVertexData *m_VertPointer[3];
|
OutputVertexData *m_VertPointer[3];
|
||||||
OutputVertexData *m_VertWritePointer;
|
OutputVertexData *m_VertWritePointer;
|
||||||
|
|
||||||
void SetupQuad();
|
void SetupQuad();
|
||||||
void SetupTriangle();
|
void SetupTriangle();
|
||||||
void SetupTriStrip();
|
void SetupTriStrip();
|
||||||
void SetupTriFan();
|
void SetupTriFan();
|
||||||
void SetupLine();
|
void SetupLine();
|
||||||
void SetupLineStrip();
|
void SetupLineStrip();
|
||||||
void SetupPoint();
|
void SetupPoint();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void Init(u8 primitiveType);
|
void Init(u8 primitiveType);
|
||||||
|
|
||||||
OutputVertexData* GetVertex() { return m_VertWritePointer; }
|
OutputVertexData* GetVertex() { return m_VertWritePointer; }
|
||||||
|
|
||||||
void SetupVertex();
|
void SetupVertex();
|
||||||
void DoState(PointerWrap &p);
|
void DoState(PointerWrap &p);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -12,7 +12,7 @@
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official Git repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#ifndef _TEV_H_
|
#ifndef _TEV_H_
|
||||||
|
@ -23,12 +23,13 @@
|
||||||
|
|
||||||
class Tev
|
class Tev
|
||||||
{
|
{
|
||||||
struct InputRegType {
|
struct InputRegType
|
||||||
unsigned a : 8;
|
{
|
||||||
unsigned b : 8;
|
unsigned a : 8;
|
||||||
unsigned c : 8;
|
unsigned b : 8;
|
||||||
signed d : 11;
|
unsigned c : 8;
|
||||||
};
|
signed d : 11;
|
||||||
|
};
|
||||||
|
|
||||||
struct TextureCoordinateType
|
struct TextureCoordinateType
|
||||||
{
|
{
|
||||||
|
@ -36,26 +37,26 @@ class Tev
|
||||||
signed t : 24;
|
signed t : 24;
|
||||||
};
|
};
|
||||||
|
|
||||||
// color order: ABGR
|
// color order: ABGR
|
||||||
s16 Reg[4][4];
|
s16 Reg[4][4];
|
||||||
s16 KonstantColors[4][4];
|
s16 KonstantColors[4][4];
|
||||||
s16 TexColor[4];
|
s16 TexColor[4];
|
||||||
s16 RasColor[4];
|
s16 RasColor[4];
|
||||||
s16 StageKonst[4];
|
s16 StageKonst[4];
|
||||||
s16 Zero16[4];
|
s16 Zero16[4];
|
||||||
|
|
||||||
s16 FixedConstants[9];
|
s16 FixedConstants[9];
|
||||||
u8 AlphaBump;
|
u8 AlphaBump;
|
||||||
u8 IndirectTex[4][4];
|
u8 IndirectTex[4][4];
|
||||||
TextureCoordinateType TexCoord;
|
TextureCoordinateType TexCoord;
|
||||||
|
|
||||||
s16 *m_ColorInputLUT[16][3];
|
s16 *m_ColorInputLUT[16][3];
|
||||||
s16 *m_AlphaInputLUT[8]; // values must point to ABGR color
|
s16 *m_AlphaInputLUT[8]; // values must point to ABGR color
|
||||||
s16 *m_KonstLUT[32][4];
|
s16 *m_KonstLUT[32][4];
|
||||||
u8 *m_RasColorLUT[8];
|
u8 *m_RasColorLUT[8];
|
||||||
s16 m_BiasLUT[4];
|
s16 m_BiasLUT[4];
|
||||||
u8 m_ScaleLShiftLUT[4];
|
u8 m_ScaleLShiftLUT[4];
|
||||||
u8 m_ScaleRShiftLUT[4];
|
u8 m_ScaleRShiftLUT[4];
|
||||||
|
|
||||||
// enumeration for color input LUT
|
// enumeration for color input LUT
|
||||||
enum
|
enum
|
||||||
|
@ -72,29 +73,29 @@ class Tev
|
||||||
INDIRECT = 32
|
INDIRECT = 32
|
||||||
};
|
};
|
||||||
|
|
||||||
void SetRasColor(int colorChan, int swaptable);
|
void SetRasColor(int colorChan, int swaptable);
|
||||||
|
|
||||||
void DrawColorRegular(TevStageCombiner::ColorCombiner &cc);
|
void DrawColorRegular(TevStageCombiner::ColorCombiner &cc);
|
||||||
void DrawColorCompare(TevStageCombiner::ColorCombiner &cc);
|
void DrawColorCompare(TevStageCombiner::ColorCombiner &cc);
|
||||||
void DrawAlphaRegular(TevStageCombiner::AlphaCombiner &ac);
|
void DrawAlphaRegular(TevStageCombiner::AlphaCombiner &ac);
|
||||||
void DrawAlphaCompare(TevStageCombiner::AlphaCombiner &ac);
|
void DrawAlphaCompare(TevStageCombiner::AlphaCombiner &ac);
|
||||||
|
|
||||||
void Indirect(unsigned int stageNum, s32 s, s32 t);
|
void Indirect(unsigned int stageNum, s32 s, s32 t);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
s32 Position[3];
|
s32 Position[3];
|
||||||
u8 Color[2][4]; // must be RGBA for correct swap table ordering
|
u8 Color[2][4]; // must be RGBA for correct swap table ordering
|
||||||
TextureCoordinateType Uv[8];
|
TextureCoordinateType Uv[8];
|
||||||
s32 IndirectLod[4];
|
s32 IndirectLod[4];
|
||||||
bool IndirectLinear[4];
|
bool IndirectLinear[4];
|
||||||
s32 TextureLod[16];
|
s32 TextureLod[16];
|
||||||
bool TextureLinear[16];
|
bool TextureLinear[16];
|
||||||
|
|
||||||
void Init();
|
void Init();
|
||||||
|
|
||||||
void Draw();
|
void Draw();
|
||||||
|
|
||||||
void SetRegColor(int reg, int comp, bool konst, s16 color);
|
void SetRegColor(int reg, int comp, bool konst, s16 color);
|
||||||
|
|
||||||
enum { ALP_C, BLU_C, GRN_C, RED_C };
|
enum { ALP_C, BLU_C, GRN_C, RED_C };
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -12,7 +12,7 @@
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official Git repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@
|
||||||
|
|
||||||
namespace TextureEncoder
|
namespace TextureEncoder
|
||||||
{
|
{
|
||||||
void Encode(u8 *dest_ptr);
|
void Encode(u8 *dest_ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official Git repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
|
|
||||||
|
@ -30,51 +30,51 @@ namespace TextureSampler
|
||||||
|
|
||||||
inline void WrapCoord(int &coord, int wrapMode, int imageSize)
|
inline void WrapCoord(int &coord, int wrapMode, int imageSize)
|
||||||
{
|
{
|
||||||
switch (wrapMode)
|
switch (wrapMode)
|
||||||
{
|
{
|
||||||
case 0: // clamp
|
case 0: // clamp
|
||||||
coord = (coord>imageSize)?imageSize:(coord<0)?0:coord;
|
coord = (coord>imageSize)?imageSize:(coord<0)?0:coord;
|
||||||
break;
|
break;
|
||||||
case 1: // wrap
|
case 1: // wrap
|
||||||
coord = coord % (imageSize + 1);
|
coord = coord % (imageSize + 1);
|
||||||
coord = (coord<0)?imageSize+coord:coord;
|
coord = (coord<0)?imageSize+coord:coord;
|
||||||
break;
|
break;
|
||||||
case 2: // mirror
|
case 2: // mirror
|
||||||
{
|
{
|
||||||
int sizePlus1 = imageSize + 1;
|
int sizePlus1 = imageSize + 1;
|
||||||
int div = coord / sizePlus1;
|
int div = coord / sizePlus1;
|
||||||
coord = coord - (div * sizePlus1);
|
coord = coord - (div * sizePlus1);
|
||||||
coord = (coord<0)?-coord:coord;
|
coord = (coord<0)?-coord:coord;
|
||||||
coord = (div&1)?imageSize - coord:coord;
|
coord = (div&1)?imageSize - coord:coord;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void SetTexel(u8 *inTexel, u32 *outTexel, u32 fract)
|
inline void SetTexel(u8 *inTexel, u32 *outTexel, u32 fract)
|
||||||
{
|
{
|
||||||
outTexel[0] = inTexel[0] * fract;
|
outTexel[0] = inTexel[0] * fract;
|
||||||
outTexel[1] = inTexel[1] * fract;
|
outTexel[1] = inTexel[1] * fract;
|
||||||
outTexel[2] = inTexel[2] * fract;
|
outTexel[2] = inTexel[2] * fract;
|
||||||
outTexel[3] = inTexel[3] * fract;
|
outTexel[3] = inTexel[3] * fract;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void AddTexel(u8 *inTexel, u32 *outTexel, u32 fract)
|
inline void AddTexel(u8 *inTexel, u32 *outTexel, u32 fract)
|
||||||
{
|
{
|
||||||
outTexel[0] += inTexel[0] * fract;
|
outTexel[0] += inTexel[0] * fract;
|
||||||
outTexel[1] += inTexel[1] * fract;
|
outTexel[1] += inTexel[1] * fract;
|
||||||
outTexel[2] += inTexel[2] * fract;
|
outTexel[2] += inTexel[2] * fract;
|
||||||
outTexel[3] += inTexel[3] * fract;
|
outTexel[3] += inTexel[3] * fract;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sample(s32 s, s32 t, s32 lod, bool linear, u8 texmap, u8 *sample)
|
void Sample(s32 s, s32 t, s32 lod, bool linear, u8 texmap, u8 *sample)
|
||||||
{
|
{
|
||||||
int baseMip = 0;
|
int baseMip = 0;
|
||||||
bool mipLinear = false;
|
bool mipLinear = false;
|
||||||
|
|
||||||
#if (ALLOW_MIPMAP)
|
#if (ALLOW_MIPMAP)
|
||||||
FourTexUnits& texUnit = bpmem.tex[(texmap >> 2) & 1];
|
FourTexUnits& texUnit = bpmem.tex[(texmap >> 2) & 1];
|
||||||
TexMode0& tm0 = texUnit.texMode0[texmap & 3];
|
TexMode0& tm0 = texUnit.texMode0[texmap & 3];
|
||||||
|
|
||||||
s32 lodFract = lod & 0xf;
|
s32 lodFract = lod & 0xf;
|
||||||
|
|
||||||
|
@ -91,7 +91,7 @@ void Sample(s32 s, s32 t, s32 lod, bool linear, u8 texmap, u8 *sample)
|
||||||
if (mipLinear)
|
if (mipLinear)
|
||||||
{
|
{
|
||||||
u8 sampledTex[4];
|
u8 sampledTex[4];
|
||||||
u32 texel[4];
|
u32 texel[4];
|
||||||
|
|
||||||
SampleMip(s, t, baseMip, linear, texmap, sampledTex);
|
SampleMip(s, t, baseMip, linear, texmap, sampledTex);
|
||||||
SetTexel(sampledTex, texel, (16 - lodFract));
|
SetTexel(sampledTex, texel, (16 - lodFract));
|
||||||
|
@ -100,25 +100,25 @@ void Sample(s32 s, s32 t, s32 lod, bool linear, u8 texmap, u8 *sample)
|
||||||
AddTexel(sampledTex, texel, lodFract);
|
AddTexel(sampledTex, texel, lodFract);
|
||||||
|
|
||||||
sample[0] = (u8)(texel[0] >> 4);
|
sample[0] = (u8)(texel[0] >> 4);
|
||||||
sample[1] = (u8)(texel[1] >> 4);
|
sample[1] = (u8)(texel[1] >> 4);
|
||||||
sample[2] = (u8)(texel[2] >> 4);
|
sample[2] = (u8)(texel[2] >> 4);
|
||||||
sample[3] = (u8)(texel[3] >> 4);
|
sample[3] = (u8)(texel[3] >> 4);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
SampleMip(s, t, baseMip, linear, texmap, sample);
|
SampleMip(s, t, baseMip, linear, texmap, sample);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SampleMip(s32 s, s32 t, s32 mip, bool linear, u8 texmap, u8 *sample)
|
void SampleMip(s32 s, s32 t, s32 mip, bool linear, u8 texmap, u8 *sample)
|
||||||
{
|
{
|
||||||
FourTexUnits& texUnit = bpmem.tex[(texmap >> 2) & 1];
|
FourTexUnits& texUnit = bpmem.tex[(texmap >> 2) & 1];
|
||||||
u8 subTexmap = texmap & 3;
|
u8 subTexmap = texmap & 3;
|
||||||
|
|
||||||
TexMode0& tm0 = texUnit.texMode0[subTexmap];
|
TexMode0& tm0 = texUnit.texMode0[subTexmap];
|
||||||
TexImage0& ti0 = texUnit.texImage0[subTexmap];
|
TexImage0& ti0 = texUnit.texImage0[subTexmap];
|
||||||
TexTLUT& texTlut = texUnit.texTlut[subTexmap];
|
TexTLUT& texTlut = texUnit.texTlut[subTexmap];
|
||||||
|
|
||||||
u8 *imageSrc, *imageSrcOdd = NULL;
|
u8 *imageSrc, *imageSrcOdd = NULL;
|
||||||
if (texUnit.texImage1[subTexmap].image_type)
|
if (texUnit.texImage1[subTexmap].image_type)
|
||||||
|
@ -129,7 +129,7 @@ void SampleMip(s32 s, s32 t, s32 mip, bool linear, u8 texmap, u8 *sample)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
u32 imageBase = texUnit.texImage3[subTexmap].image_base << 5;
|
u32 imageBase = texUnit.texImage3[subTexmap].image_base << 5;
|
||||||
imageSrc = Memory::GetPointer(imageBase);
|
imageSrc = Memory::GetPointer(imageBase);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -167,8 +167,8 @@ void SampleMip(s32 s, s32 t, s32 mip, bool linear, u8 texmap, u8 *sample)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (linear)
|
if (linear)
|
||||||
{
|
{
|
||||||
// offset linear sampling
|
// offset linear sampling
|
||||||
s -= 64;
|
s -= 64;
|
||||||
t -= 64;
|
t -= 64;
|
||||||
|
@ -179,18 +179,18 @@ void SampleMip(s32 s, s32 t, s32 mip, bool linear, u8 texmap, u8 *sample)
|
||||||
|
|
||||||
// linear sampling
|
// linear sampling
|
||||||
int imageSPlus1 = imageS + 1;
|
int imageSPlus1 = imageS + 1;
|
||||||
int fractS = s & 0x7f;
|
int fractS = s & 0x7f;
|
||||||
|
|
||||||
int imageTPlus1 = imageT + 1;
|
|
||||||
int fractT = t & 0x7f;
|
|
||||||
|
|
||||||
u8 sampledTex[4];
|
int imageTPlus1 = imageT + 1;
|
||||||
u32 texel[4];
|
int fractT = t & 0x7f;
|
||||||
|
|
||||||
WrapCoord(imageS, tm0.wrap_s, imageWidth);
|
u8 sampledTex[4];
|
||||||
WrapCoord(imageT, tm0.wrap_t, imageHeight);
|
u32 texel[4];
|
||||||
WrapCoord(imageSPlus1, tm0.wrap_s, imageWidth);
|
|
||||||
WrapCoord(imageTPlus1, tm0.wrap_t, imageHeight);
|
WrapCoord(imageS, tm0.wrap_s, imageWidth);
|
||||||
|
WrapCoord(imageT, tm0.wrap_t, imageHeight);
|
||||||
|
WrapCoord(imageSPlus1, tm0.wrap_s, imageWidth);
|
||||||
|
WrapCoord(imageTPlus1, tm0.wrap_t, imageHeight);
|
||||||
|
|
||||||
if (!(ti0.format == GX_TF_RGBA8 && texUnit.texImage1[subTexmap].image_type))
|
if (!(ti0.format == GX_TF_RGBA8 && texUnit.texImage1[subTexmap].image_type))
|
||||||
{
|
{
|
||||||
|
@ -221,26 +221,26 @@ void SampleMip(s32 s, s32 t, s32 mip, bool linear, u8 texmap, u8 *sample)
|
||||||
AddTexel(sampledTex, texel, (fractS) * (fractT));
|
AddTexel(sampledTex, texel, (fractS) * (fractT));
|
||||||
}
|
}
|
||||||
|
|
||||||
sample[0] = (u8)(texel[0] >> 14);
|
sample[0] = (u8)(texel[0] >> 14);
|
||||||
sample[1] = (u8)(texel[1] >> 14);
|
sample[1] = (u8)(texel[1] >> 14);
|
||||||
sample[2] = (u8)(texel[2] >> 14);
|
sample[2] = (u8)(texel[2] >> 14);
|
||||||
sample[3] = (u8)(texel[3] >> 14);
|
sample[3] = (u8)(texel[3] >> 14);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// integer part of sample location
|
// integer part of sample location
|
||||||
int imageS = s >> 7;
|
int imageS = s >> 7;
|
||||||
int imageT = t >> 7;
|
int imageT = t >> 7;
|
||||||
|
|
||||||
// nearest neighbor sampling
|
// nearest neighbor sampling
|
||||||
WrapCoord(imageS, tm0.wrap_s, imageWidth);
|
WrapCoord(imageS, tm0.wrap_s, imageWidth);
|
||||||
WrapCoord(imageT, tm0.wrap_t, imageHeight);
|
WrapCoord(imageT, tm0.wrap_t, imageHeight);
|
||||||
|
|
||||||
if (!(ti0.format == GX_TF_RGBA8 && texUnit.texImage1[subTexmap].image_type))
|
if (!(ti0.format == GX_TF_RGBA8 && texUnit.texImage1[subTexmap].image_type))
|
||||||
TexDecoder_DecodeTexel(sample, imageSrc, imageS, imageT, imageWidth, ti0.format, tlutAddress, texTlut.tlut_format);
|
TexDecoder_DecodeTexel(sample, imageSrc, imageS, imageT, imageWidth, ti0.format, tlutAddress, texTlut.tlut_format);
|
||||||
else
|
else
|
||||||
TexDecoder_DecodeTexelRGBA8FromTmem(sample, imageSrc, imageSrcOdd, imageS, imageT, imageWidth);
|
TexDecoder_DecodeTexelRGBA8FromTmem(sample, imageSrc, imageSrcOdd, imageS, imageT, imageWidth);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official Git repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#ifndef _TEXTURESAMPLER_H_
|
#ifndef _TEXTURESAMPLER_H_
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official Git repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
|
@ -33,114 +33,114 @@ namespace TransformUnit
|
||||||
|
|
||||||
void MultiplyVec2Mat24(const Vec3 &vec, const float *mat, Vec3 &result)
|
void MultiplyVec2Mat24(const Vec3 &vec, const float *mat, Vec3 &result)
|
||||||
{
|
{
|
||||||
result.x = mat[0] * vec.x + mat[1] * vec.y + mat[2] + mat[3];
|
result.x = mat[0] * vec.x + mat[1] * vec.y + mat[2] + mat[3];
|
||||||
result.y = mat[4] * vec.x + mat[5] * vec.y + mat[6] + mat[7];
|
result.y = mat[4] * vec.x + mat[5] * vec.y + mat[6] + mat[7];
|
||||||
result.z = 1.0f;
|
result.z = 1.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MultiplyVec2Mat34(const Vec3 &vec, const float *mat, Vec3 &result)
|
void MultiplyVec2Mat34(const Vec3 &vec, const float *mat, Vec3 &result)
|
||||||
{
|
{
|
||||||
result.x = mat[0] * vec.x + mat[1] * vec.y + mat[2] + mat[3];
|
result.x = mat[0] * vec.x + mat[1] * vec.y + mat[2] + mat[3];
|
||||||
result.y = mat[4] * vec.x + mat[5] * vec.y + mat[6] + mat[7];
|
result.y = mat[4] * vec.x + mat[5] * vec.y + mat[6] + mat[7];
|
||||||
result.z = mat[8] * vec.x + mat[9] * vec.y + mat[10] + mat[11];
|
result.z = mat[8] * vec.x + mat[9] * vec.y + mat[10] + mat[11];
|
||||||
}
|
}
|
||||||
|
|
||||||
void MultiplyVec3Mat33(const Vec3 &vec, const float *mat, Vec3 &result)
|
void MultiplyVec3Mat33(const Vec3 &vec, const float *mat, Vec3 &result)
|
||||||
{
|
{
|
||||||
result.x = mat[0] * vec.x + mat[1] * vec.y + mat[2] * vec.z;
|
result.x = mat[0] * vec.x + mat[1] * vec.y + mat[2] * vec.z;
|
||||||
result.y = mat[3] * vec.x + mat[4] * vec.y + mat[5] * vec.z;
|
result.y = mat[3] * vec.x + mat[4] * vec.y + mat[5] * vec.z;
|
||||||
result.z = mat[6] * vec.x + mat[7] * vec.y + mat[8] * vec.z;
|
result.z = mat[6] * vec.x + mat[7] * vec.y + mat[8] * vec.z;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MultiplyVec3Mat24(const Vec3 &vec, const float *mat, Vec3 &result)
|
void MultiplyVec3Mat24(const Vec3 &vec, const float *mat, Vec3 &result)
|
||||||
{
|
{
|
||||||
result.x = mat[0] * vec.x + mat[1] * vec.y + mat[2] * vec.z + mat[3];
|
result.x = mat[0] * vec.x + mat[1] * vec.y + mat[2] * vec.z + mat[3];
|
||||||
result.y = mat[4] * vec.x + mat[5] * vec.y + mat[6] * vec.z + mat[7];
|
result.y = mat[4] * vec.x + mat[5] * vec.y + mat[6] * vec.z + mat[7];
|
||||||
result.z = 1.0f;
|
result.z = 1.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MultiplyVec3Mat34(const Vec3 &vec, const float *mat, Vec3 &result)
|
void MultiplyVec3Mat34(const Vec3 &vec, const float *mat, Vec3 &result)
|
||||||
{
|
{
|
||||||
result.x = mat[0] * vec.x + mat[1] * vec.y + mat[2] * vec.z + mat[3];
|
result.x = mat[0] * vec.x + mat[1] * vec.y + mat[2] * vec.z + mat[3];
|
||||||
result.y = mat[4] * vec.x + mat[5] * vec.y + mat[6] * vec.z + mat[7];
|
result.y = mat[4] * vec.x + mat[5] * vec.y + mat[6] * vec.z + mat[7];
|
||||||
result.z = mat[8] * vec.x + mat[9] * vec.y + mat[10] * vec.z + mat[11];
|
result.z = mat[8] * vec.x + mat[9] * vec.y + mat[10] * vec.z + mat[11];
|
||||||
}
|
}
|
||||||
|
|
||||||
void MultipleVec3Perspective(const Vec3 &vec, const float *proj, Vec4 &result)
|
void MultipleVec3Perspective(const Vec3 &vec, const float *proj, Vec4 &result)
|
||||||
{
|
{
|
||||||
result.x = proj[0] * vec.x + proj[1] * vec.z;
|
result.x = proj[0] * vec.x + proj[1] * vec.z;
|
||||||
result.y = proj[2] * vec.y + proj[3] * vec.z;
|
result.y = proj[2] * vec.y + proj[3] * vec.z;
|
||||||
//result.z = (proj[4] * vec.z + proj[5]);
|
//result.z = (proj[4] * vec.z + proj[5]);
|
||||||
result.z = (proj[4] * vec.z + proj[5]) * (1.0f - (float)1e-7);
|
result.z = (proj[4] * vec.z + proj[5]) * (1.0f - (float)1e-7);
|
||||||
result.w = -vec.z;
|
result.w = -vec.z;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MultipleVec3Ortho(const Vec3 &vec, const float *proj, Vec4 &result)
|
void MultipleVec3Ortho(const Vec3 &vec, const float *proj, Vec4 &result)
|
||||||
{
|
{
|
||||||
result.x = proj[0] * vec.x + proj[1];
|
result.x = proj[0] * vec.x + proj[1];
|
||||||
result.y = proj[2] * vec.y + proj[3];
|
result.y = proj[2] * vec.y + proj[3];
|
||||||
result.z = proj[4] * vec.z + proj[5];
|
result.z = proj[4] * vec.z + proj[5];
|
||||||
result.w = 1;
|
result.w = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TransformPosition(const InputVertexData *src, OutputVertexData *dst)
|
void TransformPosition(const InputVertexData *src, OutputVertexData *dst)
|
||||||
{
|
{
|
||||||
const float* mat = (const float*)&swxfregs.posMatrices[src->posMtx * 4];
|
const float* mat = (const float*)&swxfregs.posMatrices[src->posMtx * 4];
|
||||||
MultiplyVec3Mat34(src->position, mat, dst->mvPosition);
|
MultiplyVec3Mat34(src->position, mat, dst->mvPosition);
|
||||||
|
|
||||||
if (swxfregs.projection.type == GX_PERSPECTIVE)
|
if (swxfregs.projection.type == GX_PERSPECTIVE)
|
||||||
{
|
{
|
||||||
MultipleVec3Perspective(dst->mvPosition, swxfregs.projection.rawProjection, dst->projectedPosition);
|
MultipleVec3Perspective(dst->mvPosition, swxfregs.projection.rawProjection, dst->projectedPosition);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
MultipleVec3Ortho(dst->mvPosition, swxfregs.projection.rawProjection, dst->projectedPosition);
|
MultipleVec3Ortho(dst->mvPosition, swxfregs.projection.rawProjection, dst->projectedPosition);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TransformNormal(const InputVertexData *src, bool nbt, OutputVertexData *dst)
|
void TransformNormal(const InputVertexData *src, bool nbt, OutputVertexData *dst)
|
||||||
{
|
{
|
||||||
const float* mat = (const float*)&swxfregs.normalMatrices[(src->posMtx & 31) * 3];
|
const float* mat = (const float*)&swxfregs.normalMatrices[(src->posMtx & 31) * 3];
|
||||||
|
|
||||||
if (nbt)
|
if (nbt)
|
||||||
{
|
{
|
||||||
MultiplyVec3Mat33(src->normal[0], mat, dst->normal[0]);
|
MultiplyVec3Mat33(src->normal[0], mat, dst->normal[0]);
|
||||||
MultiplyVec3Mat33(src->normal[1], mat, dst->normal[1]);
|
MultiplyVec3Mat33(src->normal[1], mat, dst->normal[1]);
|
||||||
MultiplyVec3Mat33(src->normal[2], mat, dst->normal[2]);
|
MultiplyVec3Mat33(src->normal[2], mat, dst->normal[2]);
|
||||||
dst->normal[0].normalize();
|
dst->normal[0].normalize();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
MultiplyVec3Mat33(src->normal[0], mat, dst->normal[0]);
|
MultiplyVec3Mat33(src->normal[0], mat, dst->normal[0]);
|
||||||
dst->normal[0].normalize();
|
dst->normal[0].normalize();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TransformTexCoordRegular(const TexMtxInfo &texinfo, int coordNum, bool specialCase, const InputVertexData *srcVertex, OutputVertexData *dstVertex)
|
void TransformTexCoordRegular(const TexMtxInfo &texinfo, int coordNum, bool specialCase, const InputVertexData *srcVertex, OutputVertexData *dstVertex)
|
||||||
{
|
{
|
||||||
const Vec3 *src;
|
const Vec3 *src;
|
||||||
switch (texinfo.sourcerow)
|
switch (texinfo.sourcerow)
|
||||||
{
|
{
|
||||||
case XF_SRCGEOM_INROW:
|
case XF_SRCGEOM_INROW:
|
||||||
src = &srcVertex->position;
|
src = &srcVertex->position;
|
||||||
break;
|
break;
|
||||||
case XF_SRCNORMAL_INROW:
|
case XF_SRCNORMAL_INROW:
|
||||||
src = &srcVertex->normal[0];
|
src = &srcVertex->normal[0];
|
||||||
break;
|
break;
|
||||||
case XF_SRCBINORMAL_T_INROW:
|
case XF_SRCBINORMAL_T_INROW:
|
||||||
src = &srcVertex->normal[1];
|
src = &srcVertex->normal[1];
|
||||||
break;
|
break;
|
||||||
case XF_SRCBINORMAL_B_INROW:
|
case XF_SRCBINORMAL_B_INROW:
|
||||||
src = &srcVertex->normal[2];
|
src = &srcVertex->normal[2];
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
_assert_(texinfo.sourcerow >= XF_SRCTEX0_INROW && texinfo.sourcerow <= XF_SRCTEX7_INROW);
|
_assert_(texinfo.sourcerow >= XF_SRCTEX0_INROW && texinfo.sourcerow <= XF_SRCTEX7_INROW);
|
||||||
src = (Vec3*)srcVertex->texCoords[texinfo.sourcerow - XF_SRCTEX0_INROW];
|
src = (Vec3*)srcVertex->texCoords[texinfo.sourcerow - XF_SRCTEX0_INROW];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
const float *mat = (const float*)&swxfregs.posMatrices[srcVertex->texMtx[coordNum] * 4];
|
const float *mat = (const float*)&swxfregs.posMatrices[srcVertex->texMtx[coordNum] * 4];
|
||||||
Vec3 *dst = &dstVertex->texCoords[coordNum];
|
Vec3 *dst = &dstVertex->texCoords[coordNum];
|
||||||
|
|
||||||
if (texinfo.projection == XF_TEXPROJ_ST)
|
if (texinfo.projection == XF_TEXPROJ_ST)
|
||||||
{
|
{
|
||||||
|
@ -159,12 +159,12 @@ void TransformTexCoordRegular(const TexMtxInfo &texinfo, int coordNum, bool spec
|
||||||
MultiplyVec3Mat34(*src, mat, *dst);
|
MultiplyVec3Mat34(*src, mat, *dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (swxfregs.dualTexTrans)
|
if (swxfregs.dualTexTrans)
|
||||||
{
|
{
|
||||||
Vec3 tempCoord;
|
Vec3 tempCoord;
|
||||||
|
|
||||||
// normalize
|
// normalize
|
||||||
const PostMtxInfo &postInfo = swxfregs.postMtxInfo[coordNum];
|
const PostMtxInfo &postInfo = swxfregs.postMtxInfo[coordNum];
|
||||||
const float *postMat = (const float*)&swxfregs.postMatrices[postInfo.index * 4];
|
const float *postMat = (const float*)&swxfregs.postMatrices[postInfo.index * 4];
|
||||||
|
|
||||||
if (specialCase)
|
if (specialCase)
|
||||||
|
@ -180,7 +180,7 @@ void TransformTexCoordRegular(const TexMtxInfo &texinfo, int coordNum, bool spec
|
||||||
dst->z = 1.0f;
|
dst->z = 1.0f;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (postInfo.normalize)
|
if (postInfo.normalize)
|
||||||
tempCoord = dst->normalized();
|
tempCoord = dst->normalized();
|
||||||
else
|
else
|
||||||
|
@ -188,320 +188,336 @@ void TransformTexCoordRegular(const TexMtxInfo &texinfo, int coordNum, bool spec
|
||||||
|
|
||||||
MultiplyVec3Mat34(tempCoord, postMat, *dst);
|
MultiplyVec3Mat34(tempCoord, postMat, *dst);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct LightPointer
|
struct LightPointer
|
||||||
{
|
{
|
||||||
u32 reserved[3];
|
u32 reserved[3];
|
||||||
u8 color[4];
|
u8 color[4];
|
||||||
Vec3 cosatt;
|
Vec3 cosatt;
|
||||||
Vec3 distatt;
|
Vec3 distatt;
|
||||||
Vec3 pos;
|
Vec3 pos;
|
||||||
Vec3 dir;
|
Vec3 dir;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline void AddIntegerColor(const u8 *src, Vec3 &dst)
|
inline void AddIntegerColor(const u8 *src, Vec3 &dst)
|
||||||
{
|
{
|
||||||
dst.x += src[1];
|
dst.x += src[1];
|
||||||
dst.y += src[2];
|
dst.y += src[2];
|
||||||
dst.z += src[3];
|
dst.z += src[3];
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void AddScaledIntegerColor(const u8 *src, float scale, Vec3 &dst)
|
inline void AddScaledIntegerColor(const u8 *src, float scale, Vec3 &dst)
|
||||||
{
|
{
|
||||||
dst.x += src[1] * scale;
|
dst.x += src[1] * scale;
|
||||||
dst.y += src[2] * scale;
|
dst.y += src[2] * scale;
|
||||||
dst.z += src[3] * scale;
|
dst.z += src[3] * scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline float Clamp(float val, float a, float b)
|
inline float Clamp(float val, float a, float b)
|
||||||
{
|
{
|
||||||
return val<a?a:val>b?b:val;
|
return val<a?a:val>b?b:val;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline float SafeDivide(float n, float d)
|
inline float SafeDivide(float n, float d)
|
||||||
{
|
{
|
||||||
return (d==0)?(n>0?1:0):n/d;
|
return (d==0) ? (n>0?1:0) : n/d;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LightColor(const Vec3 &pos, const Vec3 &normal, u8 lightNum, const LitChannel &chan, Vec3 &lightCol)
|
void LightColor(const Vec3 &pos, const Vec3 &normal, u8 lightNum, const LitChannel &chan, Vec3 &lightCol)
|
||||||
{
|
{
|
||||||
const LightPointer *light = (const LightPointer*)&swxfregs.lights[0x10*lightNum];
|
const LightPointer *light = (const LightPointer*)&swxfregs.lights[0x10*lightNum];
|
||||||
|
|
||||||
if (!(chan.attnfunc & 1)) {
|
if (!(chan.attnfunc & 1))
|
||||||
// atten disabled
|
{
|
||||||
switch (chan.diffusefunc) {
|
// atten disabled
|
||||||
case LIGHTDIF_NONE:
|
switch (chan.diffusefunc)
|
||||||
AddIntegerColor(light->color, lightCol);
|
{
|
||||||
break;
|
case LIGHTDIF_NONE:
|
||||||
case LIGHTDIF_SIGN:
|
AddIntegerColor(light->color, lightCol);
|
||||||
{
|
break;
|
||||||
Vec3 ldir = (light->pos - pos).normalized();
|
case LIGHTDIF_SIGN:
|
||||||
float diffuse = ldir * normal;
|
{
|
||||||
AddScaledIntegerColor(light->color, diffuse, lightCol);
|
Vec3 ldir = (light->pos - pos).normalized();
|
||||||
}
|
float diffuse = ldir * normal;
|
||||||
break;
|
AddScaledIntegerColor(light->color, diffuse, lightCol);
|
||||||
case LIGHTDIF_CLAMP:
|
}
|
||||||
{
|
break;
|
||||||
Vec3 ldir = (light->pos - pos).normalized();
|
case LIGHTDIF_CLAMP:
|
||||||
float diffuse = max(0.0f, ldir * normal);
|
{
|
||||||
AddScaledIntegerColor(light->color, diffuse, lightCol);
|
Vec3 ldir = (light->pos - pos).normalized();
|
||||||
}
|
float diffuse = max(0.0f, ldir * normal);
|
||||||
break;
|
AddScaledIntegerColor(light->color, diffuse, lightCol);
|
||||||
default: _assert_(0);
|
}
|
||||||
}
|
break;
|
||||||
}
|
default: _assert_(0);
|
||||||
else { // spec and spot
|
}
|
||||||
// not sure about divide by zero checks
|
}
|
||||||
Vec3 ldir = light->pos - pos;
|
else // spec and spot
|
||||||
float attn;
|
{
|
||||||
|
// not sure about divide by zero checks
|
||||||
|
Vec3 ldir = light->pos - pos;
|
||||||
|
float attn;
|
||||||
|
|
||||||
if (chan.attnfunc == 3) { // spot
|
if (chan.attnfunc == 3) // spot
|
||||||
float dist2 = ldir.length2();
|
{
|
||||||
float dist = sqrtf(dist2);
|
float dist2 = ldir.length2();
|
||||||
ldir = ldir / dist;
|
float dist = sqrtf(dist2);
|
||||||
attn = max(0.0f, ldir * light->dir);
|
ldir = ldir / dist;
|
||||||
|
attn = max(0.0f, ldir * light->dir);
|
||||||
|
|
||||||
float cosAtt = light->cosatt.x + (light->cosatt.y * attn) + (light->cosatt.z * attn * attn);
|
float cosAtt = light->cosatt.x + (light->cosatt.y * attn) + (light->cosatt.z * attn * attn);
|
||||||
float distAtt = light->distatt.x + (light->distatt.y * dist) + (light->distatt.z * dist2);
|
float distAtt = light->distatt.x + (light->distatt.y * dist) + (light->distatt.z * dist2);
|
||||||
attn = SafeDivide(max(0.0f, cosAtt), distAtt);
|
attn = SafeDivide(max(0.0f, cosAtt), distAtt);
|
||||||
}
|
}
|
||||||
else if (chan.attnfunc == 1) { // specular
|
else if (chan.attnfunc == 1) // specular
|
||||||
// donko - what is going on here? 655.36 is a guess but seems about right.
|
{
|
||||||
attn = (light->pos * normal) > -655.36 ? max(0.0f, (light->dir * normal)) : 0;
|
// donko - what is going on here? 655.36 is a guess but seems about right.
|
||||||
ldir.set(1.0f, attn, attn * attn);
|
attn = (light->pos * normal) > -655.36 ? max(0.0f, (light->dir * normal)) : 0;
|
||||||
|
ldir.set(1.0f, attn, attn * attn);
|
||||||
|
|
||||||
float cosAtt = max(0.0f, light->cosatt * ldir);
|
float cosAtt = max(0.0f, light->cosatt * ldir);
|
||||||
float distAtt = light->distatt * ldir;
|
float distAtt = light->distatt * ldir;
|
||||||
attn = SafeDivide(max(0.0f, cosAtt), distAtt);
|
attn = SafeDivide(max(0.0f, cosAtt), distAtt);
|
||||||
} else {
|
}
|
||||||
PanicAlert("LightColor");
|
else
|
||||||
return;
|
{
|
||||||
}
|
PanicAlert("LightColor");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
switch (chan.diffusefunc) {
|
switch (chan.diffusefunc)
|
||||||
case LIGHTDIF_NONE:
|
{
|
||||||
AddScaledIntegerColor(light->color, attn, lightCol);
|
case LIGHTDIF_NONE:
|
||||||
break;
|
AddScaledIntegerColor(light->color, attn, lightCol);
|
||||||
case LIGHTDIF_SIGN:
|
break;
|
||||||
{
|
case LIGHTDIF_SIGN:
|
||||||
float difAttn = ldir * normal;
|
{
|
||||||
AddScaledIntegerColor(light->color, attn * difAttn, lightCol);
|
float difAttn = ldir * normal;
|
||||||
}
|
AddScaledIntegerColor(light->color, attn * difAttn, lightCol);
|
||||||
break;
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case LIGHTDIF_CLAMP:
|
case LIGHTDIF_CLAMP:
|
||||||
{
|
{
|
||||||
float difAttn = max(0.0f, ldir * normal);
|
float difAttn = max(0.0f, ldir * normal);
|
||||||
AddScaledIntegerColor(light->color, attn * difAttn, lightCol);
|
AddScaledIntegerColor(light->color, attn * difAttn, lightCol);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default: _assert_(0);
|
default: _assert_(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LightAlpha(const Vec3 &pos, const Vec3 &normal, u8 lightNum, const LitChannel &chan, float &lightCol)
|
void LightAlpha(const Vec3 &pos, const Vec3 &normal, u8 lightNum, const LitChannel &chan, float &lightCol)
|
||||||
{
|
{
|
||||||
const LightPointer *light = (const LightPointer*)&swxfregs.lights[0x10*lightNum];
|
const LightPointer *light = (const LightPointer*)&swxfregs.lights[0x10*lightNum];
|
||||||
|
|
||||||
if (!(chan.attnfunc & 1)) {
|
if (!(chan.attnfunc & 1))
|
||||||
// atten disabled
|
{
|
||||||
switch (chan.diffusefunc) {
|
// atten disabled
|
||||||
case LIGHTDIF_NONE:
|
switch (chan.diffusefunc)
|
||||||
lightCol += light->color[0];
|
{
|
||||||
break;
|
case LIGHTDIF_NONE:
|
||||||
case LIGHTDIF_SIGN:
|
lightCol += light->color[0];
|
||||||
{
|
break;
|
||||||
Vec3 ldir = (light->pos - pos).normalized();
|
case LIGHTDIF_SIGN:
|
||||||
float diffuse = ldir * normal;
|
{
|
||||||
lightCol += light->color[0] * diffuse;
|
Vec3 ldir = (light->pos - pos).normalized();
|
||||||
}
|
float diffuse = ldir * normal;
|
||||||
break;
|
lightCol += light->color[0] * diffuse;
|
||||||
case LIGHTDIF_CLAMP:
|
}
|
||||||
{
|
break;
|
||||||
Vec3 ldir = (light->pos - pos).normalized();
|
case LIGHTDIF_CLAMP:
|
||||||
float diffuse = max(0.0f, ldir * normal);
|
{
|
||||||
lightCol += light->color[0] * diffuse;
|
Vec3 ldir = (light->pos - pos).normalized();
|
||||||
}
|
float diffuse = max(0.0f, ldir * normal);
|
||||||
break;
|
lightCol += light->color[0] * diffuse;
|
||||||
default: _assert_(0);
|
}
|
||||||
}
|
break;
|
||||||
}
|
default: _assert_(0);
|
||||||
else { // spec and spot
|
}
|
||||||
Vec3 ldir = light->pos - pos;
|
}
|
||||||
float attn;
|
else // spec and spot
|
||||||
|
{
|
||||||
|
Vec3 ldir = light->pos - pos;
|
||||||
|
float attn;
|
||||||
|
|
||||||
if (chan.attnfunc == 3) { // spot
|
if (chan.attnfunc == 3) // spot
|
||||||
float dist2 = ldir.length2();
|
{
|
||||||
float dist = sqrtf(dist2);
|
float dist2 = ldir.length2();
|
||||||
ldir = ldir / dist;
|
float dist = sqrtf(dist2);
|
||||||
attn = max(0.0f, ldir * light->dir);
|
ldir = ldir / dist;
|
||||||
|
attn = max(0.0f, ldir * light->dir);
|
||||||
|
|
||||||
float cosAtt = light->cosatt.x + (light->cosatt.y * attn) + (light->cosatt.z * attn * attn);
|
float cosAtt = light->cosatt.x + (light->cosatt.y * attn) + (light->cosatt.z * attn * attn);
|
||||||
float distAtt = light->distatt.x + (light->distatt.y * dist) + (light->distatt.z * dist2);
|
float distAtt = light->distatt.x + (light->distatt.y * dist) + (light->distatt.z * dist2);
|
||||||
attn = SafeDivide(max(0.0f, cosAtt), distAtt);
|
attn = SafeDivide(max(0.0f, cosAtt), distAtt);
|
||||||
}
|
}
|
||||||
else /* if (chan.attnfunc == 1) */ { // specular
|
else /* if (chan.attnfunc == 1) */ // specular
|
||||||
// donko - what is going on here? 655.36 is a guess but seems about right.
|
{
|
||||||
attn = (light->pos * normal) > -655.36 ? max(0.0f, (light->dir * normal)) : 0;
|
// donko - what is going on here? 655.36 is a guess but seems about right.
|
||||||
ldir.set(1.0f, attn, attn * attn);
|
attn = (light->pos * normal) > -655.36 ? max(0.0f, (light->dir * normal)) : 0;
|
||||||
|
ldir.set(1.0f, attn, attn * attn);
|
||||||
|
|
||||||
float cosAtt = light->cosatt * ldir;
|
float cosAtt = light->cosatt * ldir;
|
||||||
float distAtt = light->distatt * ldir;
|
float distAtt = light->distatt * ldir;
|
||||||
attn = SafeDivide(max(0.0f, cosAtt), distAtt);
|
attn = SafeDivide(max(0.0f, cosAtt), distAtt);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (chan.diffusefunc) {
|
switch (chan.diffusefunc)
|
||||||
case LIGHTDIF_NONE:
|
{
|
||||||
lightCol += light->color[0] * attn;
|
case LIGHTDIF_NONE:
|
||||||
break;
|
lightCol += light->color[0] * attn;
|
||||||
case LIGHTDIF_SIGN:
|
break;
|
||||||
{
|
case LIGHTDIF_SIGN:
|
||||||
float difAttn = ldir * normal;
|
{
|
||||||
lightCol += light->color[0] * attn * difAttn;
|
float difAttn = ldir * normal;
|
||||||
}
|
lightCol += light->color[0] * attn * difAttn;
|
||||||
break;
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case LIGHTDIF_CLAMP:
|
case LIGHTDIF_CLAMP:
|
||||||
{
|
{
|
||||||
float difAttn = max(0.0f, ldir * normal);
|
float difAttn = max(0.0f, ldir * normal);
|
||||||
lightCol += light->color[0] * attn * difAttn;
|
lightCol += light->color[0] * attn * difAttn;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default: _assert_(0);
|
default: _assert_(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TransformColor(const InputVertexData *src, OutputVertexData *dst)
|
void TransformColor(const InputVertexData *src, OutputVertexData *dst)
|
||||||
{
|
{
|
||||||
for (u32 chan = 0; chan < swxfregs.nNumChans; chan++)
|
for (u32 chan = 0; chan < swxfregs.nNumChans; chan++)
|
||||||
{
|
{
|
||||||
// abgr
|
// abgr
|
||||||
u8 matcolor[4];
|
u8 matcolor[4];
|
||||||
u8 chancolor[4];
|
u8 chancolor[4];
|
||||||
|
|
||||||
// color
|
// color
|
||||||
LitChannel &colorchan = swxfregs.color[chan];
|
LitChannel &colorchan = swxfregs.color[chan];
|
||||||
if (colorchan.matsource)
|
if (colorchan.matsource)
|
||||||
*(u32*)matcolor = *(u32*)src->color[chan]; // vertex
|
*(u32*)matcolor = *(u32*)src->color[chan]; // vertex
|
||||||
else
|
else
|
||||||
*(u32*)matcolor = swxfregs.matColor[chan];
|
*(u32*)matcolor = swxfregs.matColor[chan];
|
||||||
|
|
||||||
if (colorchan.enablelighting)
|
if (colorchan.enablelighting)
|
||||||
{
|
{
|
||||||
Vec3 lightCol;
|
Vec3 lightCol;
|
||||||
if (colorchan.ambsource)
|
if (colorchan.ambsource)
|
||||||
{
|
{
|
||||||
// vertex
|
// vertex
|
||||||
lightCol.x = src->color[chan][1];
|
lightCol.x = src->color[chan][1];
|
||||||
lightCol.y = src->color[chan][2];
|
lightCol.y = src->color[chan][2];
|
||||||
lightCol.z = src->color[chan][3];
|
lightCol.z = src->color[chan][3];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
u8 *ambColor = (u8*)&swxfregs.ambColor[chan];
|
u8 *ambColor = (u8*)&swxfregs.ambColor[chan];
|
||||||
lightCol.x = ambColor[1];
|
lightCol.x = ambColor[1];
|
||||||
lightCol.y = ambColor[2];
|
lightCol.y = ambColor[2];
|
||||||
lightCol.z = ambColor[3];
|
lightCol.z = ambColor[3];
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 mask = colorchan.GetFullLightMask();
|
u8 mask = colorchan.GetFullLightMask();
|
||||||
for (int i = 0; i < 8; ++i) {
|
for (int i = 0; i < 8; ++i)
|
||||||
if (mask&(1<<i))
|
{
|
||||||
LightColor(dst->mvPosition, dst->normal[0], i, colorchan, lightCol);
|
if (mask&(1<<i))
|
||||||
}
|
LightColor(dst->mvPosition, dst->normal[0], i, colorchan, lightCol);
|
||||||
|
}
|
||||||
|
|
||||||
float inv = 1.0f / 255.0f;
|
float inv = 1.0f / 255.0f;
|
||||||
chancolor[1] = (u8)(matcolor[1] * Clamp(lightCol.x * inv, 0.0f, 1.0f));
|
chancolor[1] = (u8)(matcolor[1] * Clamp(lightCol.x * inv, 0.0f, 1.0f));
|
||||||
chancolor[2] = (u8)(matcolor[2] * Clamp(lightCol.y * inv, 0.0f, 1.0f));
|
chancolor[2] = (u8)(matcolor[2] * Clamp(lightCol.y * inv, 0.0f, 1.0f));
|
||||||
chancolor[3] = (u8)(matcolor[3] * Clamp(lightCol.z * inv, 0.0f, 1.0f));
|
chancolor[3] = (u8)(matcolor[3] * Clamp(lightCol.z * inv, 0.0f, 1.0f));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
*(u32*)chancolor = *(u32*)matcolor;
|
*(u32*)chancolor = *(u32*)matcolor;
|
||||||
}
|
}
|
||||||
|
|
||||||
// alpha
|
// alpha
|
||||||
LitChannel &alphachan = swxfregs.alpha[chan];
|
LitChannel &alphachan = swxfregs.alpha[chan];
|
||||||
if (alphachan.matsource)
|
if (alphachan.matsource)
|
||||||
matcolor[0] = src->color[chan][0]; // vertex
|
matcolor[0] = src->color[chan][0]; // vertex
|
||||||
else
|
else
|
||||||
matcolor[0] = swxfregs.matColor[chan] & 0xff;
|
matcolor[0] = swxfregs.matColor[chan] & 0xff;
|
||||||
|
|
||||||
if (swxfregs.alpha[chan].enablelighting)
|
if (swxfregs.alpha[chan].enablelighting)
|
||||||
{
|
{
|
||||||
float lightCol;
|
float lightCol;
|
||||||
if (alphachan.ambsource)
|
if (alphachan.ambsource)
|
||||||
lightCol = src->color[chan][0]; // vertex
|
lightCol = src->color[chan][0]; // vertex
|
||||||
else
|
else
|
||||||
lightCol = (float)(swxfregs.ambColor[chan] & 0xff);
|
lightCol = (float)(swxfregs.ambColor[chan] & 0xff);
|
||||||
|
|
||||||
u8 mask = alphachan.GetFullLightMask();
|
u8 mask = alphachan.GetFullLightMask();
|
||||||
for (int i = 0; i < 8; ++i) {
|
for (int i = 0; i < 8; ++i)
|
||||||
if (mask&(1<<i))
|
{
|
||||||
LightAlpha(dst->mvPosition, dst->normal[0], i, alphachan, lightCol);
|
if (mask&(1<<i))
|
||||||
}
|
LightAlpha(dst->mvPosition, dst->normal[0], i, alphachan, lightCol);
|
||||||
|
}
|
||||||
|
|
||||||
chancolor[0] = (u8)(matcolor[0] * Clamp(lightCol / 255.0f, 0.0f, 1.0f));
|
chancolor[0] = (u8)(matcolor[0] * Clamp(lightCol / 255.0f, 0.0f, 1.0f));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
chancolor[0] = matcolor[0];
|
chancolor[0] = matcolor[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
// abgr -> rgba
|
// abgr -> rgba
|
||||||
*(u32*)dst->color[chan] = Common::swap32(*(u32*)chancolor);
|
*(u32*)dst->color[chan] = Common::swap32(*(u32*)chancolor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TransformTexCoord(const InputVertexData *src, OutputVertexData *dst, bool specialCase)
|
void TransformTexCoord(const InputVertexData *src, OutputVertexData *dst, bool specialCase)
|
||||||
{
|
{
|
||||||
for (u32 coordNum = 0; coordNum < swxfregs.numTexGens; coordNum++)
|
for (u32 coordNum = 0; coordNum < swxfregs.numTexGens; coordNum++)
|
||||||
{
|
{
|
||||||
const TexMtxInfo &texinfo = swxfregs.texMtxInfo[coordNum];
|
const TexMtxInfo &texinfo = swxfregs.texMtxInfo[coordNum];
|
||||||
|
|
||||||
switch (texinfo.texgentype)
|
switch (texinfo.texgentype)
|
||||||
{
|
{
|
||||||
case XF_TEXGEN_REGULAR:
|
case XF_TEXGEN_REGULAR:
|
||||||
TransformTexCoordRegular(texinfo, coordNum, specialCase, src, dst);
|
TransformTexCoordRegular(texinfo, coordNum, specialCase, src, dst);
|
||||||
break;
|
break;
|
||||||
case XF_TEXGEN_EMBOSS_MAP:
|
case XF_TEXGEN_EMBOSS_MAP:
|
||||||
{
|
{
|
||||||
const LightPointer *light = (const LightPointer*)&swxfregs.lights[0x10*texinfo.embosslightshift];
|
const LightPointer *light = (const LightPointer*)&swxfregs.lights[0x10*texinfo.embosslightshift];
|
||||||
|
|
||||||
Vec3 ldir = (light->pos - dst->mvPosition).normalized();
|
Vec3 ldir = (light->pos - dst->mvPosition).normalized();
|
||||||
float d1 = ldir * dst->normal[1];
|
float d1 = ldir * dst->normal[1];
|
||||||
float d2 = ldir * dst->normal[2];
|
float d2 = ldir * dst->normal[2];
|
||||||
|
|
||||||
dst->texCoords[coordNum].x = dst->texCoords[texinfo.embosssourceshift].x + d1;
|
dst->texCoords[coordNum].x = dst->texCoords[texinfo.embosssourceshift].x + d1;
|
||||||
dst->texCoords[coordNum].y = dst->texCoords[texinfo.embosssourceshift].y + d2;
|
dst->texCoords[coordNum].y = dst->texCoords[texinfo.embosssourceshift].y + d2;
|
||||||
dst->texCoords[coordNum].z = dst->texCoords[texinfo.embosssourceshift].z;
|
dst->texCoords[coordNum].z = dst->texCoords[texinfo.embosssourceshift].z;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case XF_TEXGEN_COLOR_STRGBC0:
|
case XF_TEXGEN_COLOR_STRGBC0:
|
||||||
_assert_(texinfo.sourcerow == XF_SRCCOLORS_INROW);
|
_assert_(texinfo.sourcerow == XF_SRCCOLORS_INROW);
|
||||||
_assert_(texinfo.inputform == XF_TEXINPUT_AB11);
|
_assert_(texinfo.inputform == XF_TEXINPUT_AB11);
|
||||||
dst->texCoords[coordNum].x = (float)dst->color[0][0] / 255.0f;
|
dst->texCoords[coordNum].x = (float)dst->color[0][0] / 255.0f;
|
||||||
dst->texCoords[coordNum].y = (float)dst->color[0][1] / 255.0f;
|
dst->texCoords[coordNum].y = (float)dst->color[0][1] / 255.0f;
|
||||||
dst->texCoords[coordNum].z = 1.0f;
|
dst->texCoords[coordNum].z = 1.0f;
|
||||||
break;
|
break;
|
||||||
case XF_TEXGEN_COLOR_STRGBC1:
|
case XF_TEXGEN_COLOR_STRGBC1:
|
||||||
_assert_(texinfo.sourcerow == XF_SRCCOLORS_INROW);
|
_assert_(texinfo.sourcerow == XF_SRCCOLORS_INROW);
|
||||||
_assert_(texinfo.inputform == XF_TEXINPUT_AB11);
|
_assert_(texinfo.inputform == XF_TEXINPUT_AB11);
|
||||||
dst->texCoords[coordNum].x = (float)dst->color[1][0] / 255.0f;
|
dst->texCoords[coordNum].x = (float)dst->color[1][0] / 255.0f;
|
||||||
dst->texCoords[coordNum].y = (float)dst->color[1][1] / 255.0f;
|
dst->texCoords[coordNum].y = (float)dst->color[1][1] / 255.0f;
|
||||||
dst->texCoords[coordNum].z = 1.0f;
|
dst->texCoords[coordNum].z = 1.0f;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ERROR_LOG(VIDEO, "Bad tex gen type %i", texinfo.texgentype);
|
ERROR_LOG(VIDEO, "Bad tex gen type %i", texinfo.texgentype);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (u32 coordNum = 0; coordNum < swxfregs.numTexGens; coordNum++)
|
for (u32 coordNum = 0; coordNum < swxfregs.numTexGens; coordNum++)
|
||||||
{
|
{
|
||||||
dst->texCoords[coordNum][0] *= (bpmem.texcoords[coordNum].s.scale_minus_1 + 1);
|
dst->texCoords[coordNum][0] *= (bpmem.texcoords[coordNum].s.scale_minus_1 + 1);
|
||||||
dst->texCoords[coordNum][1] *= (bpmem.texcoords[coordNum].t.scale_minus_1 + 1);
|
dst->texCoords[coordNum][1] *= (bpmem.texcoords[coordNum].t.scale_minus_1 + 1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official Git repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#ifndef _TRANSFORM_UNIT_H_
|
#ifndef _TRANSFORM_UNIT_H_
|
||||||
|
@ -23,15 +23,15 @@ struct OutputVertexData;
|
||||||
|
|
||||||
namespace TransformUnit
|
namespace TransformUnit
|
||||||
{
|
{
|
||||||
void MultiplyVec2Mat24(const float *vec, const float *mat, float *result);
|
void MultiplyVec2Mat24(const float *vec, const float *mat, float *result);
|
||||||
void MultiplyVec2Mat34(const float *vec, const float *mat, float *result);
|
void MultiplyVec2Mat34(const float *vec, const float *mat, float *result);
|
||||||
void MultiplyVec3Mat33(const float *vec, const float *mat, float *result);
|
void MultiplyVec3Mat33(const float *vec, const float *mat, float *result);
|
||||||
void MultiplyVec3Mat34(const float *vec, const float *mat, float *result);
|
void MultiplyVec3Mat34(const float *vec, const float *mat, float *result);
|
||||||
|
|
||||||
void TransformPosition(const InputVertexData *src, OutputVertexData *dst);
|
void TransformPosition(const InputVertexData *src, OutputVertexData *dst);
|
||||||
void TransformNormal(const InputVertexData *src, bool nbt, OutputVertexData *dst);
|
void TransformNormal(const InputVertexData *src, bool nbt, OutputVertexData *dst);
|
||||||
void TransformColor(const InputVertexData *src, OutputVertexData *dst);
|
void TransformColor(const InputVertexData *src, OutputVertexData *dst);
|
||||||
void TransformTexCoord(const InputVertexData *src, OutputVertexData *dst, bool specialCase);
|
void TransformTexCoord(const InputVertexData *src, OutputVertexData *dst, bool specialCase);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official Git repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#ifndef _VEC3_H
|
#ifndef _VEC3_H
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official Git repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#include "VideoConfigDiag.h"
|
#include "VideoConfigDiag.h"
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official Git repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#ifndef _VIDEOSOFTWARE_CONFIG_DIAG_H_
|
#ifndef _VIDEOSOFTWARE_CONFIG_DIAG_H_
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official Git repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#include "VideoCommon.h"
|
#include "VideoCommon.h"
|
||||||
|
@ -26,15 +26,15 @@ XFRegisters swxfregs;
|
||||||
|
|
||||||
void InitXFMemory()
|
void InitXFMemory()
|
||||||
{
|
{
|
||||||
memset(&swxfregs, 0, sizeof(swxfregs));
|
memset(&swxfregs, 0, sizeof(swxfregs));
|
||||||
}
|
}
|
||||||
|
|
||||||
void XFWritten(u32 transferSize, u32 baseAddress)
|
void XFWritten(u32 transferSize, u32 baseAddress)
|
||||||
{
|
{
|
||||||
u32 topAddress = baseAddress + transferSize;
|
u32 topAddress = baseAddress + transferSize;
|
||||||
|
|
||||||
if (baseAddress <= 0x1026 && topAddress >= 0x1020)
|
if (baseAddress <= 0x1026 && topAddress >= 0x1020)
|
||||||
Clipper::SetViewOffset();
|
Clipper::SetViewOffset();
|
||||||
|
|
||||||
// fix lights so invalid values don't trash the lighting computations
|
// fix lights so invalid values don't trash the lighting computations
|
||||||
if (baseAddress <= 0x067f && topAddress >= 0x0604)
|
if (baseAddress <= 0x067f && topAddress >= 0x0604)
|
||||||
|
@ -63,32 +63,32 @@ void XFWritten(u32 transferSize, u32 baseAddress)
|
||||||
|
|
||||||
void SWLoadXFReg(u32 transferSize, u32 baseAddress, u32 *pData)
|
void SWLoadXFReg(u32 transferSize, u32 baseAddress, u32 *pData)
|
||||||
{
|
{
|
||||||
u32 size = transferSize;
|
u32 size = transferSize;
|
||||||
|
|
||||||
// do not allow writes past registers
|
// do not allow writes past registers
|
||||||
if (baseAddress + transferSize > 0x1058)
|
if (baseAddress + transferSize > 0x1058)
|
||||||
{
|
{
|
||||||
INFO_LOG(VIDEO, "xf load exceeds address space: %x %d bytes\n", baseAddress, transferSize);
|
INFO_LOG(VIDEO, "xf load exceeds address space: %x %d bytes\n", baseAddress, transferSize);
|
||||||
|
|
||||||
if (baseAddress >= 0x1058)
|
if (baseAddress >= 0x1058)
|
||||||
size = 0;
|
size = 0;
|
||||||
else
|
else
|
||||||
size = 0x1058 - baseAddress;
|
size = 0x1058 - baseAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (size > 0) {
|
|
||||||
memcpy_gc( &((u32*)&swxfregs)[baseAddress], pData, size * 4);
|
|
||||||
XFWritten(transferSize, baseAddress);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (size > 0)
|
||||||
|
{
|
||||||
|
memcpy_gc( &((u32*)&swxfregs)[baseAddress], pData, size * 4);
|
||||||
|
XFWritten(transferSize, baseAddress);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SWLoadIndexedXF(u32 val, int array)
|
void SWLoadIndexedXF(u32 val, int array)
|
||||||
{
|
{
|
||||||
int index = val >> 16;
|
int index = val >> 16;
|
||||||
int address = val & 0xFFF; //check mask
|
int address = val & 0xFFF; //check mask
|
||||||
int size = ((val >> 12) & 0xF) + 1;
|
int size = ((val >> 12) & 0xF) + 1;
|
||||||
//load stuff from array to address in xf mem
|
//load stuff from array to address in xf mem
|
||||||
|
|
||||||
u32 *pData = (u32*)Memory::GetPointer(arraybases[array] + arraystrides[array]*index);
|
u32 *pData = (u32*)Memory::GetPointer(arraybases[array] + arraystrides[array]*index);
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official Git repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#ifndef _XFMEMLOADER_H_
|
#ifndef _XFMEMLOADER_H_
|
||||||
|
@ -31,49 +31,49 @@
|
||||||
#define XF_TEXINPUT_AB11 0
|
#define XF_TEXINPUT_AB11 0
|
||||||
#define XF_TEXINPUT_ABC1 1
|
#define XF_TEXINPUT_ABC1 1
|
||||||
|
|
||||||
#define XF_TEXGEN_REGULAR 0
|
#define XF_TEXGEN_REGULAR 0
|
||||||
#define XF_TEXGEN_EMBOSS_MAP 1 // used when bump mapping
|
#define XF_TEXGEN_EMBOSS_MAP 1 // used when bump mapping
|
||||||
#define XF_TEXGEN_COLOR_STRGBC0 2
|
#define XF_TEXGEN_COLOR_STRGBC0 2
|
||||||
#define XF_TEXGEN_COLOR_STRGBC1 3
|
#define XF_TEXGEN_COLOR_STRGBC1 3
|
||||||
|
|
||||||
#define XF_SRCGEOM_INROW 0 // input is abc
|
#define XF_SRCGEOM_INROW 0 // input is abc
|
||||||
#define XF_SRCNORMAL_INROW 1 // input is abc
|
#define XF_SRCNORMAL_INROW 1 // input is abc
|
||||||
#define XF_SRCCOLORS_INROW 2
|
#define XF_SRCCOLORS_INROW 2
|
||||||
#define XF_SRCBINORMAL_T_INROW 3 // input is abc
|
#define XF_SRCBINORMAL_T_INROW 3 // input is abc
|
||||||
#define XF_SRCBINORMAL_B_INROW 4 // input is abc
|
#define XF_SRCBINORMAL_B_INROW 4 // input is abc
|
||||||
#define XF_SRCTEX0_INROW 5
|
#define XF_SRCTEX0_INROW 5
|
||||||
#define XF_SRCTEX1_INROW 6
|
#define XF_SRCTEX1_INROW 6
|
||||||
#define XF_SRCTEX2_INROW 7
|
#define XF_SRCTEX2_INROW 7
|
||||||
#define XF_SRCTEX3_INROW 8
|
#define XF_SRCTEX3_INROW 8
|
||||||
#define XF_SRCTEX4_INROW 9
|
#define XF_SRCTEX4_INROW 9
|
||||||
#define XF_SRCTEX5_INROW 10
|
#define XF_SRCTEX5_INROW 10
|
||||||
#define XF_SRCTEX6_INROW 11
|
#define XF_SRCTEX6_INROW 11
|
||||||
#define XF_SRCTEX7_INROW 12
|
#define XF_SRCTEX7_INROW 12
|
||||||
|
|
||||||
#define GX_SRC_REG 0
|
#define GX_SRC_REG 0
|
||||||
#define GX_SRC_VTX 1
|
#define GX_SRC_VTX 1
|
||||||
|
|
||||||
struct Light
|
struct Light
|
||||||
{
|
{
|
||||||
u32 useless[3];
|
u32 useless[3];
|
||||||
u32 color; //rgba
|
u32 color; //rgba
|
||||||
float a0; //attenuation
|
float a0; //attenuation
|
||||||
float a1;
|
float a1;
|
||||||
float a2;
|
float a2;
|
||||||
float k0; //k stuff
|
float k0; //k stuff
|
||||||
float k1;
|
float k1;
|
||||||
float k2;
|
float k2;
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
struct {
|
struct {
|
||||||
float dpos[3];
|
float dpos[3];
|
||||||
float ddir[3]; // specular lights only
|
float ddir[3]; // specular lights only
|
||||||
};
|
};
|
||||||
struct {
|
struct {
|
||||||
float sdir[3];
|
float sdir[3];
|
||||||
float shalfangle[3]; // specular lights only
|
float shalfangle[3]; // specular lights only
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
#define LIGHTDIF_NONE 0
|
#define LIGHTDIF_NONE 0
|
||||||
|
@ -83,74 +83,74 @@ struct Light
|
||||||
#define LIGHTATTN_SPEC 0 // specular attenuation
|
#define LIGHTATTN_SPEC 0 // specular attenuation
|
||||||
#define LIGHTATTN_SPOT 1 // distance/spotlight attenuation
|
#define LIGHTATTN_SPOT 1 // distance/spotlight attenuation
|
||||||
#define LIGHTATTN_NONE 2
|
#define LIGHTATTN_NONE 2
|
||||||
#define LIGHTATTN_DIR 3
|
#define LIGHTATTN_DIR 3
|
||||||
|
|
||||||
#define GX_PERSPECTIVE 0
|
#define GX_PERSPECTIVE 0
|
||||||
#define GX_ORTHOGRAPHIC 1
|
#define GX_ORTHOGRAPHIC 1
|
||||||
|
|
||||||
union LitChannel
|
union LitChannel
|
||||||
{
|
{
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
u32 matsource : 1;
|
u32 matsource : 1;
|
||||||
u32 enablelighting : 1;
|
u32 enablelighting : 1;
|
||||||
u32 lightMask0_3 : 4;
|
u32 lightMask0_3 : 4;
|
||||||
u32 ambsource : 1;
|
u32 ambsource : 1;
|
||||||
u32 diffusefunc : 2; // LIGHTDIF_X
|
u32 diffusefunc : 2; // LIGHTDIF_X
|
||||||
u32 attnfunc : 2; // LIGHTATTN_X
|
u32 attnfunc : 2; // LIGHTATTN_X
|
||||||
u32 lightMask4_7 : 4;
|
u32 lightMask4_7 : 4;
|
||||||
u32 unused : 17;
|
u32 unused : 17;
|
||||||
};
|
};
|
||||||
u32 hex;
|
u32 hex;
|
||||||
unsigned int GetFullLightMask() const
|
unsigned int GetFullLightMask() const
|
||||||
{
|
{
|
||||||
return enablelighting ? (lightMask0_3 | (lightMask4_7 << 4)) : 0;
|
return enablelighting ? (lightMask0_3 | (lightMask4_7 << 4)) : 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
union INVTXSPEC
|
union INVTXSPEC
|
||||||
{
|
{
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
u32 numcolors : 2;
|
u32 numcolors : 2;
|
||||||
u32 numnormals : 2; // 0 - nothing, 1 - just normal, 2 - normals and binormals
|
u32 numnormals : 2; // 0 - nothing, 1 - just normal, 2 - normals and binormals
|
||||||
u32 numtextures : 4;
|
u32 numtextures : 4;
|
||||||
u32 unused : 24;
|
u32 unused : 24;
|
||||||
};
|
};
|
||||||
u32 hex;
|
u32 hex;
|
||||||
};
|
};
|
||||||
|
|
||||||
union TXFMatrixIndexA
|
union TXFMatrixIndexA
|
||||||
{
|
{
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
u32 PosNormalMtxIdx : 6;
|
u32 PosNormalMtxIdx : 6;
|
||||||
u32 Tex0MtxIdx : 6;
|
u32 Tex0MtxIdx : 6;
|
||||||
u32 Tex1MtxIdx : 6;
|
u32 Tex1MtxIdx : 6;
|
||||||
u32 Tex2MtxIdx : 6;
|
u32 Tex2MtxIdx : 6;
|
||||||
u32 Tex3MtxIdx : 6;
|
u32 Tex3MtxIdx : 6;
|
||||||
};
|
};
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
u32 Hex : 30;
|
u32 Hex : 30;
|
||||||
u32 unused : 2;
|
u32 unused : 2;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
union TXFMatrixIndexB
|
union TXFMatrixIndexB
|
||||||
{
|
{
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
u32 Tex4MtxIdx : 6;
|
u32 Tex4MtxIdx : 6;
|
||||||
u32 Tex5MtxIdx : 6;
|
u32 Tex5MtxIdx : 6;
|
||||||
u32 Tex6MtxIdx : 6;
|
u32 Tex6MtxIdx : 6;
|
||||||
u32 Tex7MtxIdx : 6;
|
u32 Tex7MtxIdx : 6;
|
||||||
};
|
};
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
u32 Hex : 24;
|
u32 Hex : 24;
|
||||||
u32 unused : 8;
|
u32 unused : 8;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Viewport
|
struct Viewport
|
||||||
|
@ -171,68 +171,68 @@ struct Projection
|
||||||
|
|
||||||
union TexMtxInfo
|
union TexMtxInfo
|
||||||
{
|
{
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
u32 unknown : 1;
|
u32 unknown : 1;
|
||||||
u32 projection : 1; // XF_TEXPROJ_X
|
u32 projection : 1; // XF_TEXPROJ_X
|
||||||
u32 inputform : 2; // XF_TEXINPUT_X
|
u32 inputform : 2; // XF_TEXINPUT_X
|
||||||
u32 texgentype : 3; // XF_TEXGEN_X
|
u32 texgentype : 3; // XF_TEXGEN_X
|
||||||
u32 sourcerow : 5; // XF_SRCGEOM_X
|
u32 sourcerow : 5; // XF_SRCGEOM_X
|
||||||
u32 embosssourceshift : 3; // what generated texcoord to use
|
u32 embosssourceshift : 3; // what generated texcoord to use
|
||||||
u32 embosslightshift : 3; // light index that is used
|
u32 embosslightshift : 3; // light index that is used
|
||||||
};
|
};
|
||||||
u32 hex;
|
u32 hex;
|
||||||
};
|
};
|
||||||
|
|
||||||
union PostMtxInfo
|
union PostMtxInfo
|
||||||
{
|
{
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
u32 index : 6; // base row of dual transform matrix
|
u32 index : 6; // base row of dual transform matrix
|
||||||
u32 unused : 2;
|
u32 unused : 2;
|
||||||
u32 normalize : 1; // normalize before send operation
|
u32 normalize : 1; // normalize before send operation
|
||||||
};
|
};
|
||||||
u32 hex;
|
u32 hex;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct XFRegisters
|
struct XFRegisters
|
||||||
{
|
{
|
||||||
u32 posMatrices[256]; // 0x0000 - 0x00ff
|
u32 posMatrices[256]; // 0x0000 - 0x00ff
|
||||||
u32 unk0[768]; // 0x0100 - 0x03ff
|
u32 unk0[768]; // 0x0100 - 0x03ff
|
||||||
u32 normalMatrices[96]; // 0x0400 - 0x045f
|
u32 normalMatrices[96]; // 0x0400 - 0x045f
|
||||||
u32 unk1[160]; // 0x0460 - 0x04ff
|
u32 unk1[160]; // 0x0460 - 0x04ff
|
||||||
u32 postMatrices[256]; // 0x0500 - 0x05ff
|
u32 postMatrices[256]; // 0x0500 - 0x05ff
|
||||||
u32 lights[128]; // 0x0600 - 0x067f
|
u32 lights[128]; // 0x0600 - 0x067f
|
||||||
u32 unk2[2432]; // 0x0680 - 0x0fff
|
u32 unk2[2432]; // 0x0680 - 0x0fff
|
||||||
u32 error; // 0x1000
|
u32 error; // 0x1000
|
||||||
u32 diag; // 0x1001
|
u32 diag; // 0x1001
|
||||||
u32 state0; // 0x1002
|
u32 state0; // 0x1002
|
||||||
u32 state1; // 0x1003
|
u32 state1; // 0x1003
|
||||||
u32 xfClock; // 0x1004
|
u32 xfClock; // 0x1004
|
||||||
u32 clipDisable; // 0x1005
|
u32 clipDisable; // 0x1005
|
||||||
u32 perf0; // 0x1006
|
u32 perf0; // 0x1006
|
||||||
u32 perf1; // 0x1007
|
u32 perf1; // 0x1007
|
||||||
INVTXSPEC hostinfo; // 0x1008 number of textures,colors,normals from vertex input
|
INVTXSPEC hostinfo; // 0x1008 number of textures,colors,normals from vertex input
|
||||||
u32 nNumChans; // 0x1009
|
u32 nNumChans; // 0x1009
|
||||||
u32 ambColor[2]; // 0x100a, 0x100b
|
u32 ambColor[2]; // 0x100a, 0x100b
|
||||||
u32 matColor[2]; // 0x100c, 0x100d
|
u32 matColor[2]; // 0x100c, 0x100d
|
||||||
LitChannel color[2]; // 0x100e, 0x100f
|
LitChannel color[2]; // 0x100e, 0x100f
|
||||||
LitChannel alpha[2]; // 0x1010, 0x1011
|
LitChannel alpha[2]; // 0x1010, 0x1011
|
||||||
u32 dualTexTrans; // 0x1012
|
u32 dualTexTrans; // 0x1012
|
||||||
u32 unk3; // 0x1013
|
u32 unk3; // 0x1013
|
||||||
u32 unk4; // 0x1014
|
u32 unk4; // 0x1014
|
||||||
u32 unk5; // 0x1015
|
u32 unk5; // 0x1015
|
||||||
u32 unk6; // 0x1016
|
u32 unk6; // 0x1016
|
||||||
u32 unk7; // 0x1017
|
u32 unk7; // 0x1017
|
||||||
TXFMatrixIndexA MatrixIndexA; // 0x1018
|
TXFMatrixIndexA MatrixIndexA; // 0x1018
|
||||||
TXFMatrixIndexB MatrixIndexB; // 0x1019
|
TXFMatrixIndexB MatrixIndexB; // 0x1019
|
||||||
Viewport viewport; // 0x101a - 0x101f
|
Viewport viewport; // 0x101a - 0x101f
|
||||||
Projection projection; // 0x1020 - 0x1026
|
Projection projection; // 0x1020 - 0x1026
|
||||||
u32 unk8[24]; // 0x1027 - 0x103e
|
u32 unk8[24]; // 0x1027 - 0x103e
|
||||||
u32 numTexGens; // 0x103f
|
u32 numTexGens; // 0x103f
|
||||||
TexMtxInfo texMtxInfo[8]; // 0x1040 - 0x1047
|
TexMtxInfo texMtxInfo[8]; // 0x1040 - 0x1047
|
||||||
u32 unk9[8]; // 0x1048 - 0x104f
|
u32 unk9[8]; // 0x1048 - 0x104f
|
||||||
PostMtxInfo postMtxInfo[8]; // 0x1050 - 0x1057
|
PostMtxInfo postMtxInfo[8]; // 0x1050 - 0x1057
|
||||||
};
|
};
|
||||||
|
|
||||||
#define XFMEM_POSMATRICES 0x000
|
#define XFMEM_POSMATRICES 0x000
|
||||||
|
@ -249,7 +249,7 @@ extern XFRegisters swxfregs;
|
||||||
|
|
||||||
void InitXFMemory();
|
void InitXFMemory();
|
||||||
|
|
||||||
void XFWritten(u32 transferSize, u32 baseAddress);
|
void XFWritten(u32 transferSize, u32 baseAddress);
|
||||||
|
|
||||||
void SWLoadXFReg(u32 transferSize, u32 baseAddress, u32 *pData);
|
void SWLoadXFReg(u32 transferSize, u32 baseAddress, u32 *pData);
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official Git repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official Git repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
Loading…
Reference in New Issue