/* ZZ Open GL graphics plugin * Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com * Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008 * * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #include "GS.h" #include "Mem.h" #include "NewRegs.h" #include "PS2Etypes.h" #include "zerogs.h" #include "targets.h" #ifdef USE_OLD_REGS #include "Regs.h" #else const u32 g_primmult[8] = { 1, 2, 2, 3, 3, 3, 2, 0xff }; const u32 g_primsub[8] = { 1, 2, 1, 3, 1, 1, 2, 0 }; #ifdef _MSC_VER #pragma warning(disable:4244) #endif GIFRegHandler g_GIFPackedRegHandlers[16]; GIFRegHandler g_GIFRegHandlers[256]; GIFRegHandler g_GIFTempRegHandlers[16] = {0}; // values for keeping track of changes u32 s_uTex1Data[2][2] = {{0, }}; u32 s_uClampData[2] = {0, }; u32 results[65535] = {0, }; // return true if triangle SHOULD be painted. // My brain hurts. --arcum42 inline bool NoHighlights(int i) { // This is hack-code, I still in search of correct reason, why some triangles should not be drawn. int resultA = prim->iip + ((prim->tme) << 1) + ((prim->fge) << 2) + ((prim->abe) << 3) + ((prim->aa1) << 4) + ((prim->fst) << 5) + ((prim->ctxt) << 6) + ((prim->fix) << 7) + ((ZeroGS::vb[i].zbuf.psm) << 8); const pixTest curtest = ZeroGS::vb[i].test; int result = curtest.ate + ((curtest.atst) << 1) + ((curtest.afail) << 4) + ((curtest.date) << 6) + ((curtest.datm) << 7) + ((curtest.zte) << 8) + ((curtest.ztst) << 9); if ((resultA == 0x3a2a || resultA == 0x312a) && (result == 0x302 || result == 0x700) && (ZeroGS::vb[i].zbuf.zmsk)) return false; // Silent Hill:SM and Front Mission 5, result != 0x300 if (((resultA == 0x3100) || (resultA == 0x3108)) && ((result == 0x54c) || (result == 0x50c)) && (ZeroGS::vb[i].zbuf.zmsk)) return false; // Okage if ((resultA == 0x310a) && (result == 0x0)) return false; // Radiata Stories if (resultA == 0x3a6a && (result == 0x300 || result == 0x500) && ZeroGS::vb[i].zbuf.zmsk) return false; // Okami, result != 0x30d // Old code return (!(conf.settings().xenosaga_spec) || !ZeroGS::vb[i].zbuf.zmsk || prim->iip) ; } void __fastcall GIFPackedRegHandlerNull(u32* data) { FUNCLOG ZZLog::Debug_Log("Unexpected packed reg handler %8.8lx_%8.8lx %x.", data[0], data[1], data[2]); } // All these just call their non-packed equivalent. void __fastcall GIFPackedRegHandlerPRIM(u32* data) { GIFRegHandlerPRIM(data); } void __fastcall GIFPackedRegHandlerTEX0_1(u32* data) { GIFRegHandlerTEX0_1(data); } void __fastcall GIFPackedRegHandlerTEX0_2(u32* data) { GIFRegHandlerTEX0_2(data); } void __fastcall GIFPackedRegHandlerCLAMP_1(u32* data) { GIFRegHandlerCLAMP_1(data); } void __fastcall GIFPackedRegHandlerCLAMP_2(u32* data) { GIFRegHandlerCLAMP_2(data); } void __fastcall GIFPackedRegHandlerXYZF3(u32* data) { GIFRegHandlerXYZF3(data); } void __fastcall GIFPackedRegHandlerXYZ3(u32* data) { GIFRegHandlerXYZ3(data); } void __fastcall GIFPackedRegHandlerRGBA(u32* data) { FUNCLOG GIFPackedRGBA* r = (GIFPackedRGBA*)(data); gs.rgba = (r->R | (r->G << 8) | (r->B << 16) | (r->A << 24)); gs.vertexregs.rgba = gs.rgba; gs.vertexregs.q = gs.q; ZZLog::Greg_Log("Packed RGBA: 0x%x", gs.rgba); } void __fastcall GIFPackedRegHandlerSTQ(u32* data) { FUNCLOG GIFPackedSTQ* r = (GIFPackedSTQ*)(data); gs.vertexregs.s = r->S; gs.vertexregs.t = r->T; gs.q = r->Q; ZZLog::Greg_Log("Packed STQ: 0x%x, 0x%x, %f", r->S, r->T, r->Q); } void __fastcall GIFPackedRegHandlerUV(u32* data) { FUNCLOG GIFPackedUV* r = (GIFPackedUV*)(data); gs.vertexregs.u = r->U; gs.vertexregs.v = r->V; ZZLog::Greg_Log("Packed UV: 0x%x, 0x%x", r->U, r->V); } void __forceinline KICK_VERTEX2() { FUNCLOG if (++gs.primC >= (int)g_primmult[prim->prim]) { if (NoHighlights(prim->ctxt)) (*ZeroGS::drawfn[prim->prim])(); gs.primC -= g_primsub[prim->prim]; } } void __forceinline KICK_VERTEX3() { FUNCLOG if (++gs.primC >= (int)g_primmult[prim->prim]) { gs.primC -= g_primsub[prim->prim]; if (prim->prim == 5) { /* tri fans need special processing */ if (gs.nTriFanVert == gs.primIndex) gs.primIndex = (gs.primIndex + 1) % ArraySize(gs.gsvertex); } } } void __fastcall GIFPackedRegHandlerXYZF2(u32* data) { FUNCLOG GIFPackedXYZF2* r = (GIFPackedXYZF2*)(data); gs.add_vertex(r->X, r->Y,r->Z, r->F); // Fix Vertexes up later. if (data[3] & 0x8000) { KICK_VERTEX3(); } else { KICK_VERTEX2(); } ZZLog::Greg_Log("Packed XYZF2: 0x%x, 0x%x, 0x%x, %f", r->X, r->Y, r->Z, r->F); } void __fastcall GIFPackedRegHandlerXYZ2(u32* data) { FUNCLOG GIFPackedXYZ2* r = (GIFPackedXYZ2*)(data); gs.add_vertex(r->X, r->Y,r->Z); // Fix Vertexes up later. if (data[3] & 0x8000) { KICK_VERTEX3(); } else { KICK_VERTEX2(); } ZZLog::Greg_Log("Packed XYZ2: 0x%x, 0x%x, 0x%x", r->X, r->Y, r->Z); } void __fastcall GIFPackedRegHandlerFOG(u32* data) { FUNCLOG GIFPackedFOG* r = (GIFPackedFOG*)(data); gs.vertexregs.f = r->F; ZZLog::Greg_Log("Packed FOG: 0x%x", r->F); } void __fastcall GIFPackedRegHandlerA_D(u32* data) { FUNCLOG GIFPackedA_D* r = (GIFPackedA_D*)(data); g_GIFRegHandlers[r->ADDR](data); ZZLog::Greg_Log("Packed A_D: 0x%x", r->ADDR); } void __fastcall GIFPackedRegHandlerNOP(u32* data) { FUNCLOG } void tex0Write(int i, u32 *data) { FUNCLOG // Used on Mana Khemias opening dialog. GIFRegTEX0* r = (GIFRegTEX0*)(data); u32 psm = ZZOglGet_psm_TexBitsFix(data[0]); if (m_Blocks[psm].bpp == 0) { // kh and others return; } // don't update unless necessary if (PSMT_ISCLUT(psm)) { if (ZeroGS::CheckChangeInClut(data[1], psm)) { // loading clut, so flush whole texture ZeroGS::vb[i].FlushTexData(); } else if (r->CSA != (ZeroGS::vb[i].uCurTex0.CSA)) { // check if csa is the same!! (ffx bisaid island, grass) ZeroGS::Flush(i); // flush any previous entries } } ZeroGS::vb[i].uNextTex0Data[0] = r->ai32[0]; ZeroGS::vb[i].uNextTex0Data[1] = r->ai32[1]; ZeroGS::vb[i].bNeedTexCheck = 1; } void tex2Write(int i, u32 *data) { FUNCLOG tex0Info& tex0 = ZeroGS::vb[i].tex0; ZeroGS::vb[i].FlushTexData(); u32 psm = ZZOglGet_psm_TexBitsFix(data[0]); u32* s_uTex0Data = ZeroGS::vb[i].uCurTex0Data; // don't update unless necessary // if( ZZOglGet_psm_TexBitsFix(*s_uTex0Data) == ZZOglGet_psm_TexBitsFix(data[0]) ) { // psm is the same if (ZZOglAllExceptClutIsSame(s_uTex0Data, data)) { if (!PSMT_ISCLUT(psm)) return; // have to write the CLUT again if changed if (ZZOglClutMinusCLDunchanged(s_uTex0Data, data)) { tex0.cld = ZZOglGet_cld_TexBits(data[1]); if (tex0.cld != 0) { ZeroGS::texClutWrite(i); // invalidate to make sure target didn't change! ZeroGS::vb[i].bVarsTexSync = false; } return; } } ZeroGS::Flush(i); ZeroGS::vb[i].bVarsTexSync = false; ZeroGS::vb[i].bTexConstsSync = false; s_uTex0Data[0] = (s_uTex0Data[0] & ~0x03f00000) | (psm << 20); s_uTex0Data[1] = (s_uTex0Data[1] & 0x1f) | (data[1] & ~0x1f); tex0.psm = ZZOglGet_psm_TexBitsFix(data[0]); if (PSMT_ISCLUT(tex0.psm)) ZeroGS::CluttingForFlushedTex(&tex0, data[1], i); } __forceinline void frameWrite(int i, u32 *data) { FUNCLOG GIFRegFRAME* r = (GIFRegFRAME*)(data); frameInfo& gsfb = ZeroGS::vb[i].gsfb; if ((gsfb.fbp == ZZOglGet_fbp_FrameBitsMult(data[0])) && (gsfb.fbw == ZZOglGet_fbw_FrameBitsMult(data[0])) && (gsfb.psm == ZZOglGet_psm_FrameBits(data[0])) && (gsfb.fbm == ZZOglGet_fbm_FrameBits(data[0]))) { return; } ZeroGS::FlushBoth(); gsfb.fbp = ZZOglGet_fbp_FrameBitsMult(data[0]); gsfb.fbw = ZZOglGet_fbw_FrameBitsMult(data[0]); gsfb.psm = ZZOglGet_psm_FrameBits(data[0]); gsfb.fbm = ZZOglGet_fbm_FrameBitsFix(data[0], data[1]); gsfb.fbh = ZZOglGet_fbh_FrameBitsCalc(data[0]); ZeroGS::vb[i].bNeedFrameCheck = 1; } __forceinline void testWrite(int i, u32 *data) { FUNCLOG pixTest* test = &ZeroGS::vb[i].test; GIFRegTEST* r = (GIFRegTEST*)(data); if (test->_val != r->ai32[0]) { ZeroGS::Flush(i); } test->_val = r->ai32[0]; } void clampWrite(int i, u32 *data) { FUNCLOG clampInfo& clamp = ZeroGS::vb[i].clamp; GIFRegCLAMP* r = (GIFRegCLAMP*)(data); if ((s_uClampData[i] != data[0]) || (((clamp.minv >> 8) | (clamp.maxv << 2)) != (data[1]&0x0fff))) { ZeroGS::Flush(i); ZeroGS::vb[i].bTexConstsSync = false; } s_uClampData[i] = data[0]; clamp.wms = r->WMS; clamp.wmt = r->WMT; clamp.minu = r->MINU; clamp.maxu = r->MAXU; clamp.minv = r->MINV; clamp.maxv = r->MAXV; } void __fastcall GIFRegHandlerNull(u32* data) { FUNCLOG #ifdef _DEBUG if ((((uptr)&data[2])&0xffff) == 0) return; // 0x7f happens on a lot of games if (data[2] != 0x7f && (data[0] || data[1])) { ZZLog::Debug_Log("Unexpected reg handler %x %x %x.", data[0], data[1], data[2]); } #endif } void __fastcall GIFRegHandlerPRIM(u32 *data) { FUNCLOG //if (data[0] & ~0x3ff) //{ //ZZLog::Warn_Log("Warning: unknown bits in prim %8.8lx_%8.8lx", data[1], data[0]); //} // Come back to this one... gs.nTriFanVert = gs.primIndex; gs.primC = 0; prim->prim = (data[0]) & 0x7; gs._prim[0].prim = (data[0]) & 0x7; gs._prim[1].prim = (data[0]) & 0x7; gs._prim[1]._val = (data[0] >> 3) & 0xff; ZeroGS::Prim(); ZZLog::Greg_Log("PRIM"); } void __fastcall GIFRegHandlerRGBAQ(u32* data) { FUNCLOG GIFRegRGBAQ* r = (GIFRegRGBAQ*)(data); gs.rgba = (r->R | (r->G << 8) | (r->B << 16) | (r->A << 24)); gs.vertexregs.rgba = gs.rgba; gs.vertexregs.q = r->Q; ZZLog::Greg_Log("RGBAQ: 0x%x, 0x%x, 0x%x, %f", r->R, r->G, r->B, r->A, r->Q); } void __fastcall GIFRegHandlerST(u32* data) { FUNCLOG GIFRegST* r = (GIFRegST*)(data); gs.vertexregs.s = r->S; gs.vertexregs.t = r->T; ZZLog::Greg_Log("ST: 0x%x, 0x%x", r->S, r->T); } void __fastcall GIFRegHandlerUV(u32* data) { // Baroque breaks if u&v are 16 bits instead of 14. FUNCLOG GIFRegUV* r = (GIFRegUV*)(data); gs.vertexregs.u = r->U; gs.vertexregs.v = r->V; ZZLog::Greg_Log("UV: 0x%x, 0x%x", r->U, r->V); } void __fastcall GIFRegHandlerXYZF2(u32* data) { FUNCLOG GIFRegXYZF* r = (GIFRegXYZF*)(data); gs.add_vertex(r->X, r->Y,r->Z, r->F); KICK_VERTEX2(); ZZLog::Greg_Log("XYZF2: 0x%x, 0x%x, 0x%x, %f", r->X, r->Y, r->Z, r->F); } void __fastcall GIFRegHandlerXYZ2(u32* data) { FUNCLOG GIFRegXYZ* r = (GIFRegXYZ*)(data); gs.add_vertex(r->X, r->Y,r->Z); KICK_VERTEX2(); ZZLog::Greg_Log("XYZF2: 0x%x, 0x%x, 0x%x", r->X, r->Y, r->Z); } void __fastcall GIFRegHandlerTEX0_1(u32* data) { FUNCLOG // Worry about this later. if (!NoHighlights(0)) return; tex0Write(0, data); ZZLog::Greg_Log("TEX0_1: 0x%x", data); } void __fastcall GIFRegHandlerTEX0_2(u32* data) { FUNCLOG // Worry about this later. if (!NoHighlights(1)) return; tex0Write(1, data); ZZLog::Greg_Log("TEX0_2: 0x%x", data); } void __fastcall GIFRegHandlerCLAMP_1(u32* data) { FUNCLOG // Worry about this later. if (!NoHighlights(0)) return; clampWrite(0, data); ZZLog::Greg_Log("CLAMP_1: 0x%x", data); } void __fastcall GIFRegHandlerCLAMP_2(u32* data) { FUNCLOG // Worry about this later. if (!NoHighlights(1)) return; clampWrite(1, data); ZZLog::Greg_Log("CLAMP_2: 0x%x", data); } void __fastcall GIFRegHandlerFOG(u32* data) { FUNCLOG GIFRegFOG* r = (GIFRegFOG*)(data); gs.vertexregs.f = r->F; ZZLog::Greg_Log("FOG: 0x%x", r->F); } void __fastcall GIFRegHandlerXYZF3(u32* data) { FUNCLOG GIFRegXYZF* r = (GIFRegXYZF*)(data); gs.add_vertex(r->X, r->Y,r->Z, r->F); KICK_VERTEX3(); ZZLog::Greg_Log("XYZF3: 0x%x, 0x%x, 0x%x, %f", r->X, r->Y, r->Z, r->F); } void __fastcall GIFRegHandlerXYZ3(u32* data) { FUNCLOG GIFRegXYZ* r = (GIFRegXYZ*)(data); gs.add_vertex(r->X, r->Y,r->Z); KICK_VERTEX3(); ZZLog::Greg_Log("XYZ3: 0x%x, 0x%x, 0x%x", r->X, r->Y, r->Z); } void __fastcall GIFRegHandlerNOP(u32* data) { FUNCLOG } void tex1Write(int i, u32* data) { FUNCLOG GIFRegTEX1* r = (GIFRegTEX1*)(data); tex1Info& tex1 = ZeroGS::vb[i].tex1; if (conf.bilinear == 1 && (tex1.mmag != r->MMAG || tex1.mmin != r->MMIN)) { ZeroGS::Flush(i); ZeroGS::vb[i].bVarsTexSync = false; } tex1.lcm = r->LCM; tex1.mxl = r->MXL; tex1.mmag = r->MMAG; tex1.mmin = r->MMIN; tex1.mtba = r->MTBA; tex1.l = r->L; tex1.k = r->K; } void __fastcall GIFRegHandlerTEX1_1(u32* data) { FUNCLOG // Worry about this later. if (!NoHighlights(0)) return; tex1Write(0, data); ZZLog::Greg_Log("TEX1_1: 0x%x",data); } void __fastcall GIFRegHandlerTEX1_2(u32* data) { FUNCLOG // Worry about this later. if (!NoHighlights(1)) return; tex1Write(1, data); ZZLog::Greg_Log("TEX1_2: 0x%x",data); } void __fastcall GIFRegHandlerTEX2_1(u32* data) { FUNCLOG tex2Write(0, data); ZZLog::Greg_Log("TEX2_1: 0x%x",data); } void __fastcall GIFRegHandlerTEX2_2(u32* data) { FUNCLOG tex2Write(1, data); ZZLog::Greg_Log("TEX2_2: 0x%x",data); } void __fastcall GIFRegHandlerXYOFFSET_1(u32* data) { FUNCLOG // Affects that Mana Khemia opening dialog. GIFRegXYOFFSET* r = (GIFRegXYOFFSET*)(data); ZeroGS::vb[0].offset.x = r->OFX; ZeroGS::vb[0].offset.y = r->OFY; ZZLog::Greg_Log("XYOFFSET_1: 0x%x, 0x%x", r->OFX, r->OFY); } void __fastcall GIFRegHandlerXYOFFSET_2(u32* data) { FUNCLOG GIFRegXYOFFSET* r = (GIFRegXYOFFSET*)(data); ZeroGS::vb[1].offset.x = r->OFX; ZeroGS::vb[1].offset.y = r->OFY; ZZLog::Greg_Log("XYOFFSET_2: 0x%x, 0x%x", r->OFX, r->OFY); } void __fastcall GIFRegHandlerPRMODECONT(u32* data) { FUNCLOG // Turns all the text into colored blocks on the initial Mana Khemia dialog if not run. GIFRegPRMODECONT* r = (GIFRegPRMODECONT*)(data); gs.prac = r->AC; prim = &gs._prim[gs.prac]; ZeroGS::Prim(); ZZLog::Greg_Log("PRMODECONT"); } void __fastcall GIFRegHandlerPRMODE(u32* data) { FUNCLOG //GIFRegPRMODE* r = (GIFRegPRMODE*)(data); // Re-examine all code dealing with PRIMs in a bit. gs._prim[0]._val = (data[0] >> 3) & 0xff; if (gs.prac == 0) ZeroGS::Prim(); ZZLog::Greg_Log("PRMODE"); } void __fastcall GIFRegHandlerTEXCLUT(u32* data) { FUNCLOG // Affects background coloration of initial Mana Khemia dialog. GIFRegTEXCLUT* r = (GIFRegTEXCLUT*)(data); ZeroGS::vb[0].FlushTexData(); ZeroGS::vb[1].FlushTexData(); // Fixme. gs.clut.cbw = r->CBW << 6; gs.clut.cou = r->COU << 4; gs.clut.cov = r->COV; ZZLog::Greg_Log("TEXCLUT: CBW:0x%x, COU:0x%x, COV:0x%x",r->CBW, r->COU, r->COV); } void __fastcall GIFRegHandlerSCANMSK(u32* data) { FUNCLOG GIFRegSCANMSK* r = (GIFRegSCANMSK*)(data); if(r->MSK != gs.smask) { ZeroGS::FlushBoth(); // ZeroGS::ResolveC(&ZeroGS::vb[0]); // ZeroGS::ResolveZ(&ZeroGS::vb[0]); } gs.smask = r->MSK; ZZLog::Greg_Log("SCANMSK: 0x%x",r->MSK); } void __fastcall GIFRegHandlerMIPTBP1_1(u32* data) { FUNCLOG GIFRegMIPTBP1* r = (GIFRegMIPTBP1*)(data); // Similar here. /*if(PRIM->CTXT == i && r->MIPTBP1 != m_env.CTXT[i].MIPTBP1) { Flush(); }*/ miptbpInfo& miptbp0 = ZeroGS::vb[0].miptbp0; miptbp0.tbp[0] = r->TBP1; miptbp0.tbw[0] = r->TBW1; miptbp0.tbp[1] = r->TBP2; miptbp0.tbw[1] = r->TBW2; miptbp0.tbp[2] = r->TBP3; miptbp0.tbw[2] = r->TBW3; ZZLog::Greg_Log("MIPTBP1_1: TBP/TBW: (0x%x, 0x%x), (0x%x, 0x%x), (0x%x, 0x%x)", r->TBP1, r->TBW1, r->TBP2, r->TBW2, r->TBP3, r->TBW3); } void __fastcall GIFRegHandlerMIPTBP1_2(u32* data) { FUNCLOG GIFRegMIPTBP1* r = (GIFRegMIPTBP1*)(data); // And here. miptbpInfo& miptbp0 = ZeroGS::vb[1].miptbp0; miptbp0.tbp[0] = r->TBP1; miptbp0.tbw[0] = r->TBW1; miptbp0.tbp[1] = r->TBP2; miptbp0.tbw[1] = r->TBW2; miptbp0.tbp[2] = r->TBP3; miptbp0.tbw[2] = r->TBW3; ZZLog::Greg_Log("MIPTBP1_2: TBP/TBW: (0x%x, 0x%x), (0x%x, 0x%x), (0x%x, 0x%x)", r->TBP1, r->TBW1, r->TBP2, r->TBW2, r->TBP3, r->TBW3); } void __fastcall GIFRegHandlerMIPTBP2_1(u32* data) { FUNCLOG GIFRegMIPTBP2* r = (GIFRegMIPTBP2*)(data); // Yep. miptbpInfo& miptbp1 = ZeroGS::vb[0].miptbp1; miptbp1.tbp[0] = r->TBP4; miptbp1.tbw[0] = r->TBW4; miptbp1.tbp[1] = r->TBP5; miptbp1.tbw[1] = r->TBW5; miptbp1.tbp[2] = r->TBP6; miptbp1.tbw[2] = r->TBW6; ZZLog::Greg_Log("MIPTBP2_1: TBP/TBW: (0x%x, 0x%x), (0x%x, 0x%x), (0x%x, 0x%x)", r->TBP4, r->TBW4, r->TBP5, r->TBW5, r->TBP6, r->TBW6); } void __fastcall GIFRegHandlerMIPTBP2_2(u32* data) { FUNCLOG GIFRegMIPTBP2* r = (GIFRegMIPTBP2*)(data); // ... miptbpInfo& miptbp1 = ZeroGS::vb[1].miptbp1; miptbp1.tbp[0] = r->TBP4; miptbp1.tbw[0] = r->TBW4; miptbp1.tbp[1] = r->TBP5; miptbp1.tbw[1] = r->TBW5; miptbp1.tbp[2] = r->TBP6; miptbp1.tbw[2] = r->TBW6; ZZLog::Greg_Log("MIPTBP2_2: TBP/TBW: (0x%x, 0x%x), (0x%x, 0x%x), (0x%x, 0x%x)", r->TBP4, r->TBW4, r->TBP5, r->TBW5, r->TBP6, r->TBW6); } void __fastcall GIFRegHandlerTEXA(u32* data) { FUNCLOG // Background of initial Mana Khemia dialog. GIFRegTEXA* r = (GIFRegTEXA*)(data); if ((r->AEM != gs.texa.aem) || (r->TA0 != gs.texa.ta[0]) || (r->TA1 != gs.texa.ta[1])) { ZeroGS::FlushBoth(); ZeroGS::vb[0].bTexConstsSync = false; ZeroGS::vb[1].bTexConstsSync = false; } gs.texa.aem = r->AEM; gs.texa.ta[0] = r->TA0; gs.texa.ta[1] = r->TA1; gs.texa.fta[0] = r->TA0 / 255.0f; gs.texa.fta[1] = r->TA1 / 255.0f; ZZLog::Greg_Log("TEXA: AEM:0x%x, TA0:0x%x, TA1:0x%x", r->AEM, r->TA0, r->TA1); } void __fastcall GIFRegHandlerFOGCOL(u32* data) { FUNCLOG GIFRegFOGCOL* r = (GIFRegFOGCOL*)(data); if (gs.fogcol != r->ai32[0]) { ZeroGS::FlushBoth(); } ZeroGS::SetFogColor(r); gs.fogcol = r->ai32[0]; ZZLog::Greg_Log("FOGCOL: 0x%x", r->ai32[0]); } void __fastcall GIFRegHandlerTEXFLUSH(u32* data) { FUNCLOG // GSdx doesn't even do anything here. ZeroGS::SetTexFlush(); ZZLog::Greg_Log("TEXFLUSH"); } void __fastcall GIFRegHandlerSCISSOR_1(u32* data) { FUNCLOG GIFRegSCISSOR* r = (GIFRegSCISSOR*)(data); Rect2& scissor = ZeroGS::vb[0].scissor; Rect2 newscissor; // << 3? newscissor.x0 = r->SCAX0 << 3; newscissor.x1 = r->SCAX1 << 3; newscissor.y0 = r->SCAY0 << 3; newscissor.y1 = r->SCAY1 << 3; if (newscissor.x1 != scissor.x1 || newscissor.y1 != scissor.y1 || newscissor.x0 != scissor.x0 || newscissor.y0 != scissor.y0) { ZeroGS::Flush(0); ZeroGS::vb[0].bNeedFrameCheck = 1; } scissor = newscissor; //Hmm... /* if(PRIM->CTXT == i && r->SCISSOR != m_env.CTXT[i].SCISSOR) { Flush(); } m_env.CTXT[i].SCISSOR = (GSVector4i)r->SCISSOR; m_env.CTXT[i].UpdateScissor();*/ ZZLog::Greg_Log("SCISSOR1"); } void __fastcall GIFRegHandlerSCISSOR_2(u32* data) { FUNCLOG GIFRegSCISSOR* r = (GIFRegSCISSOR*)(data); Rect2& scissor = ZeroGS::vb[1].scissor; Rect2 newscissor; // << 3? newscissor.x0 = r->SCAX0 << 3; newscissor.x1 = r->SCAX1 << 3; newscissor.y0 = r->SCAY0 << 3; newscissor.y1 = r->SCAY1 << 3; if (newscissor.x1 != scissor.x1 || newscissor.y1 != scissor.y1 || newscissor.x0 != scissor.x0 || newscissor.y0 != scissor.y0) { ZeroGS::Flush(1); // flush everything ZeroGS::vb[1].bNeedFrameCheck = 1; } scissor = newscissor; ZZLog::Greg_Log("SCISSOR2"); } void __fastcall GIFRegHandlerALPHA_1(u32* data) { FUNCLOG // Mana Khemia Opening Dialog. GIFRegALPHA* r = (GIFRegALPHA*)(data); alphaInfo newalpha; newalpha.a = r->A; newalpha.b = r->B; newalpha.c = r->C; newalpha.d = r->D; newalpha.fix = r->FIX; if (newalpha.a == 3) newalpha.a = 0; if (newalpha.b == 3) newalpha.b = 0; if (newalpha.c == 3) newalpha.c = 0; if (newalpha.d == 3) newalpha.d = 0; if ((newalpha.abcd != ZeroGS::vb[0].alpha.abcd) || (newalpha.fix != ZeroGS::vb[0].alpha.fix)) { ZeroGS::Flush(0); } ZeroGS::vb[0].alpha = newalpha; ZZLog::Greg_Log("ALPHA1: A:0x%x B:0x%x C:0x%x D:0x%x FIX:0x%x ", r->A, r->B, r->C, r->D, r->FIX); } void __fastcall GIFRegHandlerALPHA_2(u32* data) { FUNCLOG GIFRegALPHA* r = (GIFRegALPHA*)(data); alphaInfo newalpha; newalpha.a = r->A; newalpha.b = r->B; newalpha.c = r->C; newalpha.d = r->D; newalpha.fix = r->FIX; if (newalpha.a == 3) newalpha.a = 0; if (newalpha.b == 3) newalpha.b = 0; if (newalpha.c == 3) newalpha.c = 0; if (newalpha.d == 3) newalpha.d = 0; if ((newalpha.abcd != ZeroGS::vb[1].alpha.abcd) || (newalpha.fix != ZeroGS::vb[1].alpha.fix)) { ZeroGS::Flush(1); } ZeroGS::vb[1].alpha = newalpha; ZZLog::Greg_Log("ALPHA2: A:0x%x B:0x%x C:0x%x D:0x%x FIX:0x%x ", r->A, r->B, r->C, r->D, r->FIX); } void __fastcall GIFRegHandlerDIMX(u32* data) { FUNCLOG GIFRegDIMX* r = (GIFRegDIMX*)(data); // Not even handled? Fixme. bool update = false; if (r->i64 != gs.dimx.i64) { ZeroGS::FlushBoth(); update = true; } gs.dimx.i64 = r->i64; if (update) { //gs.UpdateDIMX(); } ZZLog::Greg_Log("DIMX"); } void __fastcall GIFRegHandlerDTHE(u32* data) { FUNCLOG GIFRegDTHE* r = (GIFRegDTHE*)(data); if (r->DTHE != gs.dthe) { ZeroGS::FlushBoth(); } gs.dthe = r->DTHE; ZZLog::Greg_Log("DTHE: 0x%x ", r->DTHE); } void __fastcall GIFRegHandlerCOLCLAMP(u32* data) { FUNCLOG GIFRegCOLCLAMP* r = (GIFRegCOLCLAMP*)(data); if (r->CLAMP != gs.colclamp) { ZeroGS::FlushBoth(); } gs.colclamp = r->CLAMP; ZZLog::Greg_Log("COLCLAMP: 0x%x ", r->CLAMP); } void __fastcall GIFRegHandlerTEST_1(u32* data) { FUNCLOG testWrite(0, data); ZZLog::Greg_Log("TEST1"); } void __fastcall GIFRegHandlerTEST_2(u32* data) { FUNCLOG testWrite(1, data); ZZLog::Greg_Log("TEST2"); } void __fastcall GIFRegHandlerPABE(u32* data) { FUNCLOG GIFRegPABE* r = (GIFRegPABE*)(data); if (gs.pabe != r->PABE) { ZeroGS::FlushBoth(); // ZeroGS::SetAlphaChanged(0, GPUREG_PABE); // ZeroGS::SetAlphaChanged(1, GPUREG_PABE); } gs.pabe = r->PABE; ZZLog::Greg_Log("PABE: 0x%x ", r->PABE); } void __fastcall GIFRegHandlerFBA_1(u32* data) { FUNCLOG GIFRegFBA* r = (GIFRegFBA*)(data); if (r->FBA != ZeroGS::vb[0].fba.fba) { ZeroGS::FlushBoth(); } ZeroGS::vb[0].fba.fba = r->FBA; ZZLog::Greg_Log("FBA1: 0x%x ", r->FBA); } void __fastcall GIFRegHandlerFBA_2(u32* data) { FUNCLOG GIFRegFBA* r = (GIFRegFBA*)(data); if (r->FBA != ZeroGS::vb[1].fba.fba) { ZeroGS::FlushBoth(); } ZeroGS::vb[1].fba.fba = r->FBA; ZZLog::Greg_Log("FBA2: 0x%x ", r->FBA); } void __fastcall GIFRegHandlerFRAME_1(u32* data) { FUNCLOG // Affects opening dialogs, movie, and menu on Mana Khemia. frameWrite(0, data); ZZLog::Greg_Log("FRAME_1"); } void __fastcall GIFRegHandlerFRAME_2(u32* data) { FUNCLOG frameWrite(1, data); ZZLog::Greg_Log("FRAME_2"); } void __fastcall GIFRegHandlerZBUF_1(u32* data) { FUNCLOG // I'll wait a bit on this one. //GIFRegZBUF* r = (GIFRegZBUF*)(data); ZZLog::Greg_Log("ZBUF_1"); zbufInfo& zbuf = ZeroGS::vb[0].zbuf; int psm = (0x30 | ((data[0] >> 24) & 0xf)); if (zbuf.zbp == (data[0] & 0x1ff) << 5 && zbuf.psm == psm && zbuf.zmsk == (data[1] & 0x1)) { return; } // error detection if (m_Blocks[psm].bpp == 0) return; ZeroGS::FlushBoth(); zbuf.zbp = (data[0] & 0x1ff) << 5; zbuf.psm = 0x30 | ((data[0] >> 24) & 0xf); zbuf.zmsk = data[1] & 0x1; ZeroGS::vb[0].zprimmask = 0xffffffff; if (zbuf.psm > 0x31) ZeroGS::vb[0].zprimmask = 0xffff; ZeroGS::vb[0].bNeedZCheck = 1; } void __fastcall GIFRegHandlerZBUF_2(u32* data) { FUNCLOG ZZLog::Greg_Log("ZBUF_2"); // And this. //GIFRegZBUF* r = (GIFRegZBUF*)(data); zbufInfo& zbuf = ZeroGS::vb[1].zbuf; int psm = (0x30 | ((data[0] >> 24) & 0xf)); if (zbuf.zbp == (data[0] & 0x1ff) << 5 && zbuf.psm == psm && zbuf.zmsk == (data[1] & 0x1)) { return; } // error detection if (m_Blocks[psm].bpp == 0) return; ZeroGS::FlushBoth(); zbuf.zbp = (data[0] & 0x1ff) << 5; zbuf.psm = 0x30 | ((data[0] >> 24) & 0xf); zbuf.zmsk = data[1] & 0x1; ZeroGS::vb[1].bNeedZCheck = 1; ZeroGS::vb[1].zprimmask = 0xffffffff; if (zbuf.psm > 0x31) ZeroGS::vb[1].zprimmask = 0xffff; } void __fastcall GIFRegHandlerBITBLTBUF(u32* data) { FUNCLOG // Required for *all* graphics. (Checked on Mana Khemia) GIFRegBITBLTBUF* r = (GIFRegBITBLTBUF*)(data); // Wonder why the shift? gs.srcbufnew.bp = r->SBP; // * 64; gs.srcbufnew.bw = r->SBW << 6; gs.srcbufnew.psm = r->SPSM; gs.dstbufnew.bp = r->DBP; // * 64; gs.dstbufnew.bw = r->DBW << 6; gs.dstbufnew.psm = r->DPSM; if (gs.dstbufnew.bw == 0) gs.dstbufnew.bw = 64; // GSdx does this: /*if((gs.srcbufnew.bw & 1) && (gs.srcbufnew.psm == PSM_PSMT8 || gs.srcbufnew.psm == PSM_PSMT4)) { gs.srcbufnew.bw &= ~1; } if((gs.dstbufnew.bw & 1) && (gs.dstbufnew.psm == PSM_PSMT8 || gs.dstbufnew.psm == PSM_PSMT4)) { gs.dstbufnew.bw &= ~1; // namcoXcapcom: 5, 11, refered to as 4, 10 in TEX0.TBW later }*/ ZZLog::Greg_Log("BITBLTBUF"); } void __fastcall GIFRegHandlerTRXPOS(u32* data) { // Affects Mana Khemia opening background. FUNCLOG GIFRegTRXPOS* r = (GIFRegTRXPOS*)(data); gs.trxposnew.sx = r->SSAX; gs.trxposnew.sy = r->SSAY; gs.trxposnew.dx = r->DSAX; gs.trxposnew.dy = r->DSAY; gs.trxposnew.dirx = r->DIRX; gs.trxposnew.diry = r->DIRY; ZZLog::Greg_Log("TRXPOS: SSA:(0x%x/0x%x) DSA:(0x%x/0x%x) DIR:(0x%x/0x%x)", r->SSAX, r->SSAY, r->DSAX, r->DSAY, r->DIRX, r->DIRY); } void __fastcall GIFRegHandlerTRXREG(u32* data) { FUNCLOG GIFRegTRXREG* r = (GIFRegTRXREG*)(data); gs.imageWtemp = r->RRW; gs.imageHtemp = r->RRH; ZZLog::Greg_Log("TRXREG: RRW: 0x%x, RRH: 0x%x", r->RRW, r->RRH); } void __fastcall GIFRegHandlerTRXDIR(u32* data) { FUNCLOG // Oh dear... // terminate any previous transfers switch (gs.imageTransfer) { case 0: // host->loc gs.imageTransfer = -1; break; case 1: // loc->host ZeroGS::TerminateLocalHost(); break; } gs.srcbuf = gs.srcbufnew; gs.dstbuf = gs.dstbufnew; gs.trxpos = gs.trxposnew; gs.imageTransfer = data[0] & 0x3; gs.imageWnew = gs.imageWtemp; gs.imageHnew = gs.imageHtemp; if (gs.imageWnew > 0 && gs.imageHnew > 0) { switch (gs.imageTransfer) { case 0: // host->loc ZeroGS::InitTransferHostLocal(); break; case 1: // loc->host ZeroGS::InitTransferLocalHost(); break; case 2: ZeroGS::TransferLocalLocal(); break; case 3: gs.imageTransfer = -1; break; default: assert(0); } } else { #if defined(ZEROGS_DEVBUILD) ZZLog::Warn_Log("Dummy transfer."); #endif gs.imageTransfer = -1; } ZZLog::Greg_Log("TRXDIR"); } void __fastcall GIFRegHandlerHWREG(u32* data) { FUNCLOG if (gs.imageTransfer == 0) { ZeroGS::TransferHostLocal(data, 2); } else { #if defined(ZEROGS_DEVBUILD) ZZLog::Error_Log("ZeroGS: HWREG!? %8.8x_%8.8x", data[0], data[1]); //assert(0); #endif } ZZLog::Greg_Log("HWREG"); } extern int g_GSMultiThreaded; void __fastcall GIFRegHandlerSIGNAL(u32* data) { FUNCLOG if (!g_GSMultiThreaded) { SIGLBLID->SIGID = (SIGLBLID->SIGID & ~data[1]) | (data[0] & data[1]); if (gs.CSRw & 0x1) { CSR->SIGNAL = 1; } if (!IMR->SIGMSK && GSirq) GSirq(); } } void __fastcall GIFRegHandlerFINISH(u32* data) { FUNCLOG if (!g_GSMultiThreaded) { if (gs.CSRw & 0x2) CSR->FINISH = 1; if (!IMR->FINISHMSK && GSirq) GSirq(); } } void __fastcall GIFRegHandlerLABEL(u32* data) { FUNCLOG if (!g_GSMultiThreaded) { SIGLBLID->LBLID = (SIGLBLID->LBLID & ~data[1]) | (data[0] & data[1]); } } void SetMultithreaded() { // Some older versions of PCSX2 didn't properly set the irq callback to NULL // in multithreaded mode (possibly because ZeroGS itself would assert in such // cases), and didn't bind them to a dummy callback either. PCSX2 handles all // IRQs internally when multithreaded anyway -- so let's ignore them here: if (g_GSMultiThreaded) { g_GIFRegHandlers[GIF_A_D_REG_SIGNAL] = &GIFRegHandlerNull; g_GIFRegHandlers[GIF_A_D_REG_FINISH] = &GIFRegHandlerNull; g_GIFRegHandlers[GIF_A_D_REG_LABEL] = &GIFRegHandlerNull; } else { g_GIFRegHandlers[GIF_A_D_REG_SIGNAL] = &GIFRegHandlerSIGNAL; g_GIFRegHandlers[GIF_A_D_REG_FINISH] = &GIFRegHandlerFINISH; g_GIFRegHandlers[GIF_A_D_REG_LABEL] = &GIFRegHandlerLABEL; } } void ResetRegs() { for (int i = 0; i < 16; i++) { g_GIFPackedRegHandlers[i] = &GIFPackedRegHandlerNull; } g_GIFPackedRegHandlers[GIF_REG_PRIM] = &GIFPackedRegHandlerPRIM; g_GIFPackedRegHandlers[GIF_REG_RGBA] = &GIFPackedRegHandlerRGBA; g_GIFPackedRegHandlers[GIF_REG_STQ] = &GIFPackedRegHandlerSTQ; g_GIFPackedRegHandlers[GIF_REG_UV] = &GIFPackedRegHandlerUV; g_GIFPackedRegHandlers[GIF_REG_XYZF2] = &GIFPackedRegHandlerXYZF2; g_GIFPackedRegHandlers[GIF_REG_XYZ2] = &GIFPackedRegHandlerXYZ2; g_GIFPackedRegHandlers[GIF_REG_TEX0_1] = &GIFPackedRegHandlerTEX0_1; g_GIFPackedRegHandlers[GIF_REG_TEX0_2] = &GIFPackedRegHandlerTEX0_2; g_GIFPackedRegHandlers[GIF_REG_CLAMP_1] = &GIFPackedRegHandlerCLAMP_1; g_GIFPackedRegHandlers[GIF_REG_CLAMP_2] = &GIFPackedRegHandlerCLAMP_2; g_GIFPackedRegHandlers[GIF_REG_FOG] = &GIFPackedRegHandlerFOG; g_GIFPackedRegHandlers[GIF_REG_XYZF3] = &GIFPackedRegHandlerXYZF3; g_GIFPackedRegHandlers[GIF_REG_XYZ3] = &GIFPackedRegHandlerXYZ3; g_GIFPackedRegHandlers[GIF_REG_A_D] = &GIFPackedRegHandlerA_D; g_GIFPackedRegHandlers[GIF_REG_NOP] = &GIFPackedRegHandlerNOP; for (int i = 0; i < 256; i++) { g_GIFRegHandlers[i] = &GIFPackedRegHandlerNull; } g_GIFRegHandlers[GIF_A_D_REG_PRIM] = &GIFRegHandlerPRIM; g_GIFRegHandlers[GIF_A_D_REG_RGBAQ] = &GIFRegHandlerRGBAQ; g_GIFRegHandlers[GIF_A_D_REG_ST] = &GIFRegHandlerST; g_GIFRegHandlers[GIF_A_D_REG_UV] = &GIFRegHandlerUV; g_GIFRegHandlers[GIF_A_D_REG_XYZF2] = &GIFRegHandlerXYZF2; g_GIFRegHandlers[GIF_A_D_REG_XYZ2] = &GIFRegHandlerXYZ2; g_GIFRegHandlers[GIF_A_D_REG_TEX0_1] = &GIFRegHandlerTEX0_1; g_GIFRegHandlers[GIF_A_D_REG_TEX0_2] = &GIFRegHandlerTEX0_2; g_GIFRegHandlers[GIF_A_D_REG_CLAMP_1] = &GIFRegHandlerCLAMP_1; g_GIFRegHandlers[GIF_A_D_REG_CLAMP_2] = &GIFRegHandlerCLAMP_2; g_GIFRegHandlers[GIF_A_D_REG_FOG] = &GIFRegHandlerFOG; g_GIFRegHandlers[GIF_A_D_REG_XYZF3] = &GIFRegHandlerXYZF3; g_GIFRegHandlers[GIF_A_D_REG_XYZ3] = &GIFRegHandlerXYZ3; g_GIFRegHandlers[GIF_A_D_REG_NOP] = &GIFRegHandlerNOP; g_GIFRegHandlers[GIF_A_D_REG_TEX1_1] = &GIFRegHandlerTEX1_1; g_GIFRegHandlers[GIF_A_D_REG_TEX1_2] = &GIFRegHandlerTEX1_2; g_GIFRegHandlers[GIF_A_D_REG_TEX2_1] = &GIFRegHandlerTEX2_1; g_GIFRegHandlers[GIF_A_D_REG_TEX2_2] = &GIFRegHandlerTEX2_2; g_GIFRegHandlers[GIF_A_D_REG_XYOFFSET_1] = &GIFRegHandlerXYOFFSET_1; g_GIFRegHandlers[GIF_A_D_REG_XYOFFSET_2] = &GIFRegHandlerXYOFFSET_2; g_GIFRegHandlers[GIF_A_D_REG_PRMODECONT] = &GIFRegHandlerPRMODECONT; g_GIFRegHandlers[GIF_A_D_REG_PRMODE] = &GIFRegHandlerPRMODE; g_GIFRegHandlers[GIF_A_D_REG_TEXCLUT] = &GIFRegHandlerTEXCLUT; g_GIFRegHandlers[GIF_A_D_REG_SCANMSK] = &GIFRegHandlerSCANMSK; g_GIFRegHandlers[GIF_A_D_REG_MIPTBP1_1] = &GIFRegHandlerMIPTBP1_1; g_GIFRegHandlers[GIF_A_D_REG_MIPTBP1_2] = &GIFRegHandlerMIPTBP1_2; g_GIFRegHandlers[GIF_A_D_REG_MIPTBP2_1] = &GIFRegHandlerMIPTBP2_1; g_GIFRegHandlers[GIF_A_D_REG_MIPTBP2_2] = &GIFRegHandlerMIPTBP2_2; g_GIFRegHandlers[GIF_A_D_REG_TEXA] = &GIFRegHandlerTEXA; g_GIFRegHandlers[GIF_A_D_REG_FOGCOL] = &GIFRegHandlerFOGCOL; g_GIFRegHandlers[GIF_A_D_REG_TEXFLUSH] = &GIFRegHandlerTEXFLUSH; g_GIFRegHandlers[GIF_A_D_REG_SCISSOR_1] = &GIFRegHandlerSCISSOR_1; g_GIFRegHandlers[GIF_A_D_REG_SCISSOR_2] = &GIFRegHandlerSCISSOR_2; g_GIFRegHandlers[GIF_A_D_REG_ALPHA_1] = &GIFRegHandlerALPHA_1; g_GIFRegHandlers[GIF_A_D_REG_ALPHA_2] = &GIFRegHandlerALPHA_2; g_GIFRegHandlers[GIF_A_D_REG_DIMX] = &GIFRegHandlerDIMX; g_GIFRegHandlers[GIF_A_D_REG_DTHE] = &GIFRegHandlerDTHE; g_GIFRegHandlers[GIF_A_D_REG_COLCLAMP] = &GIFRegHandlerCOLCLAMP; g_GIFRegHandlers[GIF_A_D_REG_TEST_1] = &GIFRegHandlerTEST_1; g_GIFRegHandlers[GIF_A_D_REG_TEST_2] = &GIFRegHandlerTEST_2; g_GIFRegHandlers[GIF_A_D_REG_PABE] = &GIFRegHandlerPABE; g_GIFRegHandlers[GIF_A_D_REG_FBA_1] = &GIFRegHandlerFBA_1; g_GIFRegHandlers[GIF_A_D_REG_FBA_2] = &GIFRegHandlerFBA_2; g_GIFRegHandlers[GIF_A_D_REG_FRAME_1] = &GIFRegHandlerFRAME_1; g_GIFRegHandlers[GIF_A_D_REG_FRAME_2] = &GIFRegHandlerFRAME_2; g_GIFRegHandlers[GIF_A_D_REG_ZBUF_1] = &GIFRegHandlerZBUF_1; g_GIFRegHandlers[GIF_A_D_REG_ZBUF_2] = &GIFRegHandlerZBUF_2; g_GIFRegHandlers[GIF_A_D_REG_BITBLTBUF] = &GIFRegHandlerBITBLTBUF; g_GIFRegHandlers[GIF_A_D_REG_TRXPOS] = &GIFRegHandlerTRXPOS; g_GIFRegHandlers[GIF_A_D_REG_TRXREG] = &GIFRegHandlerTRXREG; g_GIFRegHandlers[GIF_A_D_REG_TRXDIR] = &GIFRegHandlerTRXDIR; g_GIFRegHandlers[GIF_A_D_REG_HWREG] = &GIFRegHandlerHWREG; SetMultithreaded(); } void WriteTempRegs() { memcpy(g_GIFTempRegHandlers, g_GIFPackedRegHandlers, sizeof(g_GIFTempRegHandlers)); } void SetFrameSkip(bool skip) { if (skip) { g_GIFPackedRegHandlers[GIF_REG_PRIM] = &GIFPackedRegHandlerNOP; g_GIFPackedRegHandlers[GIF_REG_RGBA] = &GIFPackedRegHandlerNOP; g_GIFPackedRegHandlers[GIF_REG_STQ] = &GIFPackedRegHandlerNOP; g_GIFPackedRegHandlers[GIF_REG_UV] = &GIFPackedRegHandlerNOP; g_GIFPackedRegHandlers[GIF_REG_XYZF2] = &GIFPackedRegHandlerNOP; g_GIFPackedRegHandlers[GIF_REG_XYZ2] = &GIFPackedRegHandlerNOP; g_GIFPackedRegHandlers[GIF_REG_CLAMP_1] = &GIFPackedRegHandlerNOP; g_GIFPackedRegHandlers[GIF_REG_CLAMP_2] = &GIFPackedRegHandlerNOP; g_GIFPackedRegHandlers[GIF_REG_FOG] = &GIFPackedRegHandlerNOP; g_GIFPackedRegHandlers[GIF_REG_XYZF3] = &GIFPackedRegHandlerNOP; g_GIFPackedRegHandlers[GIF_REG_XYZ3] = &GIFPackedRegHandlerNOP; g_GIFRegHandlers[GIF_A_D_REG_PRIM] = &GIFRegHandlerNOP; g_GIFRegHandlers[GIF_A_D_REG_RGBAQ] = &GIFRegHandlerNOP; g_GIFRegHandlers[GIF_A_D_REG_ST] = &GIFRegHandlerNOP; g_GIFRegHandlers[GIF_A_D_REG_UV] = &GIFRegHandlerNOP; g_GIFRegHandlers[GIF_A_D_REG_XYZF2] = &GIFRegHandlerNOP; g_GIFRegHandlers[GIF_A_D_REG_XYZ2] = &GIFRegHandlerNOP; g_GIFRegHandlers[GIF_A_D_REG_XYZF3] = &GIFRegHandlerNOP; g_GIFRegHandlers[GIF_A_D_REG_XYZ3] = &GIFRegHandlerNOP; g_GIFRegHandlers[GIF_A_D_REG_PRMODECONT] = &GIFRegHandlerNOP; g_GIFRegHandlers[GIF_A_D_REG_PRMODE] = &GIFRegHandlerNOP; } else { g_GIFPackedRegHandlers[GIF_REG_PRIM] = &GIFPackedRegHandlerPRIM; g_GIFPackedRegHandlers[GIF_REG_RGBA] = &GIFPackedRegHandlerRGBA; g_GIFPackedRegHandlers[GIF_REG_STQ] = &GIFPackedRegHandlerSTQ; g_GIFPackedRegHandlers[GIF_REG_UV] = &GIFPackedRegHandlerUV; g_GIFPackedRegHandlers[GIF_REG_XYZF2] = &GIFPackedRegHandlerXYZF2; g_GIFPackedRegHandlers[GIF_REG_XYZ2] = &GIFPackedRegHandlerXYZ2; g_GIFPackedRegHandlers[GIF_REG_CLAMP_1] = &GIFPackedRegHandlerCLAMP_1; g_GIFPackedRegHandlers[GIF_REG_CLAMP_2] = &GIFPackedRegHandlerCLAMP_2; g_GIFPackedRegHandlers[GIF_REG_FOG] = &GIFPackedRegHandlerFOG; g_GIFPackedRegHandlers[GIF_REG_XYZF3] = &GIFPackedRegHandlerXYZF3; g_GIFPackedRegHandlers[GIF_REG_XYZ3] = &GIFPackedRegHandlerXYZ3; g_GIFRegHandlers[GIF_A_D_REG_PRIM] = &GIFRegHandlerPRIM; g_GIFRegHandlers[GIF_A_D_REG_RGBAQ] = &GIFRegHandlerRGBAQ; g_GIFRegHandlers[GIF_A_D_REG_ST] = &GIFRegHandlerST; g_GIFRegHandlers[GIF_A_D_REG_UV] = &GIFRegHandlerUV; g_GIFRegHandlers[GIF_A_D_REG_XYZF2] = &GIFRegHandlerXYZF2; g_GIFRegHandlers[GIF_A_D_REG_XYZ2] = &GIFRegHandlerXYZ2; g_GIFRegHandlers[GIF_A_D_REG_XYZF3] = &GIFRegHandlerXYZF3; g_GIFRegHandlers[GIF_A_D_REG_XYZ3] = &GIFRegHandlerXYZ3; g_GIFRegHandlers[GIF_A_D_REG_PRMODECONT] = &GIFRegHandlerPRMODECONT; g_GIFRegHandlers[GIF_A_D_REG_PRMODE] = &GIFRegHandlerPRMODE; } } #endif