// all gfx state registers here #include "pch.h" static FILE *gplog; GXDrawDoneCallback GxDrawDone; GXDrawTokenCallback GxDrawToken; void GXSetDrawCallbacks(GXDrawDoneCallback drawDoneCb, GXDrawTokenCallback drawTokenCb) { GxDrawDone = drawDoneCb; GxDrawToken = drawTokenCb; } CPMemory cpRegs; BPMemory bpRegs; XFMemory xfRegs; uint32_t cpLoads, bpLoads, xfLoads; static bool GpRegsLog = false; // --------------------------------------------------------------------------- // index range = 00..FF // reg size = 32 bit void loadCPReg(size_t index, uint32_t value) { cpLoads++; if (GpRegsLog) { DBReport2(DbgChannel::GP, "Load CP: index: 0x%02X, data: 0x%08X", index, value); } switch(index) { case CP_MATIDX_A: { cpRegs.matidxA.matidx = value; //GFXError("cp posidx : %i", cpRegs.matidxA.pos); } return; case CP_MATIDX_B: { cpRegs.matidxB.matidx = value; } return; case CP_VCD_LO: { cpRegs.vcdLo.vcdlo = value; // update pipeline, using all VATs for(unsigned vatnum=0; vatnum<8; vatnum++) { FifoReconfigure( VTX_POSMATIDX, vatnum, cpRegs.vcdLo.pmidx, 0, 0, 0 ); FifoReconfigure( VTX_TEX0MTXIDX, vatnum, cpRegs.vcdLo.t0midx, 0, 0, 0 ); FifoReconfigure( VTX_TEX1MTXIDX, vatnum, cpRegs.vcdLo.t1midx, 0, 0, 0 ); FifoReconfigure( VTX_TEX2MTXIDX, vatnum, cpRegs.vcdLo.t2midx, 0, 0, 0 ); FifoReconfigure( VTX_TEX3MTXIDX, vatnum, cpRegs.vcdLo.t3midx, 0, 0, 0 ); FifoReconfigure( VTX_TEX4MTXIDX, vatnum, cpRegs.vcdLo.t4midx, 0, 0, 0 ); FifoReconfigure( VTX_TEX5MTXIDX, vatnum, cpRegs.vcdLo.t5midx, 0, 0, 0 ); FifoReconfigure( VTX_TEX6MTXIDX, vatnum, cpRegs.vcdLo.t6midx, 0, 0, 0 ); FifoReconfigure( VTX_TEX7MTXIDX, vatnum, cpRegs.vcdLo.t7midx, 0, 0, 0 ); FifoReconfigure( VTX_POS, vatnum, cpRegs.vcdLo.pos, cpRegs.vatA[vatnum].poscnt, cpRegs.vatA[vatnum].posfmt, cpRegs.vatA[vatnum].posshft ); FifoReconfigure( VTX_NRM, vatnum, cpRegs.vcdLo.nrm, cpRegs.vatA[vatnum].nrmcnt, cpRegs.vatA[vatnum].nrmfmt, 0 ); FifoReconfigure( VTX_COLOR0, vatnum, cpRegs.vcdLo.col0, cpRegs.vatA[vatnum].col0cnt, cpRegs.vatA[vatnum].col0fmt, 0 ); FifoReconfigure( VTX_COLOR1, vatnum, cpRegs.vcdLo.col1, cpRegs.vatA[vatnum].col1cnt, cpRegs.vatA[vatnum].col1fmt, 0 ); } } return; case CP_VCD_HI: { cpRegs.vcdHi.vcdhi = value; // update pipeline, using all VATs for(unsigned vatnum=0; vatnum<8; vatnum++) { FifoReconfigure( VTX_TEXCOORD0, vatnum, cpRegs.vcdHi.tex0, cpRegs.vatA[vatnum].tex0cnt, cpRegs.vatA[vatnum].tex0fmt, cpRegs.vatA[vatnum].tex0shft ); FifoReconfigure( VTX_TEXCOORD1, vatnum, cpRegs.vcdHi.tex1, cpRegs.vatB[vatnum].tex1cnt, cpRegs.vatB[vatnum].tex1fmt, cpRegs.vatB[vatnum].tex1shft ); FifoReconfigure( VTX_TEXCOORD2, vatnum, cpRegs.vcdHi.tex2, cpRegs.vatB[vatnum].tex2cnt, cpRegs.vatB[vatnum].tex2fmt, cpRegs.vatB[vatnum].tex2shft ); FifoReconfigure( VTX_TEXCOORD3, vatnum, cpRegs.vcdHi.tex3, cpRegs.vatB[vatnum].tex3cnt, cpRegs.vatB[vatnum].tex3fmt, cpRegs.vatB[vatnum].tex3shft ); FifoReconfigure( VTX_TEXCOORD4, vatnum, cpRegs.vcdHi.tex4, cpRegs.vatB[vatnum].tex4cnt, cpRegs.vatB[vatnum].tex4fmt, cpRegs.vatC[vatnum].tex4shft ); FifoReconfigure( VTX_TEXCOORD5, vatnum, cpRegs.vcdHi.tex5, cpRegs.vatC[vatnum].tex5cnt, cpRegs.vatC[vatnum].tex5fmt, cpRegs.vatC[vatnum].tex5shft ); FifoReconfigure( VTX_TEXCOORD6, vatnum, cpRegs.vcdHi.tex6, cpRegs.vatC[vatnum].tex6cnt, cpRegs.vatC[vatnum].tex6fmt, cpRegs.vatC[vatnum].tex6shft ); FifoReconfigure( VTX_TEXCOORD7, vatnum, cpRegs.vcdHi.tex7, cpRegs.vatC[vatnum].tex7cnt, cpRegs.vatC[vatnum].tex7fmt, cpRegs.vatC[vatnum].tex7shft ); } } return; case CP_VAT0_A: case CP_VAT1_A: case CP_VAT2_A: case CP_VAT3_A: case CP_VAT4_A: case CP_VAT5_A: case CP_VAT6_A: case CP_VAT7_A: { unsigned vatnum = index & 7; cpRegs.vatA[vatnum].vata = value; FifoReconfigure( VTX_POS, vatnum, cpRegs.vcdLo.pos, cpRegs.vatA[vatnum].poscnt, cpRegs.vatA[vatnum].posfmt, cpRegs.vatA[vatnum].posshft ); FifoReconfigure( VTX_NRM, vatnum, cpRegs.vcdLo.nrm, cpRegs.vatA[vatnum].nrmcnt, cpRegs.vatA[vatnum].nrmfmt, 0 ); FifoReconfigure( VTX_COLOR0, vatnum, cpRegs.vcdLo.col0, cpRegs.vatA[vatnum].col0cnt, cpRegs.vatA[vatnum].col0fmt, 0 ); FifoReconfigure( VTX_COLOR1, vatnum, cpRegs.vcdLo.col1, cpRegs.vatA[vatnum].col1cnt, cpRegs.vatA[vatnum].col1fmt, 0 ); FifoReconfigure( VTX_TEXCOORD0, vatnum, cpRegs.vcdHi.tex0, cpRegs.vatA[vatnum].tex0cnt, cpRegs.vatA[vatnum].tex0fmt, cpRegs.vatA[vatnum].tex0shft ); } return; case CP_VAT0_B: case CP_VAT1_B: case CP_VAT2_B: case CP_VAT3_B: case CP_VAT4_B: case CP_VAT5_B: case CP_VAT6_B: case CP_VAT7_B: { unsigned vatnum = index & 7; cpRegs.vatB[vatnum].vatb = value; FifoReconfigure( VTX_TEXCOORD1, vatnum, cpRegs.vcdHi.tex1, cpRegs.vatB[vatnum].tex1cnt, cpRegs.vatB[vatnum].tex1fmt, cpRegs.vatB[vatnum].tex1shft ); FifoReconfigure( VTX_TEXCOORD2, vatnum, cpRegs.vcdHi.tex2, cpRegs.vatB[vatnum].tex2cnt, cpRegs.vatB[vatnum].tex2fmt, cpRegs.vatB[vatnum].tex2shft ); FifoReconfigure( VTX_TEXCOORD3, vatnum, cpRegs.vcdHi.tex3, cpRegs.vatB[vatnum].tex3cnt, cpRegs.vatB[vatnum].tex3fmt, cpRegs.vatB[vatnum].tex3shft ); FifoReconfigure( VTX_TEXCOORD4, vatnum, cpRegs.vcdHi.tex4, cpRegs.vatB[vatnum].tex4cnt, cpRegs.vatB[vatnum].tex4fmt, cpRegs.vatC[vatnum].tex4shft ); } return; case CP_VAT0_C: case CP_VAT1_C: case CP_VAT2_C: case CP_VAT3_C: case CP_VAT4_C: case CP_VAT5_C: case CP_VAT6_C: case CP_VAT7_C: { unsigned vatnum = index & 7; cpRegs.vatC[vatnum].vatc = value; FifoReconfigure( VTX_TEXCOORD4, vatnum, cpRegs.vcdHi.tex4, cpRegs.vatB[vatnum].tex4cnt, cpRegs.vatB[vatnum].tex4fmt, cpRegs.vatC[vatnum].tex4shft ); FifoReconfigure( VTX_TEXCOORD5, vatnum, cpRegs.vcdHi.tex5, cpRegs.vatC[vatnum].tex5cnt, cpRegs.vatC[vatnum].tex5fmt, cpRegs.vatC[vatnum].tex5shft ); FifoReconfigure( VTX_TEXCOORD6, vatnum, cpRegs.vcdHi.tex6, cpRegs.vatC[vatnum].tex6cnt, cpRegs.vatC[vatnum].tex6fmt, cpRegs.vatC[vatnum].tex6shft ); FifoReconfigure( VTX_TEXCOORD7, vatnum, cpRegs.vcdHi.tex7, cpRegs.vatC[vatnum].tex7cnt, cpRegs.vatC[vatnum].tex7fmt, cpRegs.vatC[vatnum].tex7shft ); } return; case CP_ARRAY_BASE | (VTX_POS - VTX_POS): // 0xA0 case CP_ARRAY_BASE | (VTX_NRM - VTX_POS): // 0xA1 case CP_ARRAY_BASE | (VTX_COLOR0 - VTX_POS): // 0xA2 case CP_ARRAY_BASE | (VTX_COLOR1 - VTX_POS): // 0xA3 case CP_ARRAY_BASE | (VTX_TEXCOORD0 - VTX_POS): // 0xA4 case CP_ARRAY_BASE | (VTX_TEXCOORD1 - VTX_POS): // 0xA5 case CP_ARRAY_BASE | (VTX_TEXCOORD2 - VTX_POS): // 0xA6 case CP_ARRAY_BASE | (VTX_TEXCOORD3 - VTX_POS): // 0xA7 case CP_ARRAY_BASE | (VTX_TEXCOORD4 - VTX_POS): // 0xA8 case CP_ARRAY_BASE | (VTX_TEXCOORD5 - VTX_POS): // 0xA9 case CP_ARRAY_BASE | (VTX_TEXCOORD6 - VTX_POS): // 0xAA case CP_ARRAY_BASE | (VTX_TEXCOORD7 - VTX_POS): // 0xAB { // array base is already translated cpRegs.arbase[VTX_POS + (index & 0xf)] = (uint8_t *)&RAM[value & RAMMASK]; } return; case CP_ARRAY_STRIDE | (VTX_POS - VTX_POS): // 0xB0 case CP_ARRAY_STRIDE | (VTX_NRM - VTX_POS): // 0xB1 case CP_ARRAY_STRIDE | (VTX_COLOR0 - VTX_POS): // 0xB2 case CP_ARRAY_STRIDE | (VTX_COLOR1 - VTX_POS): // 0xB3 case CP_ARRAY_STRIDE | (VTX_TEXCOORD0 - VTX_POS): // 0xB4 case CP_ARRAY_STRIDE | (VTX_TEXCOORD1 - VTX_POS): // 0xB5 case CP_ARRAY_STRIDE | (VTX_TEXCOORD2 - VTX_POS): // 0xB6 case CP_ARRAY_STRIDE | (VTX_TEXCOORD3 - VTX_POS): // 0xB7 case CP_ARRAY_STRIDE | (VTX_TEXCOORD4 - VTX_POS): // 0xB8 case CP_ARRAY_STRIDE | (VTX_TEXCOORD5 - VTX_POS): // 0xB9 case CP_ARRAY_STRIDE | (VTX_TEXCOORD6 - VTX_POS): // 0xBA case CP_ARRAY_STRIDE | (VTX_TEXCOORD7 - VTX_POS): // 0xBB { cpRegs.arstride[VTX_POS + (index & 0xf)] = value; } return; default: { #ifdef GPLOG fprintf(gplog, "unknown CP load, index: %02X, data: %08X\n", index, value); fflush(gplog); #endif // GFXError("unknown CP load, index : %02X", index); } } } static void tryLoadTex(int id) { if(bpRegs.valid[0][id] && bpRegs.valid[3][id]) { bpRegs.valid[0][id] = bpRegs.valid[3][id] = FALSE; #ifndef WIREFRAME LoadTexture( bpRegs.teximg3[id].base << 5, id, bpRegs.teximg0[id].fmt, bpRegs.teximg0[id].width + 1, bpRegs.teximg0[id].height + 1 ); #endif } } // index range = 00..FF // reg size = 24 bit (value is already masked) void loadBPReg(size_t index, uint32_t value) { static Color copyClearRGBA; static uint32_t copyClearZ; bpLoads++; if (GpRegsLog) { DBReport2(DbgChannel::GP, "Load BP: index: 0x%02X, data: 0x%08X", index, value); } switch(index) { // draw done case PE_DONE: { GPFrameDone(); if (GxDrawDone) { GxDrawDone(); } } return; // token case PE_TOKEN_INT: { bpRegs.tokint = (uint16_t)value; } return; case PE_TOKEN: { if (GxDrawToken && (uint16_t)value == bpRegs.tokint) { GPFrameDone(); GxDrawToken(bpRegs.tokint); } } return; // // gen mode // application : clipping // case BP_GEN_MODE: { static int cull_modes[4] = { GFX_CULL_NONE, GFX_CULL_BACK, GFX_CULL_FRONT, GFX_CULL_ALL, }; bpRegs.genmode.hex = value; //GFXError("%i", bpRegs.genmode.cull); GL_SetCullMode(cull_modes[bpRegs.genmode.cull]); } return; // // set scissor box // case BP_SU_SCIS0: { int x, y, w, h; bpRegs.scis0.scis0 = value; x = bpRegs.scis0.sux - 342; y = bpRegs.scis0.suy - 342; w = bpRegs.scis1.suw - bpRegs.scis0.sux + 1; h = bpRegs.scis1.suh - bpRegs.scis0.suy + 1; //GFXError("scissor (%i, %i)-(%i, %i)", x, y, w, h); GL_SetScissor(x, y, w, h); } return; case BP_SU_SCIS1: { int x, y, w, h; bpRegs.scis1.scis1 = value; x = bpRegs.scis0.sux - 342; y = bpRegs.scis0.suy - 342; w = bpRegs.scis1.suw - bpRegs.scis0.sux + 1; h = bpRegs.scis1.suh - bpRegs.scis0.suy + 1; //GFXError("scissor (%i, %i)-(%i, %i)", x, y, w, h); GL_SetScissor(x, y, w, h); } return; // // set copy clear color/z // case PE_COPY_CLEAR_AR: { copyClearRGBA.A = (uint8_t)(value >> 8); copyClearRGBA.R = (uint8_t)(value ); return; } case PE_COPY_CLEAR_GB: { copyClearRGBA.G = (uint8_t)(value >> 8); copyClearRGBA.B = (uint8_t)(value ); } return; case PE_COPY_CLEAR_Z: { copyClearZ = value & 0xffffff; GL_SetClear(copyClearRGBA, copyClearZ); } return; // // texture image width, height, format // case TX_SETIMAGE_0_0: { bpRegs.teximg0[0].hex = value; bpRegs.valid[0][0] = TRUE; tryLoadTex(0); } return; // // texture image base // case TX_SETIMAGE_3_0: { bpRegs.teximg3[0].hex = value; bpRegs.valid[3][0] = TRUE; tryLoadTex(0); } return; // // load tlut // case TX_LOADTLUT0: { bpRegs.loadtlut0.hex = value; LoadTlut( (bpRegs.loadtlut0.base << 5), // ram address (bpRegs.loadtlut1.tmem << 9), // tlut offset bpRegs.loadtlut1.count // tlut size ); } return; case TX_LOADTLUT1: { bpRegs.loadtlut1.hex = value; LoadTlut( (bpRegs.loadtlut0.base << 5), // ram address (bpRegs.loadtlut1.tmem << 9), // tlut offset bpRegs.loadtlut1.count // tlut size ); } return; // // set tlut // case TX_SETTLUT_0: { bpRegs.settlut[0].hex = value; } return; // // set texture modes // case TX_SETMODE_0_0: { bpRegs.texmode0[0].hex = value; } return; // // set blending rules // case PE_CMODE0: { bpRegs.cmode0.hex = value; static const char *logicop[] = { "clear", "and", "revand", "copy", "invand", "nop", "xor", "or", "nor", "eqv", "inv", "revor", "invcopy", "invor", "nand", "set" }; static const char *sfactor[] = { "zero", "one", "srcclr", "invsrcclr", "srcalpha", "invsrcalpha", "dstalpha", "invdstalpha" }; static const char *dfactor[] = { "zero", "one", "dstclr", "invdstclr", "srcalpha", "invsrcalpha", "dstalpha", "invdstalpha" }; /*/ GFXError( "blend rules\n\n" "blend:%s, logic:%s\n" "logic op : %s\n" "sfactor : %s\n" "dfactor : %s\n", (bpRegs.cmode0.blend_en) ? ("on") : ("off"), (bpRegs.cmode0.logop_en) ? ("on") : ("off"), logicop[bpRegs.cmode0.logop], sfactor[bpRegs.cmode0.sfactor], dfactor[bpRegs.cmode0.dfactor] ); /*/ static uint32_t glsf[] = { GL_ZERO, GL_ONE, GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA }; static uint32_t gldf[] = { GL_ZERO, GL_ONE, GL_DST_COLOR, GL_ONE_MINUS_DST_COLOR, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA }; // blend hack if(bpRegs.cmode0.blend_en) { glEnable(GL_BLEND); glBlendFunc(glsf[bpRegs.cmode0.sfactor], gldf[bpRegs.cmode0.dfactor]); } else glDisable(GL_BLEND); static uint32_t logop[] = { GL_CLEAR, GL_AND, GL_AND_REVERSE, GL_COPY, GL_AND_INVERTED, GL_NOOP, GL_XOR, GL_OR, GL_NOR, GL_EQUIV, GL_INVERT, GL_OR_REVERSE, GL_COPY_INVERTED, GL_OR_INVERTED, GL_NAND, GL_SET }; // logic operations if(bpRegs.cmode0.logop_en) { glEnable(GL_COLOR_LOGIC_OP); glLogicOp(logop[bpRegs.cmode0.logop]); } else glDisable(GL_COLOR_LOGIC_OP); } return; case PE_CMODE1: { bpRegs.cmode1.hex = value; } return; case PE_ZMODE_ID: { static const char *zf[] = { "NEVER", "LESS", "EQUAL", "LEQUAL", "GREATER", "NEQUAL", "GEQUAL", "ALWAYS" }; static uint32_t glzf[] = { GL_NEVER, GL_LESS, GL_EQUAL, GL_LEQUAL, GL_GREATER, GL_NOTEQUAL, GL_GEQUAL, GL_ALWAYS }; bpRegs.zmode.hex = value; /*/ GFXError( "z mode:\n" "compare: %s\n" "func: %s\n" "update: %s", (bpRegs.zmode.enable) ? ("yes") : ("no"), zf[bpRegs.zmode.func], (bpRegs.zmode.mask) ? ("yes") : ("no") ); /*/ if(bpRegs.zmode.enable) { glEnable(GL_DEPTH_TEST); glDepthFunc(glzf[bpRegs.zmode.func]); glDepthMask(bpRegs.zmode.mask); } else glDisable(GL_DEPTH_TEST); } return; // // texture coord scale // case SU_SSIZE_0: case SU_SSIZE_1: case SU_SSIZE_2: case SU_SSIZE_3: case SU_SSIZE_4: case SU_SSIZE_5: case SU_SSIZE_6: case SU_SSIZE_7: { int num = (index >> 1) & 1; bpRegs.ssize[num].hex = value; } return; case SU_TSIZE_0: case SU_TSIZE_1: case SU_TSIZE_2: case SU_TSIZE_3: case SU_TSIZE_4: case SU_TSIZE_5: case SU_TSIZE_6: case SU_TSIZE_7: { int num = (index >> 1) & 1; bpRegs.tsize[num].hex = value; } return; default: { #ifdef GPLOG fprintf(gplog, "unknown BP load, index: %02X, data: %08X\n", index, value); fflush(gplog); #endif // GFXError("unknown BP load, index : %02X", index); } } } // index range = 0000..FFFF // reg size = 32 bit void loadXFRegs(size_t startIdx, size_t amount, GX::FifoProcessor* fifo) { xfLoads += (uint32_t)amount; #if 0 GFXError("unknown XF load, start index: %04X, n : %i\n", startIdx, amount); for(unsigned n=0; n= 0x0000) && (startIdx < 0x0400)) { for (int i = 0; i < amount; i++) { *(float*)(((uint8_t*)xfRegs.posmtx + 4 * startIdx) + 4 * i) = fifo->ReadFloat(); } #ifdef GPLOG fprintf(gplog, "load position matrix, start index: %04X\n", startIdx); for(unsigned n=0; n= 0x0400) && (startIdx < 0x0500)) { for (int i = 0; i < amount; i++) { *(float*)(((uint8_t*)xfRegs.nrmmtx + 4 * (startIdx - 0x400)) + 4 * i) = fifo->ReadFloat(); } } // load post-trans matrix else if((startIdx >= 0x0500) && (startIdx < 0x0600)) { for (int i = 0; i < amount; i++) { *(float*)(((uint8_t*)xfRegs.postmtx + 4 * (startIdx - 0x500)) + 4 * i) = fifo->ReadFloat(); } #ifdef GPLOG fprintf(gplog, "load post-transform matrix, start index: %04X\n", startIdx); for(unsigned n=0; nRead32(); xfRegs.posidx = xfRegs.matidxA.pos; xfRegs.texidx[0] = xfRegs.matidxA.tex0; xfRegs.texidx[1] = xfRegs.matidxA.tex1; xfRegs.texidx[2] = xfRegs.matidxA.tex2; xfRegs.texidx[3] = xfRegs.matidxA.tex3; //GFXError("xf posidx : %i", xfRegs.matidxA.pos); } return; case XF_MATINDEX_B: { xfRegs.matidxB.matidx = fifo->Read32(); xfRegs.texidx[4] = xfRegs.matidxB.tex4; xfRegs.texidx[5] = xfRegs.matidxB.tex5; xfRegs.texidx[6] = xfRegs.matidxB.tex6; xfRegs.texidx[7] = xfRegs.matidxB.tex7; } return; // // load projection matrix // case XF_PROJECTION: { float pMatrix[7]; pMatrix[0] = fifo->ReadFloat(); pMatrix[1] = fifo->ReadFloat(); pMatrix[2] = fifo->ReadFloat(); pMatrix[3] = fifo->ReadFloat(); pMatrix[4] = fifo->ReadFloat(); pMatrix[5] = fifo->ReadFloat(); pMatrix[6] = fifo->ReadFloat(); float Matrix[4][4]; if (pMatrix[6] == 0) { Matrix[0][0] = pMatrix[0]; Matrix[1][0] = 0.0f; Matrix[2][0] = pMatrix[1]; Matrix[3][0] = 0.0f; Matrix[0][1] = 0.0f; Matrix[1][1] = pMatrix[2]; Matrix[2][1] = pMatrix[3]; Matrix[3][1] = 0.0f; Matrix[0][2] = 0.0f; Matrix[1][2] = 0.0f; Matrix[2][2] = pMatrix[4]; Matrix[3][2] = pMatrix[5]; Matrix[0][3] = 0.0f; Matrix[1][3] = 0.0f; Matrix[2][3] = -1.0f; Matrix[3][3] = 0.0f; } else { Matrix[0][0] = pMatrix[0]; Matrix[1][0] = 0.0f; Matrix[2][0] = 0.0f; Matrix[3][0] = pMatrix[1]; Matrix[0][1] = 0.0f; Matrix[1][1] = pMatrix[2]; Matrix[2][1] = 0.0f; Matrix[3][1] = pMatrix[3]; Matrix[0][2] = 0.0f; Matrix[1][2] = 0.0f; Matrix[2][2] = pMatrix[4]; Matrix[3][2] = pMatrix[5]; Matrix[0][3] = 0.0f; Matrix[1][3] = 0.0f; Matrix[2][3] = 0.0f; Matrix[3][3] = 1.0f; } GL_SetProjection((float*)Matrix); } return; // // load viewport configuration // case XF_VIEWPORT: { float w, h, x, y, zf, zn; // // read coefficients // xfRegs.vp_scale[0] = fifo->ReadFloat(); // w / 2 xfRegs.vp_scale[1] = fifo->ReadFloat(); // -h / 2 xfRegs.vp_scale[2] = fifo->ReadFloat(); // ZMAX * (zfar - znear) xfRegs.vp_offs[0] = fifo->ReadFloat(); // x + w/2 + 342 xfRegs.vp_offs[1] = fifo->ReadFloat(); // y + h/2 + 342 xfRegs.vp_offs[2] = fifo->ReadFloat(); // ZMAX * zfar // // convert them to human usable form // w = xfRegs.vp_scale[0] * 2; h = -xfRegs.vp_scale[1] * 2; x = xfRegs.vp_offs[0] - xfRegs.vp_scale[0] - 342; y = xfRegs.vp_offs[1] + xfRegs.vp_scale[1] - 342; zf = xfRegs.vp_offs[2] / 16777215.0f; zn = -((xfRegs.vp_scale[2] / 16777215.0f) - zf); //GFXError("viewport (%.2f, %.2f)-(%.2f, %.2f), %f, %f", x, y, w, h, zn, zf); GL_SetViewport((int)x, (int)y, (int)w, (int)h, zn, zf); } return; // // load light object (unaligned writes not supported) // case XF_LIGHT0: case XF_LIGHT1: case XF_LIGHT2: case XF_LIGHT3: case XF_LIGHT4: case XF_LIGHT5: case XF_LIGHT6: case XF_LIGHT7: { unsigned lnum = (startIdx >> 4) & 7; xfRegs.light[lnum].rsrv[0] = fifo->Read32(); xfRegs.light[lnum].rsrv[1] = fifo->Read32(); xfRegs.light[lnum].rsrv[2] = fifo->Read32(); xfRegs.light[lnum].color.RGBA = fifo->Read32(); xfRegs.light[lnum].a[0] = fifo->ReadFloat(); xfRegs.light[lnum].a[1] = fifo->ReadFloat(); xfRegs.light[lnum].a[2] = fifo->ReadFloat(); xfRegs.light[lnum].k[0] = fifo->ReadFloat(); xfRegs.light[lnum].k[1] = fifo->ReadFloat(); xfRegs.light[lnum].k[2] = fifo->ReadFloat(); xfRegs.light[lnum].pos[0] = fifo->ReadFloat(); xfRegs.light[lnum].pos[1] = fifo->ReadFloat(); xfRegs.light[lnum].pos[2] = fifo->ReadFloat(); xfRegs.light[lnum].dir[0] = fifo->ReadFloat(); xfRegs.light[lnum].dir[1] = fifo->ReadFloat(); xfRegs.light[lnum].dir[2] = fifo->ReadFloat(); } return; // // channel constant color registers // case XF_AMBIENT0: { xfRegs.ambient[0].RGBA = fifo->Read32(); } return; case XF_AMBIENT1: { xfRegs.ambient[1].RGBA = fifo->Read32(); } return; case XF_MATERIAL0: { xfRegs.material[0].RGBA = fifo->Read32(); } return; case XF_MATERIAL1: { xfRegs.material[1].RGBA = fifo->Read32(); } return; // // channel control registers // case XF_COLOR0CNTL: { xfRegs.color[0].Chan = fifo->Read32(); // change light mask xfRegs.colmask[0][0] = (xfRegs.color[0].Light0) ? (TRUE) : (FALSE); xfRegs.colmask[1][0] = (xfRegs.color[0].Light1) ? (TRUE) : (FALSE); xfRegs.colmask[2][0] = (xfRegs.color[0].Light2) ? (TRUE) : (FALSE); xfRegs.colmask[3][0] = (xfRegs.color[0].Light3) ? (TRUE) : (FALSE); xfRegs.colmask[4][0] = (xfRegs.color[0].Light4) ? (TRUE) : (FALSE); xfRegs.colmask[5][0] = (xfRegs.color[0].Light5) ? (TRUE) : (FALSE); xfRegs.colmask[6][0] = (xfRegs.color[0].Light6) ? (TRUE) : (FALSE); xfRegs.colmask[7][0] = (xfRegs.color[0].Light7) ? (TRUE) : (FALSE); } return; case XF_COLOR1CNTL: { xfRegs.color[1].Chan = fifo->Read32(); // change light mask xfRegs.colmask[0][1] = (xfRegs.color[1].Light0) ? (TRUE) : (FALSE); xfRegs.colmask[1][1] = (xfRegs.color[1].Light1) ? (TRUE) : (FALSE); xfRegs.colmask[2][1] = (xfRegs.color[1].Light2) ? (TRUE) : (FALSE); xfRegs.colmask[3][1] = (xfRegs.color[1].Light3) ? (TRUE) : (FALSE); xfRegs.colmask[4][1] = (xfRegs.color[1].Light4) ? (TRUE) : (FALSE); xfRegs.colmask[5][1] = (xfRegs.color[1].Light5) ? (TRUE) : (FALSE); xfRegs.colmask[6][1] = (xfRegs.color[1].Light6) ? (TRUE) : (FALSE); xfRegs.colmask[7][1] = (xfRegs.color[1].Light7) ? (TRUE) : (FALSE); } return; case XF_ALPHA0CNTL: { xfRegs.alpha[0].Chan = fifo->Read32(); // change light mask xfRegs.amask[0][0] = (xfRegs.alpha[0].Light0) ? (TRUE) : (FALSE); xfRegs.amask[1][0] = (xfRegs.alpha[0].Light1) ? (TRUE) : (FALSE); xfRegs.amask[2][0] = (xfRegs.alpha[0].Light2) ? (TRUE) : (FALSE); xfRegs.amask[3][0] = (xfRegs.alpha[0].Light3) ? (TRUE) : (FALSE); xfRegs.amask[4][0] = (xfRegs.alpha[0].Light4) ? (TRUE) : (FALSE); xfRegs.amask[5][0] = (xfRegs.alpha[0].Light5) ? (TRUE) : (FALSE); xfRegs.amask[6][0] = (xfRegs.alpha[0].Light6) ? (TRUE) : (FALSE); xfRegs.amask[7][0] = (xfRegs.alpha[0].Light7) ? (TRUE) : (FALSE); } return; case XF_ALPHA1CNTL: { xfRegs.alpha[1].Chan = fifo->Read32(); // change light mask xfRegs.amask[0][1] = (xfRegs.alpha[1].Light0) ? (TRUE) : (FALSE); xfRegs.amask[1][1] = (xfRegs.alpha[1].Light1) ? (TRUE) : (FALSE); xfRegs.amask[2][1] = (xfRegs.alpha[1].Light2) ? (TRUE) : (FALSE); xfRegs.amask[3][1] = (xfRegs.alpha[1].Light3) ? (TRUE) : (FALSE); xfRegs.amask[4][1] = (xfRegs.alpha[1].Light4) ? (TRUE) : (FALSE); xfRegs.amask[5][1] = (xfRegs.alpha[1].Light5) ? (TRUE) : (FALSE); xfRegs.amask[6][1] = (xfRegs.alpha[1].Light6) ? (TRUE) : (FALSE); xfRegs.amask[7][1] = (xfRegs.alpha[1].Light7) ? (TRUE) : (FALSE); } return; // // set dualtex enable / disable // case XF_DUALTEX: { xfRegs.dualtex = fifo->Read32(); //GFXError("dual texgen : %s", (regData[0]) ? ("on") : ("off")); } return; case XF_DUALGEN0: case XF_DUALGEN1: case XF_DUALGEN2: case XF_DUALGEN3: case XF_DUALGEN4: case XF_DUALGEN5: case XF_DUALGEN6: case XF_DUALGEN7: { size_t n = startIdx - XF_DUALGEN0; fifo->Read32(); //ASSERT(amount != 1); //xfRegs.dual[n].hex = regData[0]; /*/ GFXError( "set dual for %i:\n" "raw: %08X\n" "index: %i\n" "normalize: %s", n, regData[0], xfRegs.dual[n].dualidx, (xfRegs.dual[n].norm) ? ("yes") : ("no") ); /*/ } return; // // number of output colors // case XF_NUMCOLS: { xfRegs.numcol = fifo->Read32(); } return; // // set number of texgens // case XF_NUMTEX: { xfRegs.numtex = fifo->Read32(); } return; // // set texgen configuration // case XF_TEXGEN0: case XF_TEXGEN1: case XF_TEXGEN2: case XF_TEXGEN3: case XF_TEXGEN4: case XF_TEXGEN5: case XF_TEXGEN6: case XF_TEXGEN7: { unsigned num = startIdx & 7; static const char *prj[] = { "2x4", "3x4" }; static const char *inf[] = { "ab11", "abc1" }; static const char *type[] = { "regular", "bump", "toon0", "toon1" }; static const char *srcrow[] = { "xyz", "normal", "colors", "binormal t", "binormal b", "tex0", "tex1", "tex2", "tex3", "tex4", "tex5", "tex6", "tex7", "", "", "" }; xfRegs.texgen[num].hex = fifo->Read32(); /*/ GFXError( "texgen %i set\n" "prj : %s\n" "in form : %s\n" "type : %s\n" "src row : %s\n" "emboss src : %i\n" "emboss lnum : %i\n", num, prj[xfRegs.texgen[num].pojection & 1], inf[xfRegs.texgen[num].in_form & 1], type[xfRegs.texgen[num].type & 3], srcrow[xfRegs.texgen[num].src_row & 0xf], xfRegs.texgen[num].emboss_src, xfRegs.texgen[num].emboss_light ); /*/ } return; // // not implemented // default: { while (amount--) { fifo->Read32(); } #ifdef GPLOG fprintf(gplog, "unknown XF load, start index: %04X\n", startIdx); for(unsigned n=0; n