GSdx: ffxii fmv works again and even less bogus

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@1552 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
gabest11 2009-07-22 14:28:14 +00:00
parent 3a569dba23
commit 3599acc618
5 changed files with 103 additions and 68 deletions

View File

@ -26,6 +26,7 @@ GSRenderer::GSRenderer(uint8* base, bool mt, void (*irq)(), GSDevice* dev)
: GSState(base, mt, irq) : GSState(base, mt, irq)
, m_dev(dev) , m_dev(dev)
, m_shader(0) , m_shader(0)
, m_vt(this)
{ {
m_interlace = theApp.GetConfig("interlace", 0); m_interlace = theApp.GetConfig("interlace", 0);
m_aspectratio = theApp.GetConfig("aspectratio", 1); m_aspectratio = theApp.GetConfig("aspectratio", 1);

View File

@ -115,7 +115,7 @@ protected:
if(!m_dev->IsLost()) if(!m_dev->IsLost())
{ {
m_vt.Update(m_vertices, m_count, PRIM, m_context); m_vt.Update(m_vertices, m_count, GSUtil::GetPrimClass(PRIM->PRIM));
Draw(); Draw();
} }

View File

@ -37,68 +37,86 @@ class GSRendererHW : public GSRendererT<Vertex>
#pragma region hacks #pragma region hacks
typedef bool (GSRendererHW::*OI_Ptr)(int& prim, GSTexture* rt, GSTexture* ds, GSTextureCache::Source* t); typedef bool (GSRendererHW::*OI_Ptr)(GSTexture* rt, GSTexture* ds, GSTextureCache::Source* t);
typedef void (GSRendererHW::*OO_Ptr)(); typedef void (GSRendererHW::*OO_Ptr)();
typedef bool (GSRendererHW::*CU_Ptr)(); typedef bool (GSRendererHW::*CU_Ptr)();
bool OI_FFXII(int& prim, GSTexture* rt, GSTexture* ds, GSTextureCache::Source* t) bool OI_FFXII(GSTexture* rt, GSTexture* ds, GSTextureCache::Source* t)
{ {
static uint32* video = NULL; static uint32* video = NULL;
static bool ok = false; static int lines = 0;
if(prim == GS_POINTLIST && m_count >= 448 * 448 && m_count <= 448 * 512) if(lines == 0)
{ {
// incoming pixels are stored in columns, one column is 16x512, total res 448x512 or 448x454 if(m_vt.m_primclass == GS_LINE_CLASS && (m_count == 448 * 2 || m_count == 512 * 2))
if(!video) video = new uint32[512 * 512];
for(int x = 0, i = 0, rows = m_count / 448; x < 448; x += 16)
{ {
uint32* dst = &video[x]; lines = m_count / 2;
}
for(int y = 0; y < rows; y++, dst += 512) }
else
{
if(m_vt.m_primclass == GS_POINT_CLASS)
{
if(m_count >= 16 * 512)
{ {
for(int j = 0; j < 16; j++, i++) // incoming pixels are stored in columns, one column is 16x512, total res 448x512 or 448x454
if(!video) video = new uint32[512 * 512];
int ox = m_context->XYOFFSET.OFX;
int oy = m_context->XYOFFSET.OFY;
for(int i = 0; i < m_count; i++)
{ {
dst[j] = m_vertices[i].c0; int x = ((int)m_vertices[i].p.x - ox) >> 4;
int y = ((int)m_vertices[i].p.y - oy) >> 4;
// video[y * 448 + x] = m_vertices[i].c0;
video[(y << 8) + (y << 7) + (y << 6) + x] = m_vertices[i].c0;
} }
return false;
}
else
{
lines = 0;
} }
} }
else if(m_vt.m_primclass == GS_LINE_CLASS)
{
if(m_count == lines * 2)
{
// normally, this step would copy the video onto screen with 512 texture mapped horizontal lines,
// but we use the stored video data to create a new texture, and replace the lines with two triangles
ok = true; m_dev->Recycle(t->m_texture);
return false; t->m_texture = m_dev->CreateTexture(512, 512);
}
else if(prim == GS_LINELIST && m_count == 512 * 2 && ok)
{
// normally, this step would copy the video onto screen with 512 texture mapped horizontal lines,
// but we use the stored video data to create a new texture, and replace the lines with two triangles
ok = false; t->m_texture->Update(GSVector4i(0, 0, 448, lines), video, 448 * 4);
m_dev->Recycle(t->m_texture); m_vertices[0] = m_vertices[0];
m_vertices[1] = m_vertices[1];
m_vertices[2] = m_vertices[m_count - 2];
m_vertices[3] = m_vertices[1];
m_vertices[4] = m_vertices[2];
m_vertices[5] = m_vertices[m_count - 1];
t->m_texture = m_dev->CreateTexture(512, 512); m_count = 6;
t->m_texture->Update(GSVector4i(0, 0, 448, 512), video, 512 * 4); m_vt.Update(m_vertices, m_count, GS_TRIANGLE_CLASS);
}
m_vertices[0] = m_vertices[0]; else
m_vertices[1] = m_vertices[1]; {
m_vertices[2] = m_vertices[m_count - 2]; lines = 0;
m_vertices[3] = m_vertices[1]; }
m_vertices[4] = m_vertices[2]; }
m_vertices[5] = m_vertices[m_count - 1];
prim = GS_TRIANGLELIST;
m_count = 6;
return true;
} }
return true; return true;
} }
bool OI_FFX(int& prim, GSTexture* rt, GSTexture* ds, GSTextureCache::Source* t) bool OI_FFX(GSTexture* rt, GSTexture* ds, GSTextureCache::Source* t)
{ {
uint32 FBP = m_context->FRAME.Block(); uint32 FBP = m_context->FRAME.Block();
uint32 ZBP = m_context->ZBUF.Block(); uint32 ZBP = m_context->ZBUF.Block();
@ -114,7 +132,7 @@ class GSRendererHW : public GSRendererT<Vertex>
return true; return true;
} }
bool OI_MetalSlug6(int& prim, GSTexture* rt, GSTexture* ds, GSTextureCache::Source* t) bool OI_MetalSlug6(GSTexture* rt, GSTexture* ds, GSTextureCache::Source* t)
{ {
// missing red channel fix // missing red channel fix
@ -126,10 +144,12 @@ class GSRendererHW : public GSRendererT<Vertex>
} }
} }
m_vt.Update(m_vertices, m_count, m_vt.m_primclass);
return true; return true;
} }
bool OI_GodOfWar2(int& prim, GSTexture* rt, GSTexture* ds, GSTextureCache::Source* t) bool OI_GodOfWar2(GSTexture* rt, GSTexture* ds, GSTextureCache::Source* t)
{ {
uint32 FBP = m_context->FRAME.Block(); uint32 FBP = m_context->FRAME.Block();
uint32 FBW = m_context->FRAME.FBW; uint32 FBW = m_context->FRAME.FBW;
@ -156,7 +176,7 @@ class GSRendererHW : public GSRendererT<Vertex>
return true; return true;
} }
bool OI_SimpsonsGame(int& prim, GSTexture* rt, GSTexture* ds, GSTextureCache::Source* t) bool OI_SimpsonsGame(GSTexture* rt, GSTexture* ds, GSTextureCache::Source* t)
{ {
uint32 FBP = m_context->FRAME.Block(); uint32 FBP = m_context->FRAME.Block();
uint32 FBW = m_context->FRAME.FBW; uint32 FBW = m_context->FRAME.FBW;
@ -176,7 +196,7 @@ class GSRendererHW : public GSRendererT<Vertex>
return true; return true;
} }
bool OI_RozenMaidenGebetGarden(int& prim, GSTexture* rt, GSTexture* ds, GSTextureCache::Source* t) bool OI_RozenMaidenGebetGarden(GSTexture* rt, GSTexture* ds, GSTextureCache::Source* t)
{ {
if(!PRIM->TME) if(!PRIM->TME)
{ {
@ -222,9 +242,9 @@ class GSRendererHW : public GSRendererT<Vertex>
return true; return true;
} }
bool OI_PointListPalette(int& prim, GSTexture* rt, GSTexture* ds, GSTextureCache::Source* t) bool OI_PointListPalette(GSTexture* rt, GSTexture* ds, GSTextureCache::Source* t)
{ {
if(prim == GS_POINTLIST && !PRIM->TME) if(m_vt.m_primclass == GS_POINT_CLASS && !PRIM->TME)
{ {
uint32 FBP = m_context->FRAME.Block(); uint32 FBP = m_context->FRAME.Block();
uint32 FBW = m_context->FRAME.FBW; uint32 FBW = m_context->FRAME.FBW;
@ -586,9 +606,7 @@ protected:
s_n++; s_n++;
} }
int prim = PRIM->PRIM; if(m_hacks.m_oi && !(this->*m_hacks.m_oi)(rt->m_texture, ds->m_texture, tex))
if(m_hacks.m_oi && !(this->*m_hacks.m_oi)(prim, rt->m_texture, ds->m_texture, tex))
{ {
return; return;
} }

View File

@ -24,14 +24,20 @@
#include "stdafx.h" #include "stdafx.h"
#include "GSVertexTrace.h" #include "GSVertexTrace.h"
#include "GSUtil.h" #include "GSUtil.h"
#include "GSState.h"
uint32 GSVertexTrace::Hash(const GIFRegPRIM* PRIM, const GSDrawingContext* context) GSVertexTrace::GSVertexTrace(const GSState* state)
: m_state(state)
{ {
m_primclass = GSUtil::GetPrimClass(PRIM->PRIM); }
uint32 hash = m_primclass | (PRIM->IIP << 2) | (PRIM->TME << 3) | (PRIM->FST << 4); uint32 GSVertexTrace::Hash(GS_PRIM_CLASS primclass)
{
m_primclass = primclass;
if(!(PRIM->TME && context->TEX0.TFX == TFX_DECAL && context->TEX0.TCC)) uint32 hash = m_primclass | (m_state->PRIM->IIP << 2) | (m_state->PRIM->TME << 3) | (m_state->PRIM->FST << 4);
if(!(m_state->PRIM->TME && m_state->m_context->TEX0.TFX == TFX_DECAL && m_state->m_context->TEX0.TCC))
{ {
hash |= 1 << 5; hash |= 1 << 5;
} }
@ -39,18 +45,20 @@ uint32 GSVertexTrace::Hash(const GIFRegPRIM* PRIM, const GSDrawingContext* conte
return hash; return hash;
} }
void GSVertexTrace::Update(const GSVertexSW* v, int count, const GIFRegPRIM* PRIM, const GSDrawingContext* context) void GSVertexTrace::Update(const GSVertexSW* v, int count, GS_PRIM_CLASS primclass)
{ {
m_map_sw[Hash(PRIM, context)](v, count, m_min, m_max); m_map_sw[Hash(primclass)](v, count, m_min, m_max);
m_eq.value = (m_min.c == m_max.c).mask() | ((m_min.p == m_max.p).mask() << 16) | ((m_min.t == m_max.t).mask() << 20); m_eq.value = (m_min.c == m_max.c).mask() | ((m_min.p == m_max.p).mask() << 16) | ((m_min.t == m_max.t).mask() << 20);
m_alpha.valid = false; m_alpha.valid = false;
} }
void GSVertexTrace::Update(const GSVertexHW9* v, int count, const GIFRegPRIM* PRIM, const GSDrawingContext* context) void GSVertexTrace::Update(const GSVertexHW9* v, int count, GS_PRIM_CLASS primclass)
{ {
m_map_hw9[Hash(PRIM, context)](v, count, m_min, m_max); m_map_hw9[Hash(primclass)](v, count, m_min, m_max);
const GSDrawingContext* context = m_state->m_context;
GSVector4 o(context->XYOFFSET); GSVector4 o(context->XYOFFSET);
GSVector4 s(1.0f / 16, 1.0f / 16, 1.0f, 1.0f); GSVector4 s(1.0f / 16, 1.0f / 16, 1.0f, 1.0f);
@ -58,9 +66,9 @@ void GSVertexTrace::Update(const GSVertexHW9* v, int count, const GIFRegPRIM* PR
m_min.p = (m_min.p - o) * s; m_min.p = (m_min.p - o) * s;
m_max.p = (m_max.p - o) * s; m_max.p = (m_max.p - o) * s;
if(PRIM->TME) if(m_state->PRIM->TME)
{ {
if(PRIM->FST) if(m_state->PRIM->FST)
{ {
s = GSVector4(1 << (16 - 4), 1).xxyy(); s = GSVector4(1 << (16 - 4), 1).xxyy();
} }
@ -78,9 +86,11 @@ void GSVertexTrace::Update(const GSVertexHW9* v, int count, const GIFRegPRIM* PR
m_alpha.valid = false; m_alpha.valid = false;
} }
void GSVertexTrace::Update(const GSVertexHW10* v, int count, const GIFRegPRIM* PRIM, const GSDrawingContext* context) void GSVertexTrace::Update(const GSVertexHW10* v, int count, GS_PRIM_CLASS primclass)
{ {
m_map_hw10[Hash(PRIM, context)](v, count, m_min, m_max); m_map_hw10[Hash(primclass)](v, count, m_min, m_max);
const GSDrawingContext* context = m_state->m_context;
GSVector4 o(context->XYOFFSET); GSVector4 o(context->XYOFFSET);
GSVector4 s(1.0f / 16, 1.0f / 16, 2.0f, 1.0f); GSVector4 s(1.0f / 16, 1.0f / 16, 2.0f, 1.0f);
@ -88,9 +98,9 @@ void GSVertexTrace::Update(const GSVertexHW10* v, int count, const GIFRegPRIM* P
m_min.p = (m_min.p - o) * s; m_min.p = (m_min.p - o) * s;
m_max.p = (m_max.p - o) * s; m_max.p = (m_max.p - o) * s;
if(PRIM->TME) if(m_state->PRIM->TME)
{ {
if(PRIM->FST) if(m_state->PRIM->FST)
{ {
s = GSVector4(1 << (16 - 4), 1).xxyy(); s = GSVector4(1 << (16 - 4), 1).xxyy();
} }

View File

@ -29,6 +29,8 @@
#include "xbyak/xbyak.h" #include "xbyak/xbyak.h"
#include "xbyak/xbyak_util.h" #include "xbyak/xbyak_util.h"
class GSState;
__declspec(align(16)) class GSVertexTrace __declspec(align(16)) class GSVertexTrace
{ {
struct Vertex {GSVector4i c; GSVector4 p, t;}; struct Vertex {GSVector4i c; GSVector4 p, t;};
@ -83,7 +85,9 @@ __declspec(align(16)) class GSVertexTrace
GSVertexTraceMapHW9 m_map_hw9; GSVertexTraceMapHW9 m_map_hw9;
GSVertexTraceMapHW10 m_map_hw10; GSVertexTraceMapHW10 m_map_hw10;
uint32 Hash(const GIFRegPRIM* PRIM, const GSDrawingContext* context); uint32 Hash(GS_PRIM_CLASS primclass);
const GSState* m_state;
public: public:
GS_PRIM_CLASS m_primclass; GS_PRIM_CLASS m_primclass;
@ -97,8 +101,10 @@ public:
struct {uint32 rgba:16, xyzf:4, stq:4;}; struct {uint32 rgba:16, xyzf:4, stq:4;};
} m_eq; } m_eq;
void Update(const GSVertexSW* v, int count, const GIFRegPRIM* PRIM, const GSDrawingContext* context); GSVertexTrace(const GSState* state);
void Update(const GSVertexHW9* v, int count, const GIFRegPRIM* PRIM, const GSDrawingContext* context);
void Update(const GSVertexHW10* v, int count, const GIFRegPRIM* PRIM, const GSDrawingContext* context); void Update(const GSVertexSW* v, int count, GS_PRIM_CLASS primclass);
void Update(const GSVertexNull* v, int count, const GIFRegPRIM* PRIM, const GSDrawingContext* context) {} void Update(const GSVertexHW9* v, int count, GS_PRIM_CLASS primclass);
void Update(const GSVertexHW10* v, int count, GS_PRIM_CLASS primclass);
void Update(const GSVertexNull* v, int count, GS_PRIM_CLASS primclass) {}
}; };