GSdx: adapted to ref's changes to the image transfer, it was a bug in GSdx but not triggered by the old way, also the data overflow is now ignored, no idea what it may cause, look out for missing or fixed textures.

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@1005 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
gabest11 2009-04-18 09:34:25 +00:00
parent f51e6b7d91
commit 94e2bd9409
4 changed files with 149 additions and 156 deletions

View File

@ -43,7 +43,6 @@ public:
GIFRegTRXDIR TRXDIR; GIFRegTRXDIR TRXDIR;
GIFRegTRXPOS TRXPOS; GIFRegTRXPOS TRXPOS;
GIFRegTRXREG TRXREG; GIFRegTRXREG TRXREG;
GIFRegTRXREG TRXREG2;
GSDrawingContext CTXT[2]; GSDrawingContext CTXT[2];
GSDrawingEnvironment() GSDrawingEnvironment()
@ -67,7 +66,6 @@ public:
memset(&TRXDIR, 0, sizeof(TRXDIR)); memset(&TRXDIR, 0, sizeof(TRXDIR));
memset(&TRXPOS, 0, sizeof(TRXPOS)); memset(&TRXPOS, 0, sizeof(TRXPOS));
memset(&TRXREG, 0, sizeof(TRXREG)); memset(&TRXREG, 0, sizeof(TRXREG));
memset(&TRXREG2, 0, sizeof(TRXREG2));
CTXT[0].Reset(); CTXT[0].Reset();
CTXT[1].Reset(); CTXT[1].Reset();

View File

@ -896,7 +896,7 @@ void GSLocalMemory::WriteImage(int& tx, int& ty, BYTE* src, int len, GIFRegBITBL
if(TRXREG.RRW == 0) return; if(TRXREG.RRW == 0) return;
int l = (int)TRXPOS.DSAX; int l = (int)TRXPOS.DSAX;
int r = (int)TRXREG.RRW; int r = l + (int)TRXREG.RRW;
// finish the incomplete row first // finish the incomplete row first
@ -913,9 +913,7 @@ void GSLocalMemory::WriteImage(int& tx, int& ty, BYTE* src, int len, GIFRegBITBL
int srcpitch = (r - l) * trbpp >> 3; int srcpitch = (r - l) * trbpp >> 3;
int h = len / srcpitch; int h = len / srcpitch;
// transfer width >= block width, and there is at least one full row if(ra - la >= bsx && h > 0) // "transfer width" >= "block width" && there is at least one full row
if(ra - la >= bsx && h > 0)
{ {
BYTE* s = &src[-l * trbpp >> 3]; BYTE* s = &src[-l * trbpp >> 3];
@ -1009,7 +1007,7 @@ void GSLocalMemory::WriteImage24(int& tx, int& ty, BYTE* src, int len, GIFRegBIT
DWORD bp = BITBLTBUF.DBP; DWORD bp = BITBLTBUF.DBP;
DWORD bw = BITBLTBUF.DBW; DWORD bw = BITBLTBUF.DBW;
int tw = TRXREG.RRW, srcpitch = (TRXREG.RRW - TRXPOS.DSAX) * 3; int tw = TRXPOS.DSAX + TRXREG.RRW, srcpitch = TRXREG.RRW * 3;
int th = len / srcpitch; int th = len / srcpitch;
bool aligned = IsTopLeftAligned(TRXPOS.DSAX, tx, ty, 8, 8); bool aligned = IsTopLeftAligned(TRXPOS.DSAX, tx, ty, 8, 8);
@ -1035,6 +1033,7 @@ void GSLocalMemory::WriteImage24(int& tx, int& ty, BYTE* src, int len, GIFRegBIT
ty = th; ty = th;
} }
} }
void GSLocalMemory::WriteImage8H(int& tx, int& ty, BYTE* src, int len, GIFRegBITBLTBUF& BITBLTBUF, GIFRegTRXPOS& TRXPOS, GIFRegTRXREG& TRXREG) void GSLocalMemory::WriteImage8H(int& tx, int& ty, BYTE* src, int len, GIFRegBITBLTBUF& BITBLTBUF, GIFRegTRXPOS& TRXPOS, GIFRegTRXREG& TRXREG)
{ {
if(TRXREG.RRW == 0) return; if(TRXREG.RRW == 0) return;
@ -1042,7 +1041,7 @@ void GSLocalMemory::WriteImage8H(int& tx, int& ty, BYTE* src, int len, GIFRegBIT
DWORD bp = BITBLTBUF.DBP; DWORD bp = BITBLTBUF.DBP;
DWORD bw = BITBLTBUF.DBW; DWORD bw = BITBLTBUF.DBW;
int tw = TRXREG.RRW, srcpitch = TRXREG.RRW - TRXPOS.DSAX; int tw = TRXPOS.DSAX + TRXREG.RRW, srcpitch = TRXREG.RRW;
int th = len / srcpitch; int th = len / srcpitch;
bool aligned = IsTopLeftAligned(TRXPOS.DSAX, tx, ty, 8, 8); bool aligned = IsTopLeftAligned(TRXPOS.DSAX, tx, ty, 8, 8);
@ -1076,7 +1075,7 @@ void GSLocalMemory::WriteImage4HL(int& tx, int& ty, BYTE* src, int len, GIFRegBI
DWORD bp = BITBLTBUF.DBP; DWORD bp = BITBLTBUF.DBP;
DWORD bw = BITBLTBUF.DBW; DWORD bw = BITBLTBUF.DBW;
int tw = TRXREG.RRW, srcpitch = (TRXREG.RRW - TRXPOS.DSAX) / 2; int tw = TRXPOS.DSAX + TRXREG.RRW, srcpitch = TRXREG.RRW / 2;
int th = len / srcpitch; int th = len / srcpitch;
bool aligned = IsTopLeftAligned(TRXPOS.DSAX, tx, ty, 8, 8); bool aligned = IsTopLeftAligned(TRXPOS.DSAX, tx, ty, 8, 8);
@ -1110,7 +1109,7 @@ void GSLocalMemory::WriteImage4HH(int& tx, int& ty, BYTE* src, int len, GIFRegBI
DWORD bp = BITBLTBUF.DBP; DWORD bp = BITBLTBUF.DBP;
DWORD bw = BITBLTBUF.DBW; DWORD bw = BITBLTBUF.DBW;
int tw = TRXREG.RRW, srcpitch = (TRXREG.RRW - TRXPOS.DSAX) / 2; int tw = TRXPOS.DSAX + TRXREG.RRW, srcpitch = TRXREG.RRW / 2;
int th = len / srcpitch; int th = len / srcpitch;
bool aligned = IsTopLeftAligned(TRXPOS.DSAX, tx, ty, 8, 8); bool aligned = IsTopLeftAligned(TRXPOS.DSAX, tx, ty, 8, 8);
@ -1143,7 +1142,7 @@ void GSLocalMemory::WriteImage24Z(int& tx, int& ty, BYTE* src, int len, GIFRegBI
DWORD bp = BITBLTBUF.DBP; DWORD bp = BITBLTBUF.DBP;
DWORD bw = BITBLTBUF.DBW; DWORD bw = BITBLTBUF.DBW;
int tw = TRXREG.RRW, srcpitch = (TRXREG.RRW - TRXPOS.DSAX) * 3; int tw = TRXPOS.DSAX + TRXREG.RRW, srcpitch = TRXREG.RRW * 3;
int th = len / srcpitch; int th = len / srcpitch;
bool aligned = IsTopLeftAligned(TRXPOS.DSAX, tx, ty, 8, 8); bool aligned = IsTopLeftAligned(TRXPOS.DSAX, tx, ty, 8, 8);
@ -1173,8 +1172,6 @@ void GSLocalMemory::WriteImageX(int& tx, int& ty, BYTE* src, int len, GIFRegBITB
{ {
if(len <= 0) return; if(len <= 0) return;
// if(ty >= (int)TRXREG.RRH) {ASSERT(0); return;}
BYTE* pb = (BYTE*)src; BYTE* pb = (BYTE*)src;
WORD* pw = (WORD*)src; WORD* pw = (WORD*)src;
DWORD* pd = (DWORD*)src; DWORD* pd = (DWORD*)src;
@ -1186,7 +1183,7 @@ void GSLocalMemory::WriteImageX(int& tx, int& ty, BYTE* src, int len, GIFRegBITB
int x = tx; int x = tx;
int y = ty; int y = ty;
int sx = (int)TRXPOS.DSAX; int sx = (int)TRXPOS.DSAX;
int ex = (int)TRXREG.RRW; int ex = sx + (int)TRXREG.RRW;
switch(BITBLTBUF.DPSM) switch(BITBLTBUF.DPSM)
{ {
@ -1351,8 +1348,6 @@ void GSLocalMemory::ReadImageX(int& tx, int& ty, BYTE* dst, int len, GIFRegBITBL
{ {
if(len <= 0) return; if(len <= 0) return;
// if(ty >= (int)TRXREG.RRH) {ASSERT(0); return;}
BYTE* pb = (BYTE*)dst; BYTE* pb = (BYTE*)dst;
WORD* pw = (WORD*)dst; WORD* pw = (WORD*)dst;
DWORD* pd = (DWORD*)dst; DWORD* pd = (DWORD*)dst;
@ -1364,7 +1359,7 @@ void GSLocalMemory::ReadImageX(int& tx, int& ty, BYTE* dst, int len, GIFRegBITBL
int x = tx; int x = tx;
int y = ty; int y = ty;
int sx = (int)TRXPOS.SSAX; int sx = (int)TRXPOS.SSAX;
int ex = (int)TRXREG.RRW; int ex = sx + (int)TRXREG.RRW;
switch(BITBLTBUF.SPSM) switch(BITBLTBUF.SPSM)
{ {

View File

@ -52,7 +52,7 @@ GSState::GSState(BYTE* base, bool mt, void (*irq)())
m_sssize += sizeof(m_env.TRXDIR); m_sssize += sizeof(m_env.TRXDIR);
m_sssize += sizeof(m_env.TRXPOS); m_sssize += sizeof(m_env.TRXPOS);
m_sssize += sizeof(m_env.TRXREG); m_sssize += sizeof(m_env.TRXREG);
m_sssize += sizeof(m_env.TRXREG2); m_sssize += sizeof(m_env.TRXREG); // obsolete
for(int i = 0; i < 2; i++) for(int i = 0; i < 2; i++)
{ {
@ -77,8 +77,8 @@ GSState::GSState(BYTE* base, bool mt, void (*irq)())
m_sssize += sizeof(m_v.XYZ); m_sssize += sizeof(m_v.XYZ);
m_sssize += sizeof(m_v.FOG); m_sssize += sizeof(m_v.FOG);
m_sssize += sizeof(m_x); m_sssize += sizeof(m_tr.x);
m_sssize += sizeof(m_y); m_sssize += sizeof(m_tr.y);
m_sssize += m_mem.m_vmsize; m_sssize += m_mem.m_vmsize;
m_sssize += (sizeof(m_path[0].tag) + sizeof(m_path[0].nreg)) * 3; m_sssize += (sizeof(m_path[0].tag) + sizeof(m_path[0].nreg)) * 3;
m_sssize += sizeof(m_q); m_sssize += sizeof(m_q);
@ -93,11 +93,6 @@ GSState::GSState(BYTE* base, bool mt, void (*irq)())
// CSR->rREV = 0x20; // CSR->rREV = 0x20;
m_env.PRMODECONT.AC = 1; m_env.PRMODECONT.AC = 1;
m_x = m_y = 0;
m_bytes = 0;
m_maxbytes = 1024 * 1024 * 4;
m_buff = (BYTE*)_aligned_malloc(m_maxbytes, 16);
Reset(); Reset();
ResetHandlers(); ResetHandlers();
@ -105,7 +100,6 @@ GSState::GSState(BYTE* base, bool mt, void (*irq)())
GSState::~GSState() GSState::~GSState()
{ {
_aligned_free(m_buff);
} }
void GSState::Reset() void GSState::Reset()
@ -916,13 +910,12 @@ void GSState::GIFRegHandlerTRXPOS(GIFReg* r)
void GSState::GIFRegHandlerTRXREG(GIFReg* r) void GSState::GIFRegHandlerTRXREG(GIFReg* r)
{ {
if(!(m_env.TRXREG == (GSVector4i)r->TRXREG).alltrue() || !(m_env.TRXREG2 == (GSVector4i)r->TRXREG).alltrue()) if(!(m_env.TRXREG == (GSVector4i)r->TRXREG).alltrue())
{ {
FlushWrite(); FlushWrite();
} }
m_env.TRXREG = (GSVector4i)r->TRXREG; m_env.TRXREG = (GSVector4i)r->TRXREG;
m_env.TRXREG2 = (GSVector4i)r->TRXREG;
} }
void GSState::GIFRegHandlerTRXDIR(GIFReg* r) void GSState::GIFRegHandlerTRXDIR(GIFReg* r)
@ -934,16 +927,10 @@ void GSState::GIFRegHandlerTRXDIR(GIFReg* r)
switch(m_env.TRXDIR.XDIR) switch(m_env.TRXDIR.XDIR)
{ {
case 0: // host -> local case 0: // host -> local
m_x = m_env.TRXPOS.DSAX; m_tr.Init(m_env.TRXPOS.DSAX, m_env.TRXPOS.DSAY);
m_y = m_env.TRXPOS.DSAY;
m_env.TRXREG.RRW = m_x + m_env.TRXREG2.RRW;
m_env.TRXREG.RRH = m_y + m_env.TRXREG2.RRH;
break; break;
case 1: // local -> host case 1: // local -> host
m_x = m_env.TRXPOS.SSAX; m_tr.Init(m_env.TRXPOS.SSAX, m_env.TRXPOS.SSAY);
m_y = m_env.TRXPOS.SSAY;
m_env.TRXREG.RRW = m_x + m_env.TRXREG2.RRW;
m_env.TRXREG.RRH = m_y + m_env.TRXREG2.RRH;
break; break;
case 2: // local -> local case 2: // local -> local
Move(); Move();
@ -997,113 +984,66 @@ void GSState::Flush()
void GSState::FlushWrite() void GSState::FlushWrite()
{ {
FlushWrite(m_buff, m_bytes); int len = m_tr.end - m_tr.start;
m_bytes = 0; if(len <= 0) return;
}
void GSState::FlushWrite(BYTE* mem, int len) int y = m_tr.y;
{
if(len > 0) GSLocalMemory::writeImage wi = GSLocalMemory::m_psm[m_env.BITBLTBUF.DPSM].wi;
{
(m_mem.*wi)(m_tr.x, m_tr.y, &m_tr.buff[m_tr.start], len, m_env.BITBLTBUF, m_env.TRXPOS, m_env.TRXREG);
m_tr.start += len;
m_perfmon.Put(GSPerfMon::Swizzle, len);
CRect r;
r.left = m_env.TRXPOS.DSAX;
r.top = y;
r.right = r.left + m_env.TRXREG.RRW;
r.bottom = min(r.top + m_env.TRXREG.RRH, m_tr.x == r.left ? m_tr.y : m_tr.y + 1);
InvalidateVideoMem(m_env.BITBLTBUF, r);
/* /*
CSize bs = GSLocalMemory::m_psm[m_env.BITBLTBUF.DPSM].bs; static int n = 0;
CString str;
if((m_x & (bs.cx - 1)) || (m_env.TRXREG.RRW & (bs.cx - 1)) str.Format(_T("c:\\temp1\\[%04d]_%05x_%d_%d_%d_%d_%d_%d.bmp"),
|| (m_y & (bs.cy - 1)) || (m_env.TRXREG.RRH & (bs.cy - 1)) n++, (int)m_env.BITBLTBUF.DBP, (int)m_env.BITBLTBUF.DBW, (int)m_env.BITBLTBUF.DPSM,
|| m_x != m_env.TRXPOS.DSAX) r.left, r.top, r.right, r.bottom);
{ m_mem.SaveBMP(str, m_env.BITBLTBUF.DBP, m_env.BITBLTBUF.DBW, m_env.BITBLTBUF.DPSM, r.right, r.bottom);
printf("*** [%d]: %d %d, %d %d %d %d\n", m_env.BITBLTBUF.DPSM, m_env.TRXPOS.DSAX, m_env.TRXPOS.DSAY, m_x, m_y, m_env.TRXREG.RRW, m_env.TRXREG.RRH);
}
if((len % ((m_env.TRXREG.RRW - m_x) * GSLocalMemory::m_psm[m_env.BITBLTBUF.DPSM].trbpp / 8)) != 0)
{
printf("*** [%d]: %d %d\n", m_env.BITBLTBUF.DPSM, len, ((m_env.TRXREG.RRW - m_x) * GSLocalMemory::m_psm[m_env.BITBLTBUF.DPSM].trbpp / 8));
}
*/ */
int y = m_y;
GSLocalMemory::writeImage wi = GSLocalMemory::m_psm[m_env.BITBLTBUF.DPSM].wi;
(m_mem.*wi)(m_x, m_y, mem, len, m_env.BITBLTBUF, m_env.TRXPOS, m_env.TRXREG);
m_perfmon.Put(GSPerfMon::Swizzle, len);
//ASSERT(m_env.TRXREG.RRH >= m_y - y);
CRect r;
r.left = m_env.TRXPOS.DSAX;
r.top = y;
r.right = m_env.TRXREG.RRW;
r.bottom = min(m_x == m_env.TRXPOS.DSAX ? m_y : m_y + 1, m_env.TRXREG.RRH);
InvalidateVideoMem(m_env.BITBLTBUF, r);
/*
static int n = 0;
CString str;
str.Format(_T("c:\\temp1\\[%04d]_%05x_%d_%d_%d_%d_%d_%d.bmp"),
n++, (int)m_env.BITBLTBUF.DBP, (int)m_env.BITBLTBUF.DBW, (int)m_env.BITBLTBUF.DPSM,
r.left, r.top, r.right, r.bottom);
m_mem.SaveBMP(str, m_env.BITBLTBUF.DBP, m_env.BITBLTBUF.DBW, m_env.BITBLTBUF.DPSM, r.right, r.bottom);
*/
}
} }
// //
void GSState::Write(BYTE* mem, int len) void GSState::Write(BYTE* mem, int len)
{ {
/* int dx = m_env.TRXPOS.DSAX;
TRACE(_T("Write len=%d DBP=%05x DBW=%d DPSM=%d DSAX=%d DSAY=%d RRW=%d RRH=%d\n"), int dy = m_env.TRXPOS.DSAY;
len, (int)m_env.BITBLTBUF.DBP, (int)m_env.BITBLTBUF.DBW, (int)m_env.BITBLTBUF.DPSM, int w = m_env.TRXREG.RRW;
(int)m_env.TRXPOS.DSAX, (int)m_env.TRXPOS.DSAY, int h = m_env.TRXREG.RRH;
(int)m_env.TRXREG.RRW, (int)m_env.TRXREG.RRH);
*/
if(len == 0) return;
if(m_y >= m_env.TRXREG.RRH) return; // TODO: handle overflow during writing data too (just chop len below somewhere) // TRACE(_T("Write len=%d DBP=%05x DBW=%d DPSM=%d DSAX=%d DSAY=%d RRW=%d RRH=%d\n"), len, (int)m_env.BITBLTBUF.DBP, (int)m_env.BITBLTBUF.DBW, (int)m_env.BITBLTBUF.DPSM, dx, dy, w, h);
// TODO: hmmmm if(!m_tr.Update(w, h, GSLocalMemory::m_psm[m_env.BITBLTBUF.DPSM].trbpp, len))
{
return;
}
if(PRIM->TME && (m_env.BITBLTBUF.DBP == m_context->TEX0.TBP0 || m_env.BITBLTBUF.DBP == m_context->TEX0.CBP)) memcpy(&m_tr.buff[m_tr.end], mem, len);
m_tr.end += len;
if(PRIM->TME && (m_env.BITBLTBUF.DBP == m_context->TEX0.TBP0 || m_env.BITBLTBUF.DBP == m_context->TEX0.CBP)) // TODO: hmmmm
{ {
FlushPrim(); FlushPrim();
} }
int bpp = GSLocalMemory::m_psm[m_env.BITBLTBUF.DPSM].trbpp; if(m_tr.end >= m_tr.total)
int pitch = (m_env.TRXREG.RRW - m_env.TRXPOS.DSAX) * bpp >> 3;
if(pitch <= 0) {ASSERT(0); return;}
int height = len / pitch;
if(height > m_env.TRXREG.RRH - m_env.TRXPOS.DSAY)
{ {
height = m_env.TRXREG.RRH - m_env.TRXPOS.DSAY; FlushWrite();
len = height * pitch;
}
if(m_bytes > 0 || height < m_env.TRXREG.RRH - m_env.TRXPOS.DSAY)
{
ASSERT(len <= m_maxbytes); // more than 4mb into a 4mb local mem doesn't make sense
len = min(m_maxbytes, len);
if(m_bytes + len > m_maxbytes)
{
FlushWrite();
}
memcpy(&m_buff[m_bytes], mem, len);
m_bytes += len;
}
else
{
FlushWrite(mem, len);
} }
m_mem.m_clut.Invalidate(); m_mem.m_clut.Invalidate();
@ -1111,25 +1051,26 @@ void GSState::Write(BYTE* mem, int len)
void GSState::Read(BYTE* mem, int len) void GSState::Read(BYTE* mem, int len)
{ {
/* if(len <= 0) return;
TRACE(_T("Read len=%d SBP=%05x SBW=%d SPSM=%d SSAX=%d SSAY=%d RRW=%d RRH=%d\n"),
len, (int)m_env.BITBLTBUF.SBP, (int)m_env.BITBLTBUF.SBW, (int)m_env.BITBLTBUF.SPSM,
(int)m_env.TRXPOS.SSAX, (int)m_env.TRXPOS.SSAY,
(int)m_env.TRXREG.RRW, (int)m_env.TRXREG.RRH);
*/
if(m_y >= (int)m_env.TRXREG.RRH) {ASSERT(0); return;} int sx = m_env.TRXPOS.SSAX;
int sy = m_env.TRXPOS.SSAY;
int w = m_env.TRXREG.RRW;
int h = m_env.TRXREG.RRH;
if(m_x == m_env.TRXPOS.SSAX && m_y == m_env.TRXPOS.SSAY) // TRACE(_T("Read len=%d SBP=%05x SBW=%d SPSM=%d SSAX=%d SSAY=%d RRW=%d RRH=%d\n"), len, (int)m_env.BITBLTBUF.SBP, (int)m_env.BITBLTBUF.SBW, (int)m_env.BITBLTBUF.SPSM, sx, sy, w, h);
if(!m_tr.Update(w, h, GSLocalMemory::m_psm[m_env.BITBLTBUF.SPSM].trbpp, len))
{ {
CRect r(m_env.TRXPOS.SSAX, m_env.TRXPOS.SSAY, m_env.TRXREG.RRW, m_env.TRXREG.RRH); return;
InvalidateLocalMem(m_env.BITBLTBUF, r);
} }
// TODO if(m_tr.x == sx && m_tr.y == sy)
{
InvalidateLocalMem(m_env.BITBLTBUF, CRect(CPoint(sx, sy), CSize(w, h)));
}
m_mem.ReadImageX(m_x, m_y, mem, len, m_env.BITBLTBUF, m_env.TRXPOS, m_env.TRXREG); m_mem.ReadImageX(m_tr.x, m_tr.y, mem, len, m_env.BITBLTBUF, m_env.TRXPOS, m_env.TRXREG);
} }
void GSState::Move() void GSState::Move()
@ -1138,19 +1079,20 @@ void GSState::Move()
// guitar hero copies the far end of the board to do a similar blend too // guitar hero copies the far end of the board to do a similar blend too
int sx = m_env.TRXPOS.SSAX; int sx = m_env.TRXPOS.SSAX;
int dx = m_env.TRXPOS.DSAX;
int sy = m_env.TRXPOS.SSAY; int sy = m_env.TRXPOS.SSAY;
int dx = m_env.TRXPOS.DSAX;
int dy = m_env.TRXPOS.DSAY; int dy = m_env.TRXPOS.DSAY;
int w = m_env.TRXREG.RRW; int w = m_env.TRXREG.RRW;
int h = m_env.TRXREG.RRH; int h = m_env.TRXREG.RRH;
int xinc = 1;
int yinc = 1;
InvalidateLocalMem(m_env.BITBLTBUF, CRect(CPoint(sx, sy), CSize(w, h))); InvalidateLocalMem(m_env.BITBLTBUF, CRect(CPoint(sx, sy), CSize(w, h)));
InvalidateVideoMem(m_env.BITBLTBUF, CRect(CPoint(dx, dy), CSize(w, h))); InvalidateVideoMem(m_env.BITBLTBUF, CRect(CPoint(dx, dy), CSize(w, h)));
if(sx < dx) sx += w-1, dx += w-1, xinc = -1; int xinc = 1;
if(sy < dy) sy += h-1, dy += h-1, yinc = -1; int yinc = 1;
if(sx < dx) {sx += w - 1; dx += w - 1; xinc = -1;}
if(sy < dy) {sy += h - 1; dy += h - 1; yinc = -1;}
/* /*
GSLocalMemory::readPixel rp = GSLocalMemory::m_psm[m_env.BITBLTBUF.SPSM].rp; GSLocalMemory::readPixel rp = GSLocalMemory::m_psm[m_env.BITBLTBUF.SPSM].rp;
@ -1166,7 +1108,7 @@ void GSState::Move()
if(m_env.BITBLTBUF.SPSM == PSM_PSMCT32 && m_env.BITBLTBUF.DPSM == PSM_PSMCT32) if(m_env.BITBLTBUF.SPSM == PSM_PSMCT32 && m_env.BITBLTBUF.DPSM == PSM_PSMCT32)
{ {
for(int y = 0; y < h; y++, sy += yinc, dy += yinc, sx -= xinc*w, dx -= xinc*w) for(int y = 0; y < h; y++, sy += yinc, dy += yinc, sx -= xinc * w, dx -= xinc * w)
{ {
DWORD sbase = spsm.pa(0, sy, m_env.BITBLTBUF.SBP, m_env.BITBLTBUF.SBW); DWORD sbase = spsm.pa(0, sy, m_env.BITBLTBUF.SBP, m_env.BITBLTBUF.SBW);
int* soffset = spsm.rowOffset[sy & 7]; int* soffset = spsm.rowOffset[sy & 7];
@ -1182,7 +1124,7 @@ void GSState::Move()
} }
else else
{ {
for(int y = 0; y < h; y++, sy += yinc, dy += yinc, sx -= xinc*w, dx -= xinc*w) for(int y = 0; y < h; y++, sy += yinc, dy += yinc, sx -= xinc * w, dx -= xinc * w)
{ {
DWORD sbase = spsm.pa(0, sy, m_env.BITBLTBUF.SBP, m_env.BITBLTBUF.SBW); DWORD sbase = spsm.pa(0, sy, m_env.BITBLTBUF.SBP, m_env.BITBLTBUF.SBW);
int* soffset = spsm.rowOffset[sy & 7]; int* soffset = spsm.rowOffset[sy & 7];
@ -1461,7 +1403,7 @@ int GSState::Freeze(GSFreezeData* fd, bool sizeonly)
WriteState(data, &m_env.TRXDIR); WriteState(data, &m_env.TRXDIR);
WriteState(data, &m_env.TRXPOS); WriteState(data, &m_env.TRXPOS);
WriteState(data, &m_env.TRXREG); WriteState(data, &m_env.TRXREG);
WriteState(data, &m_env.TRXREG2); WriteState(data, &m_env.TRXREG); // obsolete
for(int i = 0; i < 2; i++) for(int i = 0; i < 2; i++)
{ {
@ -1485,8 +1427,8 @@ int GSState::Freeze(GSFreezeData* fd, bool sizeonly)
WriteState(data, &m_v.UV); WriteState(data, &m_v.UV);
WriteState(data, &m_v.XYZ); WriteState(data, &m_v.XYZ);
WriteState(data, &m_v.FOG); WriteState(data, &m_v.FOG);
WriteState(data, &m_x); WriteState(data, &m_tr.x);
WriteState(data, &m_y); WriteState(data, &m_tr.y);
WriteState(data, m_mem.m_vm8, m_mem.m_vmsize); WriteState(data, m_mem.m_vm8, m_mem.m_vmsize);
for(int i = 0; i < 3; i++) for(int i = 0; i < 3; i++)
@ -1542,7 +1484,7 @@ int GSState::Defrost(const GSFreezeData* fd)
ReadState(&m_env.TRXDIR, data); ReadState(&m_env.TRXDIR, data);
ReadState(&m_env.TRXPOS, data); ReadState(&m_env.TRXPOS, data);
ReadState(&m_env.TRXREG, data); ReadState(&m_env.TRXREG, data);
ReadState(&m_env.TRXREG2, data); ReadState(&m_env.TRXREG, data); // obsolete
for(int i = 0; i < 2; i++) for(int i = 0; i < 2; i++)
{ {
@ -1574,10 +1516,12 @@ int GSState::Defrost(const GSFreezeData* fd)
ReadState(&m_v.UV, data); ReadState(&m_v.UV, data);
ReadState(&m_v.XYZ, data); ReadState(&m_v.XYZ, data);
ReadState(&m_v.FOG, data); ReadState(&m_v.FOG, data);
ReadState(&m_x, data); ReadState(&m_tr.x, data);
ReadState(&m_y, data); ReadState(&m_tr.y, data);
ReadState(m_mem.m_vm8, data, m_mem.m_vmsize); ReadState(m_mem.m_vm8, data, m_mem.m_vmsize);
m_tr.total = 0; // TODO: restore transfer state
for(int i = 0; i < 3; i++) for(int i = 0; i < 3; i++)
{ {
ReadState(&m_path[i].tag, data); ReadState(&m_path[i].tag, data);
@ -1670,6 +1614,53 @@ void GSState::SetFrameSkip(int frameskip)
} }
} }
// GSTransferBuffer
GSState::GSTransferBuffer::GSTransferBuffer()
{
x = y = 0;
start = end = total = 0;
buff = (BYTE*)_aligned_malloc(1024 * 1024 * 4, 16);
}
GSState::GSTransferBuffer::~GSTransferBuffer()
{
_aligned_free(buff);
}
void GSState::GSTransferBuffer::Init(int tx, int ty)
{
x = tx;
y = ty;
total = 0;
}
bool GSState::GSTransferBuffer::Update(int tw, int th, int bpp, int& len)
{
if(total == 0)
{
start = end = 0;
total = min((tw * bpp >> 3) * th, 1024 * 1024 * 4);
overflow = false;
}
int remaining = total - end;
if(len > remaining)
{
if(!overflow)
{
overflow = true;
// printf("GS transfer overflow\n");
}
len = remaining;
}
return len > 0;
}
// hacks // hacks
struct GSFrameInfo struct GSFrameInfo

View File

@ -113,13 +113,22 @@ class GSState : public GSAlignedClass<16>
void (*m_irq)(); void (*m_irq)();
bool m_path3hack; bool m_path3hack;
int m_x, m_y; struct GSTransferBuffer
int m_bytes; {
int m_maxbytes; int x, y;
BYTE* m_buff; int start, end, total;
bool overflow;
BYTE* buff;
GSTransferBuffer();
virtual ~GSTransferBuffer();
void Init(int tx, int ty);
bool Update(int tw, int th, int bpp, int& len);
} m_tr;
void FlushWrite(); void FlushWrite();
void FlushWrite(BYTE* mem, int len);
protected: protected:
bool IsBadFrame(int& skip); bool IsBadFrame(int& skip);