diff --git a/gsdx/GPUDrawScanline.cpp b/gsdx/GPUDrawScanline.cpp index 8f30031..d2aab01 100644 --- a/gsdx/GPUDrawScanline.cpp +++ b/gsdx/GPUDrawScanline.cpp @@ -93,22 +93,45 @@ void GPUDrawScanline::SetupDraw(Vertex* vertices, int count, const void* texture m_slenv.md = GSVector4i(env.STATUS.MD ? 0x80008000 : 0); } -void GPUDrawScanline::SetupScanline(const Vertex& dv) +void GPUDrawScanline::SetupPrim(PrimitiveType type, const Vertex* vertices, const Vertex& dscan) { + if(m_sel.tme && !m_sel.twin) + { + GSVector4i t; + + switch(type) + { + case Sprite: + t = (GSVector4i(vertices[1].t) >> 8) - GSVector4i::x00000001(); + t = t.ps32(t); + t = t.upl16(t); + m_slenv.u[2] = t.xxxx(); + m_slenv.v[2] = t.yyyy(); + break; + default: + m_slenv.u[2] = GSVector4i::x00ff(); + m_slenv.v[2] = GSVector4i::x00ff(); + break; + } + } + // we could use integers here but it's more accurate to multiply a float than a 8.8 fixed point number GSVector4 ps0123 = GSVector4::ps0123(); GSVector4 ps4567 = GSVector4::ps4567(); - GSVector4i dtc8 = GSVector4i(dv.t * 8.0f).ps32(GSVector4i(dv.c * 8.0f)); + GSVector4 dt = dscan.t; + GSVector4 dc = dscan.c; - m_slenv.ds = GSVector4i(dv.t.xxxx() * ps0123).ps32(GSVector4i(dv.t.xxxx() * ps4567)); - m_slenv.dt = GSVector4i(dv.t.yyyy() * ps0123).ps32(GSVector4i(dv.t.yyyy() * ps4567)); + GSVector4i dtc8 = GSVector4i(dt * 8.0f).ps32(GSVector4i(dc * 8.0f)); + + m_slenv.ds = GSVector4i(dt.xxxx() * ps0123).ps32(GSVector4i(dt.xxxx() * ps4567)); + m_slenv.dt = GSVector4i(dt.yyyy() * ps0123).ps32(GSVector4i(dt.yyyy() * ps4567)); m_slenv.dst8 = dtc8.upl16(dtc8); - m_slenv.dr = GSVector4i(dv.c.xxxx() * ps0123).ps32(GSVector4i(dv.c.xxxx() * ps4567)); - m_slenv.dg = GSVector4i(dv.c.yyyy() * ps0123).ps32(GSVector4i(dv.c.yyyy() * ps4567)); - m_slenv.db = GSVector4i(dv.c.zzzz() * ps0123).ps32(GSVector4i(dv.c.zzzz() * ps4567)); + m_slenv.dr = GSVector4i(dc.xxxx() * ps0123).ps32(GSVector4i(dc.xxxx() * ps4567)); + m_slenv.dg = GSVector4i(dc.yyyy() * ps0123).ps32(GSVector4i(dc.yyyy() * ps4567)); + m_slenv.db = GSVector4i(dc.zzzz() * ps0123).ps32(GSVector4i(dc.zzzz() * ps4567)); m_slenv.dc8 = dtc8.uph16(dtc8); } @@ -153,6 +176,13 @@ void GPUDrawScanline::SampleTexture(int pixels, DWORD ltf, DWORD tlu, DWORD twin u1 = (u1 & m_slenv.u[0]).add16(m_slenv.u[1]); v1 = (v1 & m_slenv.v[0]).add16(m_slenv.v[1]); } + else + { + u0 = u0.min_i16(m_slenv.u[2]); + v0 = v0.min_i16(m_slenv.v[2]); + u1 = u1.min_i16(m_slenv.u[2]); + v1 = v1.min_i16(m_slenv.v[2]); + } GSVector4i addr00 = v0.sll16(8) | u0; GSVector4i addr01 = v0.sll16(8) | u1; @@ -271,6 +301,11 @@ void GPUDrawScanline::SampleTexture(int pixels, DWORD ltf, DWORD tlu, DWORD twin u = (u & m_slenv.u[0]).add16(m_slenv.u[1]); v = (v & m_slenv.v[0]).add16(m_slenv.v[1]); } + else + { + u = u.min_i16(m_slenv.u[2]); + v = v.min_i16(m_slenv.v[2]); + } GSVector4i addr = v.sll16(8) | u; diff --git a/gsdx/GPUDrawScanline.h b/gsdx/GPUDrawScanline.h index d339fd1..fb11b9e 100644 --- a/gsdx/GPUDrawScanline.h +++ b/gsdx/GPUDrawScanline.h @@ -64,8 +64,8 @@ class GPUDrawScanline : public GSAlignedClass<16>, public IDrawScanline const void* tex; const WORD* clut; - GSVector4i u[2]; - GSVector4i v[2]; + GSVector4i u[3]; + GSVector4i v[3]; GSVector4i a; GSVector4i md; // similar to gs fba @@ -105,7 +105,7 @@ public: // IDrawScanline void SetupDraw(Vertex* vertices, int count, const void* texture); - void SetupScanline(const Vertex& dv); + void SetupPrim(PrimitiveType type, const Vertex* vertices, const Vertex& dscan); void DrawScanline(int top, int left, int right, const Vertex& v); void FillRect(const GSVector4i& r, const Vertex& v); DrawScanlinePtr GetDrawScanlinePtr(); diff --git a/gsdx/GSDrawScanline.cpp b/gsdx/GSDrawScanline.cpp index d7a61e8..2b1d180 100644 --- a/gsdx/GSDrawScanline.cpp +++ b/gsdx/GSDrawScanline.cpp @@ -250,7 +250,7 @@ void GSDrawScanline::SetupDraw(Vertex* vertices, int count, const void* texture) } } -void GSDrawScanline::SetupScanline(const Vertex& dv) +void GSDrawScanline::SetupPrim(PrimitiveType type, const Vertex* vertices, const Vertex& dv) { GSVector4 ps0123 = GSVector4::ps0123(); diff --git a/gsdx/GSDrawScanline.h b/gsdx/GSDrawScanline.h index 0a1dd34..3aa2196 100644 --- a/gsdx/GSDrawScanline.h +++ b/gsdx/GSDrawScanline.h @@ -151,7 +151,7 @@ public: // IDrawScanline void SetupDraw(Vertex* vertices, int count, const void* texture); - void SetupScanline(const Vertex& dv); + void SetupPrim(PrimitiveType type, const Vertex* vertices, const Vertex& dv); void DrawScanline(int top, int left, int right, const Vertex& v); void FillRect(const GSVector4i& r, const Vertex& v); DrawScanlinePtr GetDrawScanlinePtr(); diff --git a/gsdx/GSRasterizer.cpp b/gsdx/GSRasterizer.cpp index e6c4bdc..0ce78d0 100644 --- a/gsdx/GSRasterizer.cpp +++ b/gsdx/GSRasterizer.cpp @@ -168,7 +168,7 @@ void GSRasterizer::DrawTriangleTop(Vertex* v, const GSVector4i& scissor) r += dr * dy; } - m_ds->SetupScanline(dscan); + m_ds->SetupPrim(IDrawScanline::Triangle, v, dscan); DrawTriangleSection(top, bottom, l, dl, r, dr, dscan, scissor); } @@ -215,8 +215,8 @@ void GSRasterizer::DrawTriangleBottom(Vertex* v, const GSVector4i& scissor) l += dl * dy; r += dr * dy; } - - m_ds->SetupScanline(dscan); + + m_ds->SetupPrim(IDrawScanline::Triangle, v, dscan); DrawTriangleSection(top, bottom, l, dl, r, dr, dscan, scissor); } @@ -238,7 +238,7 @@ void GSRasterizer::DrawTriangleTopBottom(Vertex* v, const GSVector4i& scissor) Vertex dscan = longest * longest.p.xxxx().rcp(); - m_ds->SetupScanline(dscan); + m_ds->SetupPrim(IDrawScanline::Triangle, v, dscan); Vertex& l = v[0]; GSVector4 r = v[0].p; @@ -446,7 +446,7 @@ void GSRasterizer::DrawSprite(Vertex* vertices, const GSVector4i& scissor, bool if(scan.p.y < (float)top) scan.t += dedge.t * ((float)top - scan.p.y); if(scan.p.x < (float)left) scan.t += dscan.t * ((float)left - scan.p.x); - m_ds->SetupScanline(dscan); + m_ds->SetupPrim(IDrawScanline::Sprite, v, dscan); IDrawScanline::DrawScanlinePtr dsf = m_ds->GetDrawScanlinePtr(); diff --git a/gsdx/GSRasterizer.h b/gsdx/GSRasterizer.h index 6a4fd35..89f9e8d 100644 --- a/gsdx/GSRasterizer.h +++ b/gsdx/GSRasterizer.h @@ -31,10 +31,12 @@ public: typedef GSVertexSW Vertex; typedef void (IDrawScanline::*DrawScanlinePtr)(int top, int left, int right, const Vertex& v); + enum PrimitiveType {Point, Line, Triangle, Sprite}; + virtual ~IDrawScanline() {} virtual void SetupDraw(Vertex* vertices, int count, const void* texture) = 0; - virtual void SetupScanline(const Vertex& dv) = 0; + virtual void SetupPrim(PrimitiveType type, const Vertex* vertices, const Vertex& dscan) = 0; virtual void DrawScanline(int top, int left, int right, const Vertex& v) = 0; virtual void FillRect(const GSVector4i& r, const Vertex& v) = 0; virtual DrawScanlinePtr GetDrawScanlinePtr() = 0;