void gsClear(void) { struct GsState *gs = gsCurState; uint16 x, y; int r = gs->clearcol & 0xFF; int g = (gs->clearcol >> 8) & 0xFF; int b = (gs->clearcol >> 16) & 0xFF; int a = (gs->clearcol >> 24) & 0xFF; x = (gs->width << 4) + gs->xoff; y = (gs->height << 4) + gs->yoff; GIF_BEGIN_PACKET(gifDmaBuf); GIF_TAG(gifDmaBuf, 6, 1, 0, 0, 0, 1, 0x0e); /* clear z-buffer too */ GIF_DATA_AD(gifDmaBuf, GS_TEST_1, MAKE_GS_TEST(0, 0, 0, 0, 0, 0, 1, ZTST_ALWAYS)); GIF_DATA_AD(gifDmaBuf, GS_PRIM, MAKE_GS_PRIM(PRIM_SPRITE, 0, 0, 0, 0, 0, 0, 0, 0)); GIF_DATA_AD(gifDmaBuf, GS_RGBAQ, MAKE_GS_RGBAQ(r, g, b, a, 0)); GIF_DATA_AD(gifDmaBuf, GS_XYZ2, MAKE_GS_XYZ(0, 0, 0)); GIF_DATA_AD(gifDmaBuf, GS_XYZ2, MAKE_GS_XYZ(x, y, 0)); /* re-enable z-test */ GIF_DATA_AD(gifDmaBuf, GS_TEST_1, MAKE_GS_TEST(0, 0, 0, 0, 0, 0, gs->ztest, gs->zfunc)); GIF_SEND_PACKET(gifDmaBuf); }
void gsKit_setactive(GSGLOBAL *gsGlobal) { u64 *p_data; u64 *p_store; p_data = p_store = (u64 *)gsGlobal->dma_misc; *p_data++ = GIF_TAG( 4, 1, 0, 0, 0, 1 ); *p_data++ = GIF_AD; // Context 1 *p_data++ = GS_SETREG_SCISSOR_1( 0, gsGlobal->Width - 1, 0, gsGlobal->Height - 1 ); *p_data++ = GS_SCISSOR_1; *p_data++ = GS_SETREG_FRAME_1( gsGlobal->ScreenBuffer[gsGlobal->ActiveBuffer & 1] / 8192, gsGlobal->Width / 64, gsGlobal->PSM, 0 ); *p_data++ = GS_FRAME_1; // Context 2 *p_data++ = GS_SETREG_SCISSOR_1( 0, gsGlobal->Width - 1, 0, gsGlobal->Height - 1 ); *p_data++ = GS_SCISSOR_2; *p_data++ = GS_SETREG_FRAME_1( gsGlobal->ScreenBuffer[gsGlobal->ActiveBuffer & 1] / 8192, gsGlobal->Width / 64, gsGlobal->PSM, 0 ); *p_data++ = GS_FRAME_2; dmaKit_wait_fast(); dmaKit_send_ucab(DMA_CHANNEL_GIF, p_store, 5); }
void gsSelectActiveFb(int n) { struct GsState *g = gsCurState; int addr; addr = g->fbAddr[n]/4/2048; GIF_BEGIN_PACKET(gifDmaBuf); GIF_TAG(gifDmaBuf, 1, 1, 0, 0, 0, 1, 0x0e); GIF_DATA_AD(gifDmaBuf, GS_FRAME_1, MAKE_GS_FRAME(addr, g->width/64, g->psm, 0)); GIF_SEND_PACKET(gifDmaBuf); }
void gsUpdateContext(void) { GsState *gs = gsCurState; GIF_BEGIN_PACKET(gifDmaBuf); GIF_TAG(gifDmaBuf, 2, 1, 0, 0, 0, 1, 0x0e); GIF_DATA_AD(gifDmaBuf, GS_TEST_1, MAKE_GS_TEST(0, 0, 0, 0, 0, 0, gs->ztest, gs->zfunc)); GIF_DATA_AD(gifDmaBuf, GS_ALPHA_1, MAKE_GS_ALPHA(gs->blend.a, gs->blend.b, gs->blend.c, gs->blend.d, gs->blend.fix)); GIF_SEND_PACKET(gifDmaBuf); }
void gsInit(void) { struct GsState *g = gsCurState; int addr0, addr1; g->visibleFb = 0; g->activeFb = 1; printf("%d %d\n", g->fbAddr[0], g->fbAddr[1]); addr0 = g->fbAddr[g->visibleFb]/4/2048; addr1 = g->fbAddr[g->activeFb]/4/2048; GS_RESET(); __asm__("sync.p; nop"); SET_REG64(GS_CSR, 0); GsPutIMR(0xff00); SetGsCrt(g->interlaced, g->mode, g->field); SET_REG64(GS_PMODE, MAKE_GS_PMODE(0, 1, 0, 1, 0, 0xFF)); SET_REG64(GS_DISPFB2, MAKE_GS_DISPFB(addr0, g->width/64, g->psm, 0, 0)); SET_REG64(GS_DISPFB1, MAKE_GS_DISPFB(addr0, g->width/64, g->psm, 0, 0)); SET_REG64(GS_DISPLAY2, MAKE_GS_DISPLAY(g->startx, g->starty, g->magh, g->magv, g->dw-1, g->dh-1)); SET_REG64(GS_DISPLAY1, MAKE_GS_DISPLAY(g->startx, g->starty, g->magh, g->magv, g->dw-1, g->dh-1)); SET_REG64(GS_BGCOLOR, MAKE_GS_BGCOLOR(100, 100, 100)); GIF_BEGIN_PACKET(gifDmaBuf); GIF_TAG(gifDmaBuf, 7, 1, 0, 0, 0, 1, 0x0e); GIF_DATA_AD(gifDmaBuf, GS_PRMODECONT, MAKE_GS_PRMODECONT(1)); GIF_DATA_AD(gifDmaBuf, GS_FRAME_1, MAKE_GS_FRAME(addr1, g->width/64, g->psm, 0)); GIF_DATA_AD(gifDmaBuf, GS_ZBUF_1, MAKE_GS_ZBUF(g->zbAddr/4/2048, g->zpsm, 0)); GIF_DATA_AD(gifDmaBuf, GS_XYOFFSET_1, MAKE_GS_XYOFFSET(g->xoff, g->yoff)); GIF_DATA_AD(gifDmaBuf, GS_SCISSOR_1, MAKE_GS_SCISSOR(0, g->xmax, 0, g->ymax)); GIF_DATA_AD(gifDmaBuf, GS_TEST_1, MAKE_GS_TEST(0, 0, 0, 0, 0, 0, g->ztest, g->zfunc)); GIF_DATA_AD(gifDmaBuf, GS_COLCLAMP, MAKE_GS_COLCLAMP(1)); GIF_SEND_PACKET(gifDmaBuf); }
void drawrect(uint16 x1, uint16 y1, uint16 x2, uint16 y2, uint32 col) { struct GsState *gs = gsCurState; x1 = (x1<<4) + gs->xoff; y1 = (y1<<4) + gs->yoff; x2 = (x2<<4) + gs->xoff; y2 = (y2<<4) + gs->yoff; int r = col & 0xFF; int g = (col >> 8) & 0xFF; int b = (col >> 16) & 0xFF; int a = (col >> 24) & 0xFF; GIF_BEGIN_PACKET(gifDmaBuf); GIF_TAG(gifDmaBuf, 4, 1, 0, 0, 0, 1, 0x0e); GIF_DATA_AD(gifDmaBuf, GS_PRIM, MAKE_GS_PRIM(PRIM_SPRITE, 0, 0, 0, gs->blend.enable, 0, 0, 0, 0)); GIF_DATA_AD(gifDmaBuf, GS_RGBAQ, MAKE_GS_RGBAQ(r, g, b, a, 0)); GIF_DATA_AD(gifDmaBuf, GS_XYZ2, MAKE_GS_XYZ(x1, y1, 0)); GIF_DATA_AD(gifDmaBuf, GS_XYZ2, MAKE_GS_XYZ(x2, y2, 0)); GIF_SEND_PACKET(gifDmaBuf); }
void gsKit_init_screen(GSGLOBAL *gsGlobal) { u64 *p_data; u64 *p_store; int size = 18; if((gsGlobal->Dithering == GS_SETTING_ON) && ((gsGlobal->PSM == GS_PSM_CT16) || (gsGlobal->PSM == GS_PSM_CT16S))) size = 19; gsKit_set_buffer_attributes(gsGlobal); #ifdef DEBUG printf("Screen Mode:\n"); printf("------------\n"); printf("Width : %d\n", gsGlobal->Width); printf("Height: %d\n", gsGlobal->Height); printf("StartX: %d\n", gsGlobal->StartX); printf("StartY: %d\n", gsGlobal->StartY); printf("MagH : %d\n", gsGlobal->MagH); printf("MagV : %d\n", gsGlobal->MagV); printf("DW : %d\n", gsGlobal->DW); printf("DH : %d\n", gsGlobal->DH); #endif GS_RESET(); __asm__("sync.p; nop;"); *GS_CSR = 0x00000000; // Clean CSR registers GsPutIMR(0x0000F700); // Unmasks all of the GS interrupts SetGsCrt(gsGlobal->Interlace, gsGlobal->Mode, gsGlobal->Field); gsGlobal->FirstFrame = GS_SETTING_ON; if(gsGlobal->ZBuffering == GS_SETTING_OFF) { gsGlobal->Test->ZTE = GS_SETTING_ON; gsGlobal->Test->ZTST = 1; } DIntr(); // disable interrupts GS_SET_PMODE( 0, // Read Circuit 1 1, // Read Circuit 2 0, // Use ALP Register for Alpha Blending 1, // Alpha Value of Read Circuit 2 for Output Selection 0, // Blend Alpha with output of Read Circuit 2 0x80); // Alpha Value = 1.0 GS_SET_DISPFB1( 0, // Frame Buffer Base Pointer (Address/2048) gsGlobal->Width / 64, // Buffer Width (Address/64) gsGlobal->PSM, // Pixel Storage Format 0, // Upper Left X in Buffer 0); GS_SET_DISPFB2( 0, // Frame Buffer Base Pointer (Address/2048) gsGlobal->Width / 64, // Buffer Width (Address/64) gsGlobal->PSM, // Pixel Storage Format 0, // Upper Left X in Buffer 0); // Upper Left Y in Buffer GS_SET_DISPLAY1(gsGlobal->StartX, // X position in the display area (in VCK unit gsGlobal->StartY, // Y position in the display area (in Raster u gsGlobal->MagH, // Horizontal Magnification gsGlobal->MagV, // Vertical Magnification gsGlobal->DW - 1, // Display area width gsGlobal->DH - 1); // Display area height GS_SET_DISPLAY2(gsGlobal->StartX, // X position in the display area (in VCK units) gsGlobal->StartY, // Y position in the display area (in Raster units) gsGlobal->MagH, // Horizontal Magnification gsGlobal->MagV, // Vertical Magnification gsGlobal->DW - 1, // Display area width gsGlobal->DH - 1); // Display area height GS_SET_BGCOLOR( gsGlobal->BGColor->Red, // Red gsGlobal->BGColor->Green, // Green gsGlobal->BGColor->Blue); // Blue EIntr(); //enable interrupts gsGlobal->CurrentPointer = 0; // reset vram pointer too // Context 1 gsGlobal->ScreenBuffer[0] = gsKit_vram_alloc( gsGlobal, gsKit_texture_size(gsGlobal->Width, gsGlobal->Height, gsGlobal->PSM), GSKIT_ALLOC_SYSBUFFER ); if(gsGlobal->DoubleBuffering == GS_SETTING_OFF) { gsGlobal->ScreenBuffer[1] = gsGlobal->ScreenBuffer[0]; } else // Context 2 gsGlobal->ScreenBuffer[1] = gsKit_vram_alloc( gsGlobal, gsKit_texture_size(gsGlobal->Width, gsGlobal->Height, gsGlobal->PSM), GSKIT_ALLOC_SYSBUFFER ); if(gsGlobal->ZBuffering == GS_SETTING_ON) gsGlobal->ZBuffer = gsKit_vram_alloc( gsGlobal, gsKit_texture_size(gsGlobal->Width, gsGlobal->Height, gsGlobal->PSMZ), GSKIT_ALLOC_SYSBUFFER ); // Z Buffer gsGlobal->TexturePointer = gsGlobal->CurrentPointer; // first useable address for textures p_data = p_store = (u64 *)gsGlobal->dma_misc; *p_data++ = GIF_TAG( size - 1, 1, 0, 0, 0, 1 ); *p_data++ = GIF_AD; *p_data++ = 1; *p_data++ = GS_PRMODECONT; *p_data++ = GS_SETREG_FRAME_1( gsGlobal->ScreenBuffer[0], gsGlobal->Width / 64, gsGlobal->PSM, 0 ); *p_data++ = GS_FRAME_1; *p_data++ = GS_SETREG_XYOFFSET_1( gsGlobal->OffsetX, gsGlobal->OffsetY); *p_data++ = GS_XYOFFSET_1; *p_data++ = GS_SETREG_SCISSOR_1( 0, gsGlobal->Width - 1, 0, gsGlobal->Height - 1 ); *p_data++ = GS_SCISSOR_1; *p_data++ = GS_SETREG_TEST( gsGlobal->Test->ATE, gsGlobal->Test->ATST, gsGlobal->Test->AREF, gsGlobal->Test->AFAIL, gsGlobal->Test->DATE, gsGlobal->Test->DATM, gsGlobal->Test->ZTE, gsGlobal->Test->ZTST ); *p_data++ = GS_TEST_1; *p_data++ = GS_SETREG_CLAMP(gsGlobal->Clamp->WMS, gsGlobal->Clamp->WMT, gsGlobal->Clamp->MINU, gsGlobal->Clamp->MAXU, gsGlobal->Clamp->MINV, gsGlobal->Clamp->MAXV); *p_data++ = GS_CLAMP_1; if(gsGlobal->ZBuffering == GS_SETTING_ON) { if((gsGlobal->PSM == GS_PSM_CT16) && (gsGlobal->PSMZ != GS_PSMZ_16)) gsGlobal->PSMZ = GS_PSMZ_16; // seems only non-S 16-bit z depth works with this mode if((gsGlobal->PSM != GS_PSM_CT16) && (gsGlobal->PSMZ == GS_PSMZ_16)) gsGlobal->PSMZ = GS_PSMZ_16S; // other depths don't seem to work with 16-bit non-S z depth *p_data++ = GS_SETREG_ZBUF_1( gsGlobal->ZBuffer / 8192, gsGlobal->PSMZ, 0 ); *p_data++ = GS_ZBUF_1; } if(gsGlobal->ZBuffering == GS_SETTING_OFF) { *p_data++ = GS_SETREG_ZBUF_1( NULL, gsGlobal->PSM, 1 ); *p_data++ = GS_ZBUF_1; } *p_data++ = GS_SETREG_COLCLAMP( 255 ); *p_data++ = GS_COLCLAMP; *p_data++ = GS_SETREG_FRAME_1( gsGlobal->ScreenBuffer[1], gsGlobal->Width / 64, gsGlobal->PSM, 0 ); *p_data++ = GS_FRAME_2; *p_data++ = GS_SETREG_XYOFFSET_1( gsGlobal->OffsetX, gsGlobal->OffsetY); *p_data++ = GS_XYOFFSET_2; *p_data++ = GS_SETREG_SCISSOR_1( 0, gsGlobal->Width - 1, 0, gsGlobal->Height - 1); *p_data++ = GS_SCISSOR_2; *p_data++ = GS_SETREG_TEST( gsGlobal->Test->ATE, gsGlobal->Test->ATST, gsGlobal->Test->AREF, gsGlobal->Test->AFAIL, gsGlobal->Test->DATE, gsGlobal->Test->DATM, gsGlobal->Test->ZTE, gsGlobal->Test->ZTST ); *p_data++ = GS_TEST_2; *p_data++ = GS_SETREG_CLAMP(gsGlobal->Clamp->WMS, gsGlobal->Clamp->WMT, gsGlobal->Clamp->MINU, gsGlobal->Clamp->MAXU, gsGlobal->Clamp->MINV, gsGlobal->Clamp->MAXV); *p_data++ = GS_CLAMP_2; if(gsGlobal->ZBuffering == GS_SETTING_ON) { *p_data++ = GS_SETREG_ZBUF_1( gsGlobal->ZBuffer / 8192, gsGlobal->PSMZ, 0 ); *p_data++ = GS_ZBUF_2; } if(gsGlobal->ZBuffering == GS_SETTING_OFF) { *p_data++ = GS_SETREG_ZBUF_1( NULL, gsGlobal->PSM, 1 ); *p_data++ = GS_ZBUF_2; } *p_data++ = GS_BLEND_BACK2FRONT; *p_data++ = GS_ALPHA_1; *p_data++ = GS_BLEND_BACK2FRONT; *p_data++ = GS_ALPHA_2; *p_data++ = GS_SETREG_DIMX(gsGlobal->DitherMatrix[0],gsGlobal->DitherMatrix[1], gsGlobal->DitherMatrix[2],gsGlobal->DitherMatrix[3],gsGlobal->DitherMatrix[4], gsGlobal->DitherMatrix[5],gsGlobal->DitherMatrix[6],gsGlobal->DitherMatrix[7], gsGlobal->DitherMatrix[8],gsGlobal->DitherMatrix[9],gsGlobal->DitherMatrix[10], gsGlobal->DitherMatrix[11],gsGlobal->DitherMatrix[12],gsGlobal->DitherMatrix[13], gsGlobal->DitherMatrix[14],gsGlobal->DitherMatrix[15]); // 4x4 dither matrix *p_data++ = GS_DIMX; if((gsGlobal->Dithering == GS_SETTING_ON) && ((gsGlobal->PSM == GS_PSM_CT16) || (gsGlobal->PSM == GS_PSM_CT16S))) { *p_data++ = 1; *p_data++ = GS_DTHE; } dmaKit_send_ucab(DMA_CHANNEL_GIF, p_store, size); dmaKit_wait_fast(); // do a single frame here to get rid whatever needs to be done during the first frame gsKit_clear(gsGlobal, GS_SETREG_RGBAQ(0x00,0x00,0x00,0x00,0x00)); // clear the screen gsKit_queue_exec(gsGlobal); gsKit_sync_flip(gsGlobal); gsKit_queue_reset(gsGlobal->Os_Queue); }
///////////////////////////////////////////////////////////////////////////////////////// // void* PbPart1_DrawObject ///////////////////////////////////////////////////////////////////////////////////////// void* PbPart2_DrawObject( PbMatrix* pLocalToScreen,int resolj, void *pChain) { s32 num_coords = 0; u32 num_sections = 0; u16 i = 0; int set_gif = 1; u64* p_store = pChain = PbSprAlloc( 10*16 ); ///////////////////////////////////////////////////////////////////////////////////// // Setup double buffering *((u64*)pChain)++ = DMA_CNT_TAG( 1 ); *((u32*)pChain)++ = VIF_CODE( VIF_NOP,0,0 ); *((u32*)pChain)++ = VIF_CODE( VIF_NOP,0,0 ); *((u32*)pChain)++ = VIF_CODE( VIF_STMOD,0,0 ); // normalmode *((u32*)pChain)++ = VIF_CODE( VIF_BASE,0,9 ); *((u32*)pChain)++ = VIF_CODE( VIF_OFFSET,0,512-9 ); *((u32*)pChain)++ = VIF_CODE( VIF_NOP,0,0 ); //////////////////////////////////////////////////////////////////////////////////// // Add LocalToScreen to the list *((u64*)pChain)++ = DMA_REF_TAG( (u32)pLocalToScreen, 4 ); *((u32*)pChain)++ = VIF_CODE( VIF_STCYL,0,0x0404 ); *((u32*)pChain)++ = VIF_CODE( VIF_UNPACK_V4_32,4,0 ); //////////////////////////////////////////////////////////////////////////////////// // Add parameters to the list *((u64*)pChain)++ = DMA_REF_TAG( (u32)&pPart2Param, 9 ); *((u32*)pChain)++ = VIF_CODE( VIF_STCYL,0,0x0404 ); *((u32*)pChain)++ = VIF_CODE( VIF_UNPACK_V4_32,9,12 ); //////////////////////////////////////////////////////////////////////////////////// // Add GifTag to list *((u64*)pChain)++ = DMA_CNT_TAG( 1 ); *((u32*)pChain)++ = VIF_CODE( VIF_STCYL,0,0x0404 ); *((u32*)pChain)++ = VIF_CODE( VIF_UNPACK_V4_32,1,21 ); // GIF_TAG(NLOOP,EOP,PRE,PRIM,FLG,NREG) *((u64*)pChain)++ = GIF_TAG( resolj-1, 1, 1, GS_SETREG_PRIM( GS_PRIM_PRIM_POINT, 0, 0, 0, 0, 0, 0, 0, 0 ), 0, 2 ); *((u64*)pChain)++ = 0x51; // registers to set //////////////////////////////////////////////////////////////////////////////////// // Add Call the program *((u64*)pChain)++ = DMA_CNT_TAG( 1 ); *((u32*)pChain)++ = VIF_CODE( VIF_NOP,0,0 ); *((u32*)pChain)++ = VIF_CODE( VIF_NOP,0,0 ); *((u32*)pChain)++ = VIF_CODE( VIF_NOP,0,0 ); *((u32*)pChain)++ = VIF_CODE( VIF_MSCAL,0,0 ); *((u32*)pChain)++ = VIF_CODE( VIF_NOP,0,0 ); *((u32*)pChain)++ = VIF_CODE( VIF_NOP,0,0 ); *((u64*)pChain)++ = DMA_END_TAG( 0 ); *((u32*)pChain)++ = VIF_CODE( VIF_NOP,0,0 ); *((u32*)pChain)++ = VIF_CODE( VIF_NOP,0,0 ); FlushCache(0); PbDmaWait01(); // lets make sure the dma is ready. PbDmaSend01ChainSpr( p_store); return NULL; }
void gsKit_vram_dump(GSGLOBAL *gsGlobal, char *Path, u32 StartAddr, u32 EndAddr) { #if 0 u64* p_store; u64* p_data; u32* p_mem; int packets; int remain; int qwc; int Size; printf("THIS IS NOT DONE YET!\n"); return 0; StartAddr = (-GS_VRAM_BLOCKSIZE)&(StartAddr+GS_VRAM_BLOCKSIZE-1); EndAddr = (-GS_VRAM_BLOCKSIZE)&(EndAddr+GS_VRAM_BLOCKSIZE-1); Size = EndAddr - StartAddr; qwc = Size / 16; if( Size % 16 ) { #ifdef DEBUG printf("Uneven division of quad word count from VRAM alloc. Rounding up QWC.\n"); #endif qwc++; } packets = qwc / DMA_MAX_SIZE; remain = qwc % DMA_MAX_SIZE; p_store = p_data = dmaKit_spr_alloc( 7 * 16 ); FlushCache(0); // DMA DATA *p_data++ = DMA_TAG( 6, 0, DMA_CNT, 0, 0, 0 ); *p_data++ = 0; *p_data++ = GIF_TAG( 5, 1, 0, 0, 0, 1 ); *p_data++ = GIF_AD; *p_data++ = GS_SETREG_BITBLTBUF(StartAddr / 64, (4095.9375 / 64), 0, 0, 0, 0); *p_data++ = GS_BITBLTBUF; *p_data++ = GS_SETREG_TRXPOS(0, 0, 0, 0, 0); *p_data++ = GS_TRXPOS; *p_data++ = GS_SETREG_TRXREG(4095.9375, 4095.9375); *p_data++ = GS_TRXREG; *p_data++ = 0; *p_data++ = GS_FINISH; *p_data++ = GS_SETREG_TRXDIR(1); *p_data++ = GS_TRXDIR; dmaKit_send_spr( DMA_CHANNEL_GIF, 0, p_store, 7 ); while(GS_CSR_FINISH != 1); GS_SETREG_CSR_FINISH(1); FlushCache(0); GS_SETREG_BUSDIR(1); #endif }
void meshDraw(Mesh *m) { struct GsState *g = gsCurState; int i, j; Vector4f vf; Vector4f n; Vector4f lightdir = {1.0f, 1.0f, 1.0f }; float intens; uint32 vi[3]; uint8 c[4]; int blockCount; int vertexCount; int blockVertCount; int vertexOffset; uint64 regs, numRegs; uint64 prim; int ind; vec3fNormalize(lightdir); if (m->attribs & MESHATTR_INDEXED) vertexCount = m->indexCount; else vertexCount = m->vertexCount; blockCount = vertexCount/39 + ((vertexCount%39) ? 1 : 0); regs = 0x5; // XYZ numRegs = 1; if (m->attribs & MESHATTR_COLORS || m->attribs & MESHATTR_NORMALS) { regs = (regs << 4) | 0x1; // RGBAQ numRegs++; } // TODO: texcoords and normals prim = MAKE_GS_PRIM(m->primitive,IIP_GOURAUD,0,0,0,0,0,0,0); vertexOffset = 0; for (i = 0; i < blockCount; i++) { blockVertCount = 39; if (i == blockCount-1) { blockVertCount = vertexCount % 39; if (blockVertCount == 0) blockVertCount = 39; } if (m->primitive == PRIM_TRI_STRIP && vertexOffset > 0) { vertexOffset -= 2; blockVertCount += 2; } GIF_BEGIN_PACKET(meshGifBuf); GIF_TAG(meshGifBuf,blockVertCount,1,1,prim,0,numRegs,regs); for (j = 0; j < blockVertCount; j++) { if (m->attribs & MESHATTR_INDEXED) ind = m->indices[j + vertexOffset]; else ind = j + vertexOffset; vec4fCopy(vf, m->vertices[ind]); vf[3] = 1.0f; matMultVec(mathModelViewMat, vf); matMultVec(mathProjectionMat, vf); vf[0] /= vf[3]; vf[1] /= vf[3]; vf[2] /= vf[3]; gsNormalizedToScreen(vf, vi); vi[0] = ((vi[0]*16) + g->xoff) & 0xFFFF; vi[1] = ((vi[1]*16) + g->yoff) & 0xFFFF; if (m->attribs & MESHATTR_COLORS) { c[0] = m->colors[ind][0]; c[1] = m->colors[ind][1]; c[2] = m->colors[ind][2]; c[3] = m->colors[ind][3]; GIF_DATA_RGBAQ(meshGifBuf,c[0],c[1],c[2],c[3]); } else if (m->attribs & MESHATTR_NORMALS) { vec4fCopy(n, m->normals[ind]); matMultVec(mathNormalMat, n); vec3fNormalize(n); intens = vec3fDot(n, lightdir); intens = intens > 0.0f ? intens : 0.0f; c[0] = intens * 255.0f; c[1] = intens * 0.0f; c[2] = intens * 255.0f; c[3] = 128.0f; GIF_DATA_RGBAQ(meshGifBuf,c[0],c[1],c[2],c[3]); } GIF_DATA_XYZ2(meshGifBuf,vi[0],vi[1],vi[2],0); } GIF_SEND_PACKET(meshGifBuf); vertexOffset += blockVertCount; } }