From c671bba45a6244d838526bd4798a1e544deba898 Mon Sep 17 00:00:00 2001 From: arcum42 Date: Fri, 15 May 2009 01:06:59 +0000 Subject: [PATCH] GSnull: Add some Gif Transfer code from pcsx2 (not currently hooked in). git-svn-id: http://pcsx2.googlecode.com/svn/trunk@1185 96395faa-99c1-11dd-bbfe-3dabce05a288 --- plugins/GSnull/GifTransfer.cpp | 239 +++++++++++++++++++++++++++++++++ plugins/GSnull/GifTransfer.h | 88 ++++++++++++ plugins/GSnull/Makefile.am | 3 +- 3 files changed, 329 insertions(+), 1 deletion(-) create mode 100644 plugins/GSnull/GifTransfer.cpp create mode 100644 plugins/GSnull/GifTransfer.h diff --git a/plugins/GSnull/GifTransfer.cpp b/plugins/GSnull/GifTransfer.cpp new file mode 100644 index 0000000000..a692018424 --- /dev/null +++ b/plugins/GSnull/GifTransfer.cpp @@ -0,0 +1,239 @@ +/* GSnull + * Copyright (C) 2004-2009 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + // Processes a GIFtag & packet, and throws out some gsIRQs as needed. +// Used to keep interrupts in sync with the EE, while the GS itself +// runs potentially several frames behind. +// size - size of the packet in simd128's + +#include "GS.h" +#include "GifTransfer.h" + +using namespace std; + +static void RegHandlerSIGNAL(const u32* data) +{ + //MTGS_LOG("MTGS SIGNAL data %x_%x CSRw %x\n",data[0], data[1], CSRw); + + //GSSIGLBLID->SIGID = (GSSIGLBLID->SIGID&~data[1])|(data[0]&data[1]); + + //if ((CSRw & 0x1)) GSCSRr |= 1; // signal + + //if (!(GSIMR&0x100) ) gsIrq(); +} + +static void RegHandlerFINISH(const u32* data) +{ + //MTGS_LOG("MTGS FINISH data %x_%x CSRw %x\n",data[0], data[1], CSRw); + + //if ((CSRw & 0x2)) GSCSRr |= 2; // finish + + //if (!(GSIMR&0x200) ) gsIrq(); + +} + +static void RegHandlerLABEL(const u32* data) +{ + //GSSIGLBLID->LBLID = (GSSIGLBLID->LBLID&~data[1])|(data[0]&data[1]); +} + +typedef void (*GIFRegHandler)(const u32* data); +static GIFRegHandler s_GSHandlers[3] = +{ + RegHandlerSIGNAL, RegHandlerFINISH, RegHandlerLABEL +}; + +__forceinline void GIFPath::PrepRegs() +{ + if( tag.nreg == 0 ) + { + u32 tempreg = tag.regs[0]; + for(u32 i=0; i<16; ++i, tempreg >>= 4) + { + if( i == 8 ) tempreg = tag.regs[1]; + assert( (tempreg&0xf) < 0x64 ); + regs[i] = tempreg & 0xf; + } + } + else + { + u32 tempreg = tag.regs[0]; + for(u32 i=0; i>= 4) + { + assert( (tempreg&0xf) < 0x64 ); + regs[i] = tempreg & 0xf; + } + } +} + +void GIFPath::SetTag(const void* mem) +{ + tag = *((GIFTAG*)mem); + curreg = 0; + + PrepRegs(); +} + +u32 GIFPath::GetReg() +{ + return regs[curreg]; +} + +__forceinline u32 _gifTransfer( GIF_PATH pathidx, const u8* pMem, u32 size ) +{ + GIFPath& path = m_path[pathidx]; + + while(size > 0) + { + bool eop = false; + + if(path.tag.nloop == 0) + { + path.SetTag( pMem ); + + pMem += sizeof(GIFTAG); + --size; + + if(pathidx == 2 && path.tag.eop) + Path3transfer = FALSE; + + if( pathidx == 0 ) + { + // hack: if too much data for VU1, just ignore. + + // The GIF is evil : if nreg is 0, it's really 16. Otherwise it's the value in nreg. + const int numregs = ((path.tag.nreg - 1) & 15) + 1; + + if((path.tag.nloop * numregs) > (size * ((path.tag.flg == 1) ? 2 : 1))) + { + path.tag.nloop = 0; + return ++size; + } + } + + if(path.tag.eop) + { + eop = true; + } + else if(path.tag.nloop == 0) + { + if(pathidx == 0) + continue; + + eop = true; + } + } + + if(path.tag.nloop > 0) + { + switch(path.tag.flg) + { + case GIF_FLG_PACKED: + + while(size > 0) + { + if( path.GetReg() == 0xe ) + { + const int handler = pMem[8]; + if(handler >= 0x60 && handler < 0x63) + s_GSHandlers[handler & 0x3]((const u32*)pMem); + } + size--; + pMem += 16; // 128 bits! //sizeof(GIFPackedReg); + + if((++path.curreg & 0xf) == path.tag.nreg) + { + path.curreg = 0; + path.tag.nloop--; + + if(path.tag.nloop == 0) + break; + } + } + break; + + case GIF_FLG_REGLIST: + + size *= 2; + + while(size > 0) + { + const int handler = path.GetReg(); + if (handler >= 0x60 && handler < 0x63) + s_GSHandlers[handler&0x3]((const u32*)pMem); + + size--; + pMem += 8; //sizeof(GIFReg); -- 64 bits! + + if((++path.curreg & 0xf) == path.tag.nreg) + { + path.curreg = 0; + path.tag.nloop--; + + if(path.tag.nloop == 0) + { + break; + } + } + } + + if (size & 1) pMem += 8; //sizeof(GIFReg); + size /= 2; + + break; + + case GIF_FLG_IMAGE2: // hmmm + assert(0); + path.tag.nloop = 0; + + break; + + case GIF_FLG_IMAGE: + { + int len = (int)min(size, path.tag.nloop); + + pMem += len * 16; + path.tag.nloop -= len; + size -= len; + } + break; + + jNO_DEFAULT; + + } + } + + if (eop && ((int)size <= 0 || pathidx == 0)) + { + break; + } + } + + if(pathidx == 0) + { + if (!path.tag.eop && path.tag.nloop > 0) + { + path.tag.nloop = 0; + SysPrintf( "path1 hack! " ); + + // This means that the giftag data got screwly somewhere + // along the way (often means curreg was in a bad state or something) + } + } + return size; +} diff --git a/plugins/GSnull/GifTransfer.h b/plugins/GSnull/GifTransfer.h new file mode 100644 index 0000000000..019e99f521 --- /dev/null +++ b/plugins/GSnull/GifTransfer.h @@ -0,0 +1,88 @@ +/* GSnull + * Copyright (C) 2004-2009 PCSX2 Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include + + struct GSRegSIGBLID +{ + u32 SIGID; + u32 LBLID; +}; + +enum GIF_FLG +{ + GIF_FLG_PACKED = 0, + GIF_FLG_REGLIST = 1, + GIF_FLG_IMAGE = 2, + GIF_FLG_IMAGE2 = 3 +}; + +enum GIF_PATH +{ + GIF_PATH_1 = 0, + GIF_PATH_2, + GIF_PATH_3, +}; + +enum GIF_REG +{ + GIF_REG_PRIM = 0x00, + GIF_REG_RGBA = 0x01, + GIF_REG_STQ = 0x02, + GIF_REG_UV = 0x03, + GIF_REG_XYZF2 = 0x04, + GIF_REG_XYZ2 = 0x05, + GIF_REG_TEX0_1 = 0x06, + GIF_REG_TEX0_2 = 0x07, + GIF_REG_CLAMP_1 = 0x08, + GIF_REG_CLAMP_2 = 0x09, + GIF_REG_FOG = 0x0a, + GIF_REG_XYZF3 = 0x0c, + GIF_REG_XYZ3 = 0x0d, + GIF_REG_A_D = 0x0e, + GIF_REG_NOP = 0x0f, +}; + +struct GIFTAG +{ + u32 nloop : 15; + u32 eop : 1; + u32 dummy0 : 16; + u32 dummy1 : 14; + u32 pre : 1; + u32 prim : 11; + u32 flg : 2; + u32 nreg : 4; + u32 regs[2]; +}; + +struct GIFPath +{ + GIFTAG tag; + u32 curreg; + u32 _pad[3]; + u8 regs[16]; + + __forceinline void PrepRegs(); + void SetTag(const void* mem); + u32 GetReg(); +}; + + GIFPath m_path[3]; + bool Path3transfer; diff --git a/plugins/GSnull/Makefile.am b/plugins/GSnull/Makefile.am index d976e49677..872aa0e2a0 100644 --- a/plugins/GSnull/Makefile.am +++ b/plugins/GSnull/Makefile.am @@ -28,7 +28,8 @@ FW.h Linux/Config.h Linux/Linux.h libGSnull_a_SOURCES += \ Linux/interface.h Linux/support.c \ Linux/interface.c Linux/support.h \ -Linux/callbacks.h +Linux/callbacks.h \ +GifTransfer.cpp GifTransfer.h #Linux/callbacks.c #SUBDIRS = Linux \ No newline at end of file