SWG: Adds TEV stage output dumping. Fixes interrupt handling in the command processor. Some code cleanup and a few graphical fixes for rare cases.

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@4472 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
donkopunchstania 2009-10-28 03:01:07 +00:00
parent a31eb24955
commit 63e3d184f8
11 changed files with 143 additions and 81 deletions

View File

@ -46,6 +46,8 @@ const int maxCommandBufferWrite = commandBufferSize - commandBufferCopySize;
u8 commandBuffer[commandBufferSize]; u8 commandBuffer[commandBufferSize];
u32 readPos; u32 readPos;
u32 writePos; u32 writePos;
bool interruptSet;
int et_UpdateInterrupts;
CPReg cpreg; // shared between gfx and emulator thread CPReg cpreg; // shared between gfx and emulator thread
@ -55,20 +57,13 @@ void DoState(PointerWrap &p)
p.Do(cpreg); p.Do(cpreg);
} }
// function
void UpdateFifoRegister();
void UpdateInterrupts();
// does it matter that there is no synchronization between threads during writes? // does it matter that there is no synchronization between threads during writes?
inline void WriteLow (u32& _reg, u16 lowbits) {_reg = (_reg & 0xFFFF0000) | lowbits;} inline void WriteLow (u32& _reg, u16 lowbits) {_reg = (_reg & 0xFFFF0000) | lowbits;}
inline void WriteHigh(u32& _reg, u16 highbits) {_reg = (_reg & 0x0000FFFF) | ((u32)highbits << 16);} inline void WriteHigh(u32& _reg, u16 highbits) {_reg = (_reg & 0x0000FFFF) | ((u32)highbits << 16);}
//inline void WriteLow (volatile u32& _reg, u16 lowbits) {Common::SyncInterlockedExchange((LONG*)&_reg,(_reg & 0xFFFF0000) | lowbits);}
//inline void WriteHigh(volatile u32& _reg, u16 highbits) {Common::SyncInterlockedExchange((LONG*)&_reg,(_reg & 0x0000FFFF) | ((u32)highbits << 16));}
inline u16 ReadLow (u32 _reg) {return (u16)(_reg & 0xFFFF);} inline u16 ReadLow (u32 _reg) {return (u16)(_reg & 0xFFFF);}
inline u16 ReadHigh (u32 _reg) {return (u16)(_reg >> 16);} inline u16 ReadHigh (u32 _reg) {return (u16)(_reg >> 16);}
int et_UpdateInterrupts;
void UpdateInterrupts_Wrapper(u64 userdata, int cyclesLate) void UpdateInterrupts_Wrapper(u64 userdata, int cyclesLate)
{ {
@ -97,25 +92,13 @@ void Init()
readPos = 0; readPos = 0;
writePos = 0; writePos = 0;
interruptSet = false;
g_pVideoData = 0; g_pVideoData = 0;
} }
void Shutdown() void Shutdown()
{ {
#ifndef _WIN32
// delete fifo.sync;
#endif
}
void Read16(u16& _rReturnValue, const u32 _Address)
{
DEBUG_LOG(COMMANDPROCESSOR, "(r): 0x%08x", _Address);
u32 regAddr = (_Address & 0xFFF) >> 1;
if (regAddr < 0x20)
_rReturnValue = ((u16*)&cpreg)[regAddr];
else
_rReturnValue = 0;
} }
void RunGpu() void RunGpu()
@ -127,12 +110,25 @@ void RunGpu()
LoadDefaultSSEState(); LoadDefaultSSEState();
// run the opcode decoder // run the opcode decoder
do {
RunBuffer(); RunBuffer();
} while (cpreg.ctrl.GPReadEnable && !cpreg.status.Breakpoint && cpreg.rwdistance >= commandBufferCopySize);
LoadSSEState(); LoadSSEState();
} }
} }
void Read16(u16& _rReturnValue, const u32 _Address)
{
DEBUG_LOG(COMMANDPROCESSOR, "(r): 0x%08x", _Address);
u32 regAddr = (_Address & 0xFFF) >> 1;
if (regAddr < 0x20)
_rReturnValue = ((u16*)&cpreg)[regAddr];
else
_rReturnValue = 0;
}
void Write16(const u16 _Value, const u32 _Address) void Write16(const u16 _Value, const u32 _Address)
{ {
INFO_LOG(COMMANDPROCESSOR, "(write16): 0x%04x @ 0x%08x",_Value,_Address); INFO_LOG(COMMANDPROCESSOR, "(write16): 0x%04x @ 0x%08x",_Value,_Address);
@ -149,6 +145,8 @@ void Write16(const u16 _Value, const u32 _Address)
cpreg.status.Hex = _Value; cpreg.status.Hex = _Value;
INFO_LOG(COMMANDPROCESSOR,"\t write to STATUS_REGISTER : %04x", _Value); INFO_LOG(COMMANDPROCESSOR,"\t write to STATUS_REGISTER : %04x", _Value);
UpdateInterrupts();
} }
break; break;
@ -158,23 +156,23 @@ void Write16(const u16 _Value, const u32 _Address)
// clear breakpoint if BPEnable and CPIntEnable are 0 // clear breakpoint if BPEnable and CPIntEnable are 0
if (!cpreg.ctrl.BPEnable) { if (!cpreg.ctrl.BPEnable) {
if (!cpreg.ctrl.CPIntEnable) { if (!cpreg.ctrl.BreakPointIntEnable) {
cpreg.status.Breakpoint = 0; cpreg.status.Breakpoint = 0;
} }
} }
UpdateInterrupts();
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 || CPIntEnable %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.CPIntEnable ? "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"
); );
UpdateInterrupts();
} }
break; break;
@ -188,6 +186,8 @@ void Write16(const u16 _Value, const u32 _Address)
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);
UpdateInterrupts();
} }
break; break;
@ -303,19 +303,21 @@ void STACKALIGN GatherPipeBursted()
void UpdateInterrupts() void UpdateInterrupts()
{ {
bool bpInt = cpreg.status.Breakpoint && cpreg.ctrl.BPEnable; 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;
DEBUG_LOG(COMMANDPROCESSOR, "\tUpdate Interrupts"); DEBUG_LOG(COMMANDPROCESSOR, "\tUpdate Interrupts");
DEBUG_LOG(COMMANDPROCESSOR, "\tCPIntEnable %s | BP %s | OvF %s | UndF %s" DEBUG_LOG(COMMANDPROCESSOR, "\tBreakPointIntEnable %s | BP %s | OvF %s | UndF %s"
, cpreg.ctrl.CPIntEnable ? "ON" : "OFF" , cpreg.ctrl.BreakPointIntEnable ? "ON" : "OFF"
, cpreg.ctrl.BPEnable ? "ON" : "OFF" , cpreg.ctrl.BPEnable ? "ON" : "OFF"
, cpreg.ctrl.FifoOverflowIntEnable ? "ON" : "OFF" , cpreg.ctrl.FifoOverflowIntEnable ? "ON" : "OFF"
, cpreg.ctrl.FifoUnderflowIntEnable ? "ON" : "OFF" , cpreg.ctrl.FifoUnderflowIntEnable ? "ON" : "OFF"
); );
if (cpreg.ctrl.CPIntEnable && (bpInt || ovfInt || undfInt)) interruptSet = bpInt || ovfInt || undfInt;
if (interruptSet)
{ {
DEBUG_LOG(COMMANDPROCESSOR,"Interrupt set"); DEBUG_LOG(COMMANDPROCESSOR,"Interrupt set");
g_VideoInitialize.pSetInterrupt(INT_CAUSE_CP, true); g_VideoInitialize.pSetInterrupt(INT_CAUSE_CP, true);
@ -334,8 +336,6 @@ void UpdateInterruptsFromVideoPlugin()
void ReadFifo() void ReadFifo()
{ {
bool updateInterrupts = false;
cpreg.status.ReadIdle = 0; cpreg.status.ReadIdle = 0;
// update rwdistance // update rwdistance
@ -347,7 +347,6 @@ void ReadFifo()
// overflow check // overflow check
cpreg.status.OverflowHiWatermark = cpreg.rwdistance < cpreg.hiwatermark?0:1; cpreg.status.OverflowHiWatermark = cpreg.rwdistance < cpreg.hiwatermark?0:1;
updateInterrupts |= cpreg.ctrl.FifoOverflowIntEnable && cpreg.status.OverflowHiWatermark;
// read from fifo // read from fifo
u8 *ptr = g_VideoInitialize.pGetMemoryPointer(cpreg.readptr); u8 *ptr = g_VideoInitialize.pGetMemoryPointer(cpreg.readptr);
@ -363,8 +362,6 @@ void ReadFifo()
{ {
cpreg.status.Breakpoint = 1; cpreg.status.Breakpoint = 1;
DEBUG_LOG(VIDEO,"Hit breakpoint at %x", readptr); DEBUG_LOG(VIDEO,"Hit breakpoint at %x", readptr);
if (cpreg.ctrl.CPIntEnable)
updateInterrupts = true;
} }
else else
{ {
@ -389,12 +386,20 @@ void ReadFifo()
// underflow check // underflow check
cpreg.status.UnderflowLoWatermark = cpreg.rwdistance > cpreg.lowatermark?0:1; cpreg.status.UnderflowLoWatermark = cpreg.rwdistance > cpreg.lowatermark?0:1;
updateInterrupts |= cpreg.ctrl.FifoUnderflowIntEnable && cpreg.status.UnderflowLoWatermark;
cpreg.status.ReadIdle = 1; cpreg.status.ReadIdle = 1;
if (updateInterrupts) bool bpInt = cpreg.status.Breakpoint && cpreg.ctrl.BreakPointIntEnable;
bool ovfInt = cpreg.status.OverflowHiWatermark && cpreg.ctrl.FifoOverflowIntEnable;
bool undfInt = cpreg.status.UnderflowLoWatermark && cpreg.ctrl.FifoUnderflowIntEnable;
bool interrupt = bpInt || ovfInt || undfInt;
if (interrupt != interruptSet)
{
interruptSet = interrupt;
UpdateInterruptsFromVideoPlugin(); UpdateInterruptsFromVideoPlugin();
}
} }
bool RunBuffer() bool RunBuffer()
@ -440,4 +445,4 @@ bool RunBuffer()
return ranDecoder; return ranDecoder;
} }
} // end of namespace CommandProcessor } // end of namespace CommandProcessor

View File

@ -76,7 +76,7 @@ namespace CommandProcessor
struct struct
{ {
unsigned GPReadEnable : 1; unsigned GPReadEnable : 1;
unsigned CPIntEnable : 1; unsigned BreakPointIntEnable : 1;
unsigned FifoOverflowIntEnable : 1; unsigned FifoOverflowIntEnable : 1;
unsigned FifoUnderflowIntEnable : 1; unsigned FifoUnderflowIntEnable : 1;
unsigned GPLinkEnable : 1; unsigned GPLinkEnable : 1;

View File

@ -32,6 +32,20 @@ namespace DebugUtil
{ {
u32 skipFrames = 0; u32 skipFrames = 0;
const int NumObjectBuffers = 32;
u8 ObjectBuffer[NumObjectBuffers][EFB_WIDTH*EFB_HEIGHT*4];
bool DrawnToBuffer[NumObjectBuffers];
const char* ObjectBufferName[NumObjectBuffers];
void Init()
{
for (int i = 0; i < NumObjectBuffers; i++)
{
memset(ObjectBuffer[i], 0, sizeof(ObjectBuffer[i]));
DrawnToBuffer[i] = false;
ObjectBufferName[i] = 0;
}
}
bool SaveTexture(const char* filename, u32 texmap, int width, int height) bool SaveTexture(const char* filename, u32 texmap, int width, int height)
{ {
@ -133,11 +147,24 @@ void DumpDepth(const char* filename)
delete []data; delete []data;
} }
void DrawObjectBuffer(s16 x, s16 y, u8 *color, int buffer, const char *name)
{
u32 offset = (x + y * EFB_WIDTH) * 4;
u8 *dst = &ObjectBuffer[buffer][offset];
*(dst++) = color[2];
*(dst++) = color[1];
*(dst++) = color[0];
*(dst++) = color[3];
DrawnToBuffer[buffer] = true;
ObjectBufferName[buffer] = name;
}
void OnObjectBegin() void OnObjectBegin()
{ {
if (!g_SkipFrame) if (!g_SkipFrame)
{ {
if (g_Config.bDumpTextures) if (g_Config.bDumpTextures && stats.thisFrame.numDrawnObjects >= g_Config.drawStart && stats.thisFrame.numDrawnObjects < g_Config.drawEnd)
DumpActiveTextures(); DumpActiveTextures();
if (g_Config.bHwRasterizer) if (g_Config.bHwRasterizer)
@ -149,12 +176,23 @@ void OnObjectEnd()
{ {
if (!g_SkipFrame) if (!g_SkipFrame)
{ {
if (g_Config.bDumpObjects) if (g_Config.bDumpObjects && stats.thisFrame.numDrawnObjects >= g_Config.drawStart && stats.thisFrame.numDrawnObjects < g_Config.drawEnd)
DumpEfb(StringFromFormat("%s/object%i.tga", FULL_FRAMES_DIR, stats.thisFrame.numDrawnObjects).c_str()); DumpEfb(StringFromFormat("%s/object%i.tga", FULL_FRAMES_DIR, stats.thisFrame.numDrawnObjects).c_str());
if (g_Config.bHwRasterizer) if (g_Config.bHwRasterizer)
HwRasterizer::EndTriangles(); HwRasterizer::EndTriangles();
for (int i = 0; i < NumObjectBuffers; i++)
{
if (DrawnToBuffer[i])
{
DrawnToBuffer[i] = false;
SaveTGA(StringFromFormat("%s/object%i_%s(%i).tga", FULL_FRAMES_DIR,
stats.thisFrame.numDrawnObjects, ObjectBufferName[i], i).c_str(), EFB_WIDTH, EFB_HEIGHT, ObjectBuffer[i]);
memset(ObjectBuffer[i], 0, sizeof(ObjectBuffer[i]));
}
}
stats.thisFrame.numDrawnObjects++; stats.thisFrame.numDrawnObjects++;
} }
} }

View File

@ -20,6 +20,8 @@
namespace DebugUtil namespace DebugUtil
{ {
void Init();
void GetTextureBGRA(u8 *dst, u32 texmap, int width, int height); void GetTextureBGRA(u8 *dst, u32 texmap, int width, int height);
void DumpActiveTextures(); void DumpActiveTextures();
@ -28,6 +30,8 @@ namespace DebugUtil
void OnObjectEnd(); void OnObjectEnd();
void OnFrameEnd(); void OnFrameEnd();
void DrawObjectBuffer(s16 x, s16 y, u8 *color, int buffer, const char *name);
} }
#endif #endif

View File

@ -136,8 +136,7 @@ void UpdateInterrupts()
// Called only if BPMEM_PE_TOKEN_INT_ID is ack by GP // Called only if BPMEM_PE_TOKEN_INT_ID is ack by GP
void SetToken_OnMainThread(u64 userdata, int cyclesLate) void SetToken_OnMainThread(u64 userdata, int cyclesLate)
{ {
g_bSignalTokenInterrupt = true; g_bSignalTokenInterrupt = true;
//_dbg_assert_msg_(PIXELENGINE, (CommandProcessor::fifo.PEToken == (userdata&0xFFFF)), "WTF? BPMEM_PE_TOKEN_INT_ID's token != BPMEM_PE_TOKEN_ID's token" );
INFO_LOG(PIXELENGINE, "VIDEO Plugin raises INT_CAUSE_PE_TOKEN (btw, token: %04x)", pereg.token); INFO_LOG(PIXELENGINE, "VIDEO Plugin raises INT_CAUSE_PE_TOKEN (btw, token: %04x)", pereg.token);
UpdateInterrupts(); UpdateInterrupts();
} }
@ -158,10 +157,6 @@ void SetToken(const u16 _token, const int _bSetTokenAcknowledge)
g_VideoInitialize.pScheduleEvent_Threadsafe( g_VideoInitialize.pScheduleEvent_Threadsafe(
0, et_SetTokenOnMainThread, _token | (_bSetTokenAcknowledge << 16)); 0, et_SetTokenOnMainThread, _token | (_bSetTokenAcknowledge << 16));
} }
else // set token value
{
ERROR_LOG(PIXELENGINE, "VIDEO plugin should set the token directly");
}
} }
// SetFinish // SetFinish

View File

@ -21,6 +21,8 @@
#include "EfbInterface.h" #include "EfbInterface.h"
#include "TextureSampler.h" #include "TextureSampler.h"
#include "Statistics.h" #include "Statistics.h"
#include "VideoConfig.h"
#include "DebugUtil.h"
#include <math.h> #include <math.h>
@ -120,6 +122,11 @@ inline s16 Clamp255(s16 in)
return in>255?255:(in<0?0:in); return in>255?255:(in<0?0:in);
} }
inline s16 Clamp1024(s16 in)
{
return in>1023?1023:(in<-1024?-1024:in);
}
inline void Tev::SetRasColor(int colorChan, int swaptable) inline void Tev::SetRasColor(int colorChan, int swaptable)
{ {
switch(colorChan) switch(colorChan)
@ -168,12 +175,7 @@ inline void Tev::SetRasColor(int colorChan, int swaptable)
void Tev::DrawColorRegular(TevStageCombiner::ColorCombiner &cc) void Tev::DrawColorRegular(TevStageCombiner::ColorCombiner &cc)
{ {
struct { InputRegType InputReg;
unsigned a : 8;
unsigned b : 8;
unsigned c : 8;
signed d : 11;
} InputReg;
for (int i = 0; i < 3; i++) for (int i = 0; i < 3; i++)
{ {
@ -202,12 +204,7 @@ void Tev::DrawColorCompare(TevStageCombiner::ColorCombiner &cc)
u32 a; u32 a;
u32 b; u32 b;
struct { InputRegType InputReg;
unsigned a : 8;
unsigned b : 8;
unsigned c : 8;
signed d : 11;
} InputReg;
switch(cmp) { switch(cmp) {
case TEVCMP_R8_GT: case TEVCMP_R8_GT:
@ -308,13 +305,7 @@ void Tev::DrawColorCompare(TevStageCombiner::ColorCombiner &cc)
void Tev::DrawAlphaRegular(TevStageCombiner::AlphaCombiner &ac) void Tev::DrawAlphaRegular(TevStageCombiner::AlphaCombiner &ac)
{ {
struct { InputRegType InputReg;
unsigned a : 8;
unsigned b : 8;
unsigned c : 8;
signed d : 11;
} InputReg;
InputReg.a = *m_AlphaInputLUT[ac.a]; InputReg.a = *m_AlphaInputLUT[ac.a];
InputReg.b = *m_AlphaInputLUT[ac.b]; InputReg.b = *m_AlphaInputLUT[ac.b];
@ -340,12 +331,7 @@ void Tev::DrawAlphaCompare(TevStageCombiner::AlphaCombiner &ac)
u32 a; u32 a;
u32 b; u32 b;
struct { InputRegType InputReg;
unsigned a : 8;
unsigned b : 8;
unsigned c : 8;
signed d : 11;
} InputReg;
switch(cmp) { switch(cmp) {
case TEVCMP_R8_GT: case TEVCMP_R8_GT:
@ -641,7 +627,7 @@ void Tev::Draw()
StageKonst[ALP_C] = *(m_KonstLUT[ka][ALP_C]); StageKonst[ALP_C] = *(m_KonstLUT[ka][ALP_C]);
// set color // set color
SetRasColor(order.getColorChan(stageOdd), ac.rswap * 2); SetRasColor(order.getColorChan(stageOdd), ac.rswap * 2);
// combine inputs // combine inputs
if (cc.bias != 3) if (cc.bias != 3)
@ -655,6 +641,12 @@ void Tev::Draw()
Reg[cc.dest][GRN_C] = Clamp255(Reg[cc.dest][GRN_C]); Reg[cc.dest][GRN_C] = Clamp255(Reg[cc.dest][GRN_C]);
Reg[cc.dest][BLU_C] = Clamp255(Reg[cc.dest][BLU_C]); Reg[cc.dest][BLU_C] = Clamp255(Reg[cc.dest][BLU_C]);
} }
else
{
Reg[cc.dest][RED_C] = Clamp1024(Reg[cc.dest][RED_C]);
Reg[cc.dest][GRN_C] = Clamp1024(Reg[cc.dest][GRN_C]);
Reg[cc.dest][BLU_C] = Clamp1024(Reg[cc.dest][BLU_C]);
}
if (ac.bias != 3) if (ac.bias != 3)
DrawAlphaRegular(ac); DrawAlphaRegular(ac);
@ -663,7 +655,16 @@ void Tev::Draw()
if (ac.clamp) if (ac.clamp)
Reg[ac.dest][ALP_C] = Clamp255(Reg[ac.dest][ALP_C]); Reg[ac.dest][ALP_C] = Clamp255(Reg[ac.dest][ALP_C]);
else
Reg[ac.dest][ALP_C] = Clamp1024(Reg[ac.dest][ALP_C]);
#ifdef _DEBUG
if (g_Config.bDumpTevStages)
{
u8 stage[4] = {(u8)Reg[0][0], (u8)Reg[0][1], (u8)Reg[0][2], (u8)Reg[0][3]};
DebugUtil::DrawObjectBuffer(Position[0], Position[1], stage, stageNum, "Stage");
}
#endif
} }
// convert to 8 bits per component // convert to 8 bits per component
@ -719,4 +720,4 @@ void Tev::SetRegColor(int reg, int comp, bool konst, s16 color)
{ {
Reg[reg][comp] = color; Reg[reg][comp] = color;
} }
} }

View File

@ -51,6 +51,13 @@ class Tev
void Indirect(unsigned int stageNum, float s, float t); void Indirect(unsigned int stageNum, float s, float t);
struct InputRegType {
unsigned a : 8;
unsigned b : 8;
unsigned c : 8;
signed d : 11;
};
public: public:
s32 Position[3]; s32 Position[3];
u8 Color[2][4]; u8 Color[2][4];

View File

@ -199,6 +199,11 @@ inline float Clamp(float val, float a, float b)
return val<a?a:val>b?b:val; return val<a?a:val>b?b:val;
} }
inline float SafeDivide(float n, float d)
{
return (d==0)?(n>0?1:0):n/d;
}
void LightColor(const float *vertexPos, const float *normal, u8 lightNum, const LitChannel &chan, Vec3 &lightCol) void LightColor(const float *vertexPos, const float *normal, u8 lightNum, const LitChannel &chan, Vec3 &lightCol)
{ {
// must be the size of 3 32bit floats for the light pointer to be valid // must be the size of 3 32bit floats for the light pointer to be valid
@ -244,15 +249,16 @@ void LightColor(const float *vertexPos, const float *normal, u8 lightNum, const
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 = distAtt==0.0f?0.0f:(max(0.0f, cosAtt) / distAtt); attn = SafeDivide(max(0.0f, cosAtt), distAtt);
} }
else if (chan.attnfunc == 1) { // specular else if (chan.attnfunc == 1) { // specular
attn = (light->pos * (*norm0)) > 0 ? max(0.0f, (light->dir * (*norm0))) : 0; // donko - what is going on here? 655.36 is a guess but seems about right.
attn = (light->pos * (*norm0)) > -655.36 ? max(0.0f, (light->dir * (*norm0))) : 0;
ldir.set(1.0f, attn, attn * attn); ldir.set(1.0f, attn, attn * attn);
float cosAtt = light->cosatt * ldir; float cosAtt = max(0.0f, light->cosatt * ldir);
float distAtt = light->distatt * ldir; float distAtt = light->distatt * ldir;
attn = distAtt==0.0f?1.0f:(max(0.0f, cosAtt) / distAtt); attn = SafeDivide(max(0.0f, cosAtt), distAtt);
} }
switch (chan.diffusefunc) { switch (chan.diffusefunc) {
@ -321,15 +327,16 @@ void LightAlpha(const float *vertexPos, const float *normal, u8 lightNum, const
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 = distAtt==0.0f?0.0f:(max(0.0f, cosAtt) / distAtt); attn = SafeDivide(max(0.0f, cosAtt), distAtt);
} }
else if (chan.attnfunc == 1) { // specular else if (chan.attnfunc == 1) { // specular
attn = (light->pos * (*norm0)) > 0 ? max(0.0f, (light->dir * (*norm0))) : 0; // donko - what is going on here? 655.36 is a guess but seems about right.
attn = (light->pos * (*norm0)) > -655.36 ? max(0.0f, (light->dir * (*norm0))) : 0;
ldir.set(1.0f, attn, attn * attn); 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 = distAtt==0.0f?1.0f:(max(0.0f, cosAtt) / distAtt); attn = SafeDivide(max(0.0f, cosAtt), distAtt);
} }
switch (chan.diffusefunc) { switch (chan.diffusefunc) {

View File

@ -32,6 +32,7 @@ Config::Config()
bDumpTextures = false; bDumpTextures = false;
bDumpObjects = false; bDumpObjects = false;
bDumpFrames = false; bDumpFrames = false;
bDumpTevStages = false;
bHwRasterizer = false; bHwRasterizer = false;

View File

@ -38,6 +38,7 @@ struct Config
bool bDumpTextures; bool bDumpTextures;
bool bDumpObjects; bool bDumpObjects;
bool bDumpFrames; bool bDumpFrames;
bool bDumpTevStages;
bool bHwRasterizer; bool bHwRasterizer;

View File

@ -33,6 +33,7 @@
#include "HwRasterizer.h" #include "HwRasterizer.h"
#include "LogManager.h" #include "LogManager.h"
#include "EfbInterface.h" #include "EfbInterface.h"
#include "DebugUtil.h"
PLUGIN_GLOBALS* globals = NULL; PLUGIN_GLOBALS* globals = NULL;
@ -88,6 +89,7 @@ void Initialize(void *init)
Rasterizer::Init(); Rasterizer::Init();
HwRasterizer::Init(); HwRasterizer::Init();
Renderer::Init(_pVideoInitialize); Renderer::Init(_pVideoInitialize);
DebugUtil::Init();
} }
void DoState(unsigned char **ptr, int mode) void DoState(unsigned char **ptr, int mode)
@ -109,6 +111,7 @@ void Video_Prepare(void)
// Run from the CPU thread (from VideoInterface.cpp) // Run from the CPU thread (from VideoInterface.cpp)
void Video_BeginField(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight) void Video_BeginField(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight)
{ {
g_VideoInitialize.pCopiedToXFB(true);
} }
// Run from the CPU thread (from VideoInterface.cpp) // Run from the CPU thread (from VideoInterface.cpp)