/*************************************************************************** prim.c - description ------------------- begin : Sun Oct 28 2001 copyright : (C) 2001 by Pete Bernert email : BlackDove@addcom.de ***************************************************************************/ /*************************************************************************** * * * 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. See also the license.txt file for * * additional informations. * * * ***************************************************************************/ #define _IN_PRIMDRAW #include "externals.h" #include "gpu.h" #include "draw.h" #include "soft.h" #include "swap.h" //////////////////////////////////////////////////////////////////////// // globals //////////////////////////////////////////////////////////////////////// BOOL bUsingTWin=FALSE; TWin_t TWin; //unsigned long clutid; // global clut unsigned short usMirror=0; // sprite mirror int iDither=0; int32_t drawX; int32_t drawY; int32_t drawW; int32_t drawH; uint32_t dwCfgFixes; uint32_t dwActFixes=0; uint32_t dwEmuFixes=0; int iUseFixes; int iUseDither=0; BOOL bDoVSyncUpdate=FALSE; //////////////////////////////////////////////////////////////////////// // Some ASM color convertion by LEWPY //////////////////////////////////////////////////////////////////////// #ifdef USE_NASM #define BGR24to16 i386_BGR24to16 __inline unsigned short BGR24to16 (uint32_t BGR); #else __inline unsigned short BGR24to16 (uint32_t BGR) { return (unsigned short)(((BGR>>3)&0x1f)|((BGR&0xf80000)>>9)|((BGR&0xf800)>>6)); } #endif //////////////////////////////////////////////////////////////////////// // Update global TP infos //////////////////////////////////////////////////////////////////////// __inline void UpdateGlobalTP(unsigned short gdata) { GlobalTextAddrX = (gdata << 6) & 0x3c0; // texture addr if(iGPUHeight==1024) { if(dwGPUVersion==2) { GlobalTextAddrY =((gdata & 0x60 ) << 3); GlobalTextIL =(gdata & 0x2000) >> 13; GlobalTextABR = (unsigned short)((gdata >> 7) & 0x3); GlobalTextTP = (gdata >> 9) & 0x3; if(GlobalTextTP==3) GlobalTextTP=2; usMirror =0; lGPUstatusRet = (lGPUstatusRet & 0xffffe000 ) | (gdata & 0x1fff ); // tekken dithering? right now only if dithering is forced by user if(iUseDither==2) iDither=2; else iDither=0; return; } else { GlobalTextAddrY = (unsigned short)(((gdata << 4) & 0x100) | ((gdata >> 2) & 0x200)); } } else GlobalTextAddrY = (gdata << 4) & 0x100; GlobalTextTP = (gdata >> 7) & 0x3; // tex mode (4,8,15) if(GlobalTextTP==3) GlobalTextTP=2; // seen in Wild9 :( GlobalTextABR = (gdata >> 5) & 0x3; // blend mode lGPUstatusRet&=~0x000001ff; // Clear the necessary bits lGPUstatusRet|=(gdata & 0x01ff); // set the necessary bits switch(iUseDither) { case 0: iDither=0; break; case 1: if(lGPUstatusRet&0x0200) iDither=2; else iDither=0; break; case 2: iDither=2; break; } } //////////////////////////////////////////////////////////////////////// __inline void SetRenderMode(uint32_t DrawAttributes) { DrawSemiTrans = (SEMITRANSBIT(DrawAttributes)) ? TRUE : FALSE; if(SHADETEXBIT(DrawAttributes)) {g_m1=g_m2=g_m3=128;} else { if((dwActFixes&4) && ((DrawAttributes&0x00ffffff)==0)) DrawAttributes|=0x007f7f7f; g_m1=(short)(DrawAttributes&0xff); g_m2=(short)((DrawAttributes>>8)&0xff); g_m3=(short)((DrawAttributes>>16)&0xff); } } //////////////////////////////////////////////////////////////////////// // oki, here are the psx gpu coord rules: poly coords are // 11 bit signed values (-1024...1023). If the x or y distance // exceeds 1024, the polygon will not be drawn. // Since quads are treated as two triangles by the real gpu, // this 'discard rule' applies to each of the quad's triangle // (so one triangle can be drawn, the other one discarded). // Also, y drawing is wrapped at 512 one time, // then it will get negative (and therefore not drawn). The // 'CheckCoord' funcs are a simple (not comlete!) approach to // do things right, I will add a better detection soon... the // current approach will be easier to do in hw/accel plugins, imho // 11 bit signed #define SIGNSHIFT 21 #define CHKMAX_X 1024 #define CHKMAX_Y 512 void AdjustCoord4() { lx0=(short)(((int)lx0<>SIGNSHIFT); lx1=(short)(((int)lx1<>SIGNSHIFT); lx2=(short)(((int)lx2<>SIGNSHIFT); lx3=(short)(((int)lx3<>SIGNSHIFT); ly0=(short)(((int)ly0<>SIGNSHIFT); ly1=(short)(((int)ly1<>SIGNSHIFT); ly2=(short)(((int)ly2<>SIGNSHIFT); ly3=(short)(((int)ly3<>SIGNSHIFT); } void AdjustCoord3() { lx0=(short)(((int)lx0<>SIGNSHIFT); lx1=(short)(((int)lx1<>SIGNSHIFT); lx2=(short)(((int)lx2<>SIGNSHIFT); ly0=(short)(((int)ly0<>SIGNSHIFT); ly1=(short)(((int)ly1<>SIGNSHIFT); ly2=(short)(((int)ly2<>SIGNSHIFT); } void AdjustCoord2() { lx0=(short)(((int)lx0<>SIGNSHIFT); lx1=(short)(((int)lx1<>SIGNSHIFT); ly0=(short)(((int)ly0<>SIGNSHIFT); ly1=(short)(((int)ly1<>SIGNSHIFT); } void AdjustCoord1() { lx0=(short)(((int)lx0<>SIGNSHIFT); ly0=(short)(((int)ly0<>SIGNSHIFT); if(lx0<-512 && PSXDisplay.DrawOffset.x<=-512) lx0+=2048; if(ly0<-512 && PSXDisplay.DrawOffset.y<=-512) ly0+=2048; } //////////////////////////////////////////////////////////////////////// // special checks... nascar, syphon filter 2, mgs //////////////////////////////////////////////////////////////////////// // xenogears FT4: not removed correctly right now... the tri 0,1,2 // should get removed, the tri 1,2,3 should stay... pfff // x -466 1023 180 1023 // y 20 -228 222 -100 // 0 __1 // \ / \ // 2___3 __inline BOOL CheckCoord4() { if(lx0<0) { if(((lx1-lx0)>CHKMAX_X) || ((lx2-lx0)>CHKMAX_X)) { if(lx3<0) { if((lx1-lx3)>CHKMAX_X) return TRUE; if((lx2-lx3)>CHKMAX_X) return TRUE; } } } if(lx1<0) { if((lx0-lx1)>CHKMAX_X) return TRUE; if((lx2-lx1)>CHKMAX_X) return TRUE; if((lx3-lx1)>CHKMAX_X) return TRUE; } if(lx2<0) { if((lx0-lx2)>CHKMAX_X) return TRUE; if((lx1-lx2)>CHKMAX_X) return TRUE; if((lx3-lx2)>CHKMAX_X) return TRUE; } if(lx3<0) { if(((lx1-lx3)>CHKMAX_X) || ((lx2-lx3)>CHKMAX_X)) { if(lx0<0) { if((lx1-lx0)>CHKMAX_X) return TRUE; if((lx2-lx0)>CHKMAX_X) return TRUE; } } } if(ly0<0) { if((ly1-ly0)>CHKMAX_Y) return TRUE; if((ly2-ly0)>CHKMAX_Y) return TRUE; } if(ly1<0) { if((ly0-ly1)>CHKMAX_Y) return TRUE; if((ly2-ly1)>CHKMAX_Y) return TRUE; if((ly3-ly1)>CHKMAX_Y) return TRUE; } if(ly2<0) { if((ly0-ly2)>CHKMAX_Y) return TRUE; if((ly1-ly2)>CHKMAX_Y) return TRUE; if((ly3-ly2)>CHKMAX_Y) return TRUE; } if(ly3<0) { if((ly1-ly3)>CHKMAX_Y) return TRUE; if((ly2-ly3)>CHKMAX_Y) return TRUE; } return FALSE; } __inline BOOL CheckCoord3() { if(lx0<0) { if((lx1-lx0)>CHKMAX_X) return TRUE; if((lx2-lx0)>CHKMAX_X) return TRUE; } if(lx1<0) { if((lx0-lx1)>CHKMAX_X) return TRUE; if((lx2-lx1)>CHKMAX_X) return TRUE; } if(lx2<0) { if((lx0-lx2)>CHKMAX_X) return TRUE; if((lx1-lx2)>CHKMAX_X) return TRUE; } if(ly0<0) { if((ly1-ly0)>CHKMAX_Y) return TRUE; if((ly2-ly0)>CHKMAX_Y) return TRUE; } if(ly1<0) { if((ly0-ly1)>CHKMAX_Y) return TRUE; if((ly2-ly1)>CHKMAX_Y) return TRUE; } if(ly2<0) { if((ly0-ly2)>CHKMAX_Y) return TRUE; if((ly1-ly2)>CHKMAX_Y) return TRUE; } return FALSE; } __inline BOOL CheckCoord2() { if(lx0<0) { if((lx1-lx0)>CHKMAX_X) return TRUE; } if(lx1<0) { if((lx0-lx1)>CHKMAX_X) return TRUE; } if(ly0<0) { if((ly1-ly0)>CHKMAX_Y) return TRUE; } if(ly1<0) { if((ly0-ly1)>CHKMAX_Y) return TRUE; } return FALSE; } __inline BOOL CheckCoordL(short slx0,short sly0,short slx1,short sly1) { if(slx0<0) { if((slx1-slx0)>CHKMAX_X) return TRUE; } if(slx1<0) { if((slx0-slx1)>CHKMAX_X) return TRUE; } if(sly0<0) { if((sly1-sly0)>CHKMAX_Y) return TRUE; } if(sly1<0) { if((sly0-sly1)>CHKMAX_Y) return TRUE; } return FALSE; } //////////////////////////////////////////////////////////////////////// // mask stuff... used in silent hill //////////////////////////////////////////////////////////////////////// void cmdSTP(unsigned char * baseAddr) { uint32_t gdata = GETLE32(&((uint32_t*)baseAddr)[0]); lGPUstatusRet&=~0x1800; // Clear the necessary bits lGPUstatusRet|=((gdata & 0x03) << 11); // Set the necessary bits if(gdata&1) {sSetMask=0x8000;lSetMask=0x80008000;} else {sSetMask=0; lSetMask=0; } if(gdata&2) bCheckMask=TRUE; else bCheckMask=FALSE; } //////////////////////////////////////////////////////////////////////// // cmd: Set texture page infos //////////////////////////////////////////////////////////////////////// void cmdTexturePage(unsigned char * baseAddr) { uint32_t gdata = GETLE32(&((uint32_t*)baseAddr)[0]); lGPUstatusRet&=~0x000007ff; lGPUstatusRet|=(gdata & 0x07ff); usMirror=gdata&0x3000; UpdateGlobalTP((unsigned short)gdata); GlobalTextREST = (gdata&0x00ffffff)>>9; } //////////////////////////////////////////////////////////////////////// // cmd: turn on/off texture window //////////////////////////////////////////////////////////////////////// void cmdTextureWindow(unsigned char *baseAddr) { uint32_t gdata = GETLE32(&((uint32_t*)baseAddr)[0]); uint32_t YAlign,XAlign; lGPUInfoVals[INFO_TW]=gdata&0xFFFFF; if(gdata & 0x020) TWin.Position.y1 = 8; // xxxx1 else if (gdata & 0x040) TWin.Position.y1 = 16; // xxx10 else if (gdata & 0x080) TWin.Position.y1 = 32; // xx100 else if (gdata & 0x100) TWin.Position.y1 = 64; // x1000 else if (gdata & 0x200) TWin.Position.y1 = 128; // 10000 else TWin.Position.y1 = 256; // 00000 // Texture window size is determined by the least bit set of the relevant 5 bits if (gdata & 0x001) TWin.Position.x1 = 8; // xxxx1 else if (gdata & 0x002) TWin.Position.x1 = 16; // xxx10 else if (gdata & 0x004) TWin.Position.x1 = 32; // xx100 else if (gdata & 0x008) TWin.Position.x1 = 64; // x1000 else if (gdata & 0x010) TWin.Position.x1 = 128; // 10000 else TWin.Position.x1 = 256; // 00000 // Re-calculate the bit field, because we can't trust what is passed in the data YAlign = (uint32_t)(32 - (TWin.Position.y1 >> 3)); XAlign = (uint32_t)(32 - (TWin.Position.x1 >> 3)); // Absolute position of the start of the texture window TWin.Position.y0 = (short)(((gdata >> 15) & YAlign) << 3); TWin.Position.x0 = (short)(((gdata >> 10) & XAlign) << 3); if((TWin.Position.x0 == 0 && // tw turned off TWin.Position.y0 == 0 && TWin.Position.x1 == 0 && TWin.Position.y1 == 0) || (TWin.Position.x1 == 256 && TWin.Position.y1 == 256)) { bUsingTWin = FALSE; // -> just do it } else // otherwise { bUsingTWin = TRUE; // -> tw turned on } } //////////////////////////////////////////////////////////////////////// // cmd: start of drawing area... primitives will be clipped inside //////////////////////////////////////////////////////////////////////// void cmdDrawAreaStart(unsigned char * baseAddr) { uint32_t gdata = GETLE32(&((uint32_t*)baseAddr)[0]); drawX = gdata & 0x3ff; // for soft drawing if(dwGPUVersion==2) { lGPUInfoVals[INFO_DRAWSTART]=gdata&0x3FFFFF; drawY = (gdata>>12)&0x3ff; if(drawY>=1024) drawY=1023; // some security } else { lGPUInfoVals[INFO_DRAWSTART]=gdata&0xFFFFF; drawY = (gdata>>10)&0x3ff; if(drawY>=512) drawY=511; // some security } } //////////////////////////////////////////////////////////////////////// // cmd: end of drawing area... primitives will be clipped inside //////////////////////////////////////////////////////////////////////// void cmdDrawAreaEnd(unsigned char * baseAddr) { uint32_t gdata = GETLE32(&((uint32_t*)baseAddr)[0]); drawW = gdata & 0x3ff; // for soft drawing if(dwGPUVersion==2) { lGPUInfoVals[INFO_DRAWEND]=gdata&0x3FFFFF; drawH = (gdata>>12)&0x3ff; if(drawH>=1024) drawH=1023; // some security } else { lGPUInfoVals[INFO_DRAWEND]=gdata&0xFFFFF; drawH = (gdata>>10)&0x3ff; if(drawH>=512) drawH=511; // some security } } //////////////////////////////////////////////////////////////////////// // cmd: draw offset... will be added to prim coords //////////////////////////////////////////////////////////////////////// void cmdDrawOffset(unsigned char * baseAddr) { uint32_t gdata = GETLE32(&((uint32_t*)baseAddr)[0]); PSXDisplay.DrawOffset.x = (short)(gdata & 0x7ff); if(dwGPUVersion==2) { lGPUInfoVals[INFO_DRAWOFF]=gdata&0x7FFFFF; PSXDisplay.DrawOffset.y = (short)((gdata>>12) & 0x7ff); } else { lGPUInfoVals[INFO_DRAWOFF]=gdata&0x3FFFFF; PSXDisplay.DrawOffset.y = (short)((gdata>>11) & 0x7ff); } PSXDisplay.DrawOffset.y=(short)(((int)PSXDisplay.DrawOffset.y<<21)>>21); PSXDisplay.DrawOffset.x=(short)(((int)PSXDisplay.DrawOffset.x<<21)>>21); } //////////////////////////////////////////////////////////////////////// // cmd: load image to vram //////////////////////////////////////////////////////////////////////// void primLoadImage(unsigned char * baseAddr) { unsigned short *sgpuData = ((unsigned short *) baseAddr); VRAMWrite.x = GETLEs16(&sgpuData[2])&0x3ff; VRAMWrite.y = GETLEs16(&sgpuData[3])&iGPUHeightMask; VRAMWrite.Width = GETLEs16(&sgpuData[4]); VRAMWrite.Height = GETLEs16(&sgpuData[5]); DataWriteMode = DR_VRAMTRANSFER; VRAMWrite.ImagePtr = psxVuw + (VRAMWrite.y<<10) + VRAMWrite.x; VRAMWrite.RowsRemaining = VRAMWrite.Width; VRAMWrite.ColsRemaining = VRAMWrite.Height; } //////////////////////////////////////////////////////////////////////// // cmd: vram -> psx mem //////////////////////////////////////////////////////////////////////// void primStoreImage(unsigned char * baseAddr) { unsigned short *sgpuData = ((unsigned short *) baseAddr); VRAMRead.x = GETLEs16(&sgpuData[2])&0x03ff; VRAMRead.y = GETLEs16(&sgpuData[3])&iGPUHeightMask; VRAMRead.Width = GETLEs16(&sgpuData[4]); VRAMRead.Height = GETLEs16(&sgpuData[5]); VRAMRead.ImagePtr = psxVuw + (VRAMRead.y<<10) + VRAMRead.x; VRAMRead.RowsRemaining = VRAMRead.Width; VRAMRead.ColsRemaining = VRAMRead.Height; DataReadMode = DR_VRAMTRANSFER; lGPUstatusRet |= GPUSTATUS_READYFORVRAM; } //////////////////////////////////////////////////////////////////////// // cmd: blkfill - NO primitive! Doesn't care about draw areas... //////////////////////////////////////////////////////////////////////// void primBlkFill(unsigned char * baseAddr) { uint32_t *gpuData = ((uint32_t *) baseAddr); short *sgpuData = ((short *) baseAddr); short sX = GETLEs16(&sgpuData[2]); short sY = GETLEs16(&sgpuData[3]); short sW = GETLEs16(&sgpuData[4]) & 0x3ff; short sH = GETLEs16(&sgpuData[5]) & 0x3ff; sW = (sW+15) & ~15; // Increase H & W if they are one short of full values, because they never can be full values if (sH >= 1023) sH=1024; if (sW >= 1023) sW=1024; // x and y of end pos sW+=sX; sH+=sY; FillSoftwareArea(sX, sY, sW, sH, BGR24to16(GETLE32(&gpuData[0]))); bDoVSyncUpdate=TRUE; } //////////////////////////////////////////////////////////////////////// // cmd: move image vram -> vram //////////////////////////////////////////////////////////////////////// void primMoveImage(unsigned char * baseAddr) { short *sgpuData = ((short *) baseAddr); short imageY0,imageX0,imageY1,imageX1,imageSX,imageSY,i,j; imageX0 = GETLEs16(&sgpuData[2])&0x03ff; imageY0 = GETLEs16(&sgpuData[3])&iGPUHeightMask; imageX1 = GETLEs16(&sgpuData[4])&0x03ff; imageY1 = GETLEs16(&sgpuData[5])&iGPUHeightMask; imageSX = GETLEs16(&sgpuData[6]); imageSY = GETLEs16(&sgpuData[7]); if((imageX0 == imageX1) && (imageY0 == imageY1)) return; if(imageSX<=0) return; if(imageSY<=0) return; // ZN SF2: screwed moves // // move sgpuData[2],sgpuData[3],sgpuData[4],sgpuData[5],sgpuData[6],sgpuData[7] // // move 365 182 32723 -21846 17219 15427 // move 127 160 147 -1 20817 13409 // move 141 165 16275 -21862 -32126 13442 // move 161 136 24620 -1 16962 13388 // move 168 138 32556 -13090 -29556 15500 // // and here's the hack for it: if(iGPUHeight==1024 && GETLEs16(&sgpuData[7])>1024) return; if((imageY0+imageSY)>iGPUHeight || (imageX0+imageSX)>1024 || (imageY1+imageSY)>iGPUHeight || (imageX1+imageSX)>1024) { int i,j; for(j=0;j>1; SRCPtr = (uint32_t *)(psxVuw + (1024*imageY0) + imageX0); DSTPtr = (uint32_t *)(psxVuw + (1024*imageY1) + imageX1); LineOffset = 512 - dx; for(j=0;j=PSXDisplay.DisplayPosition.x && imageY1=PSXDisplay.DisplayPosition.y) updateDisplay(); } */ bDoVSyncUpdate=TRUE; } //////////////////////////////////////////////////////////////////////// // cmd: draw free-size Tile //////////////////////////////////////////////////////////////////////// //#define SMALLDEBUG //#include void primTileS(unsigned char * baseAddr) { uint32_t *gpuData = ((uint32_t*)baseAddr); short *sgpuData = ((short *) baseAddr); short sW = GETLEs16(&sgpuData[4]) & 0x3ff; short sH = GETLEs16(&sgpuData[5]) & iGPUHeightMask; // mmm... limit tiles to 0x1ff or height? lx0 = GETLEs16(&sgpuData[2]); ly0 = GETLEs16(&sgpuData[3]); if(!(dwActFixes&8)) AdjustCoord1(); // x and y of start ly2 = ly3 = ly0+sH +PSXDisplay.DrawOffset.y; ly0 = ly1 = ly0 +PSXDisplay.DrawOffset.y; lx1 = lx2 = lx0+sW +PSXDisplay.DrawOffset.x; lx0 = lx3 = lx0 +PSXDisplay.DrawOffset.x; DrawSemiTrans = (SEMITRANSBIT(GETLE32(&gpuData[0]))) ? TRUE : FALSE; if(!(iTileCheat && sH==32 && GETLE32(&gpuData[0])==0x60ffffff)) // special cheat for certain ZiNc games FillSoftwareAreaTrans(lx0,ly0,lx2,ly2, BGR24to16(GETLE32(&gpuData[0]))); bDoVSyncUpdate=TRUE; } //////////////////////////////////////////////////////////////////////// // cmd: draw 1 dot Tile (point) //////////////////////////////////////////////////////////////////////// void primTile1(unsigned char * baseAddr) { uint32_t *gpuData = ((uint32_t*)baseAddr); short *sgpuData = ((short *) baseAddr); short sH = 1; short sW = 1; lx0 = GETLEs16(&sgpuData[2]); ly0 = GETLEs16(&sgpuData[3]); if(!(dwActFixes&8)) AdjustCoord1(); // x and y of start ly2 = ly3 = ly0+sH +PSXDisplay.DrawOffset.y; ly0 = ly1 = ly0 +PSXDisplay.DrawOffset.y; lx1 = lx2 = lx0+sW +PSXDisplay.DrawOffset.x; lx0 = lx3 = lx0 +PSXDisplay.DrawOffset.x; DrawSemiTrans = (SEMITRANSBIT(GETLE32(&gpuData[0]))) ? TRUE : FALSE; FillSoftwareAreaTrans(lx0,ly0,lx2,ly2, BGR24to16(GETLE32(&gpuData[0]))); // Takes Start and Offset bDoVSyncUpdate=TRUE; } //////////////////////////////////////////////////////////////////////// // cmd: draw 8 dot Tile (small rect) //////////////////////////////////////////////////////////////////////// void primTile8(unsigned char * baseAddr) { uint32_t *gpuData = ((uint32_t*)baseAddr); short *sgpuData = ((short *) baseAddr); short sH = 8; short sW = 8; lx0 = GETLEs16(&sgpuData[2]); ly0 = GETLEs16(&sgpuData[3]); if(!(dwActFixes&8)) AdjustCoord1(); // x and y of start ly2 = ly3 = ly0+sH +PSXDisplay.DrawOffset.y; ly0 = ly1 = ly0 +PSXDisplay.DrawOffset.y; lx1 = lx2 = lx0+sW +PSXDisplay.DrawOffset.x; lx0 = lx3 = lx0 +PSXDisplay.DrawOffset.x; DrawSemiTrans = (SEMITRANSBIT(GETLE32(&gpuData[0]))) ? TRUE : FALSE; FillSoftwareAreaTrans(lx0,ly0,lx2,ly2, BGR24to16(GETLE32(&gpuData[0]))); // Takes Start and Offset bDoVSyncUpdate=TRUE; } //////////////////////////////////////////////////////////////////////// // cmd: draw 16 dot Tile (medium rect) //////////////////////////////////////////////////////////////////////// void primTile16(unsigned char * baseAddr) { uint32_t *gpuData = ((uint32_t*)baseAddr); short *sgpuData = ((short *) baseAddr); short sH = 16; short sW = 16; lx0 = GETLEs16(&sgpuData[2]); ly0 = GETLEs16(&sgpuData[3]); if(!(dwActFixes&8)) AdjustCoord1(); // x and y of start ly2 = ly3 = ly0+sH +PSXDisplay.DrawOffset.y; ly0 = ly1 = ly0 +PSXDisplay.DrawOffset.y; lx1 = lx2 = lx0+sW +PSXDisplay.DrawOffset.x; lx0 = lx3 = lx0 +PSXDisplay.DrawOffset.x; DrawSemiTrans = (SEMITRANSBIT(GETLE32(&gpuData[0]))) ? TRUE : FALSE; FillSoftwareAreaTrans(lx0,ly0,lx2,ly2, BGR24to16(GETLE32(&gpuData[0]))); // Takes Start and Offset bDoVSyncUpdate=TRUE; } //////////////////////////////////////////////////////////////////////// // cmd: small sprite (textured rect) //////////////////////////////////////////////////////////////////////// void primSprt8(unsigned char * baseAddr) { uint32_t *gpuData = ((uint32_t *) baseAddr); short *sgpuData = ((short *) baseAddr); lx0 = GETLEs16(&sgpuData[2]); ly0 = GETLEs16(&sgpuData[3]); if(!(dwActFixes&8)) AdjustCoord1(); SetRenderMode(GETLE32(&gpuData[0])); if(bUsingTWin) DrawSoftwareSpriteTWin(baseAddr,8,8); else if(usMirror) DrawSoftwareSpriteMirror(baseAddr,8,8); else DrawSoftwareSprite(baseAddr,8,8, baseAddr[8], baseAddr[9]); bDoVSyncUpdate=TRUE; } //////////////////////////////////////////////////////////////////////// // cmd: medium sprite (textured rect) //////////////////////////////////////////////////////////////////////// void primSprt16(unsigned char * baseAddr) { uint32_t *gpuData = ((uint32_t *) baseAddr); short *sgpuData = ((short *) baseAddr); lx0 = GETLEs16(&sgpuData[2]); ly0 = GETLEs16(&sgpuData[3]); if(!(dwActFixes&8)) AdjustCoord1(); SetRenderMode(GETLE32(&gpuData[0])); if(bUsingTWin) DrawSoftwareSpriteTWin(baseAddr,16,16); else if(usMirror) DrawSoftwareSpriteMirror(baseAddr,16,16); else DrawSoftwareSprite(baseAddr,16,16, baseAddr[8], baseAddr[9]); bDoVSyncUpdate=TRUE; } //////////////////////////////////////////////////////////////////////// // cmd: free-size sprite (textured rect) //////////////////////////////////////////////////////////////////////// // func used on texture coord wrap void primSprtSRest(unsigned char * baseAddr,unsigned short type) { uint32_t *gpuData = ((uint32_t *) baseAddr); short *sgpuData = ((short *) baseAddr); unsigned short sTypeRest=0; short s; short sX = GETLEs16(&sgpuData[2]); short sY = GETLEs16(&sgpuData[3]); short sW = GETLEs16(&sgpuData[6]) & 0x3ff; short sH = GETLEs16(&sgpuData[7]) & 0x1ff; short tX = baseAddr[8]; short tY = baseAddr[9]; switch(type) { case 1: s=256-baseAddr[8]; sW-=s; sX+=s; tX=0; break; case 2: s=256-baseAddr[9]; sH-=s; sY+=s; tY=0; break; case 3: s=256-baseAddr[8]; sW-=s; sX+=s; tX=0; s=256-baseAddr[9]; sH-=s; sY+=s; tY=0; break; case 4: s=512-baseAddr[8]; sW-=s; sX+=s; tX=0; break; case 5: s=512-baseAddr[9]; sH-=s; sY+=s; tY=0; break; case 6: s=512-baseAddr[8]; sW-=s; sX+=s; tX=0; s=512-baseAddr[9]; sH-=s; sY+=s; tY=0; break; } SetRenderMode(GETLE32(&gpuData[0])); if(tX+sW>256) {sW=256-tX;sTypeRest+=1;} if(tY+sH>256) {sH=256-tY;sTypeRest+=2;} lx0 = sX; ly0 = sY; if(!(dwActFixes&8)) AdjustCoord1(); DrawSoftwareSprite(baseAddr,sW,sH,tX,tY); if(sTypeRest && type<4) { if(sTypeRest&1 && type==1) primSprtSRest(baseAddr,4); if(sTypeRest&2 && type==2) primSprtSRest(baseAddr,5); if(sTypeRest==3 && type==3) primSprtSRest(baseAddr,6); } } //////////////////////////////////////////////////////////////////////// void primSprtS(unsigned char * baseAddr) { uint32_t *gpuData = ((uint32_t *) baseAddr); short *sgpuData = ((short *) baseAddr); short sW,sH; lx0 = GETLEs16(&sgpuData[2]); ly0 = GETLEs16(&sgpuData[3]); if(!(dwActFixes&8)) AdjustCoord1(); sW = GETLEs16(&sgpuData[6]) & 0x3ff; sH = GETLEs16(&sgpuData[7]) & 0x1ff; SetRenderMode(GETLE32(&gpuData[0])); if(bUsingTWin) DrawSoftwareSpriteTWin(baseAddr,sW,sH); else if(usMirror) DrawSoftwareSpriteMirror(baseAddr,sW,sH); else { unsigned short sTypeRest=0; short tX=baseAddr[8]; short tY=baseAddr[9]; if(tX+sW>256) {sW=256-tX;sTypeRest+=1;} if(tY+sH>256) {sH=256-tY;sTypeRest+=2;} DrawSoftwareSprite(baseAddr,sW,sH,tX,tY); if(sTypeRest) { if(sTypeRest&1) primSprtSRest(baseAddr,1); if(sTypeRest&2) primSprtSRest(baseAddr,2); if(sTypeRest==3) primSprtSRest(baseAddr,3); } } bDoVSyncUpdate=TRUE; } //////////////////////////////////////////////////////////////////////// // cmd: flat shaded Poly4 //////////////////////////////////////////////////////////////////////// void primPolyF4(unsigned char *baseAddr) { uint32_t *gpuData = ((uint32_t *) baseAddr); short *sgpuData = ((short *) baseAddr); lx0 = GETLEs16(&sgpuData[2]); ly0 = GETLEs16(&sgpuData[3]); lx1 = GETLEs16(&sgpuData[4]); ly1 = GETLEs16(&sgpuData[5]); lx2 = GETLEs16(&sgpuData[6]); ly2 = GETLEs16(&sgpuData[7]); lx3 = GETLEs16(&sgpuData[8]); ly3 = GETLEs16(&sgpuData[9]); if(!(dwActFixes&8)) { AdjustCoord4(); if(CheckCoord4()) return; } offsetPSX4(); DrawSemiTrans = (SEMITRANSBIT(GETLE32(&gpuData[0]))) ? TRUE : FALSE; drawPoly4F(GETLE32(&gpuData[0])); bDoVSyncUpdate=TRUE; } //////////////////////////////////////////////////////////////////////// // cmd: smooth shaded Poly4 //////////////////////////////////////////////////////////////////////// void primPolyG4(unsigned char * baseAddr) { uint32_t *gpuData = (uint32_t *)baseAddr; short *sgpuData = ((short *) baseAddr); lx0 = GETLEs16(&sgpuData[2]); ly0 = GETLEs16(&sgpuData[3]); lx1 = GETLEs16(&sgpuData[6]); ly1 = GETLEs16(&sgpuData[7]); lx2 = GETLEs16(&sgpuData[10]); ly2 = GETLEs16(&sgpuData[11]); lx3 = GETLEs16(&sgpuData[14]); ly3 = GETLEs16(&sgpuData[15]); if(!(dwActFixes&8)) { AdjustCoord4(); if(CheckCoord4()) return; } offsetPSX4(); DrawSemiTrans = (SEMITRANSBIT(GETLE32(&gpuData[0]))) ? TRUE : FALSE; drawPoly4G(GETLE32(&gpuData[0]), GETLE32(&gpuData[2]), GETLE32(&gpuData[4]), GETLE32(&gpuData[6])); bDoVSyncUpdate=TRUE; } //////////////////////////////////////////////////////////////////////// // cmd: flat shaded Texture3 //////////////////////////////////////////////////////////////////////// void primPolyFT3(unsigned char * baseAddr) { uint32_t *gpuData = ((uint32_t *) baseAddr); short *sgpuData = ((short *) baseAddr); lx0 = GETLEs16(&sgpuData[2]); ly0 = GETLEs16(&sgpuData[3]); lx1 = GETLEs16(&sgpuData[6]); ly1 = GETLEs16(&sgpuData[7]); lx2 = GETLEs16(&sgpuData[10]); ly2 = GETLEs16(&sgpuData[11]); lLowerpart=GETLE32(&gpuData[4])>>16; UpdateGlobalTP((unsigned short)lLowerpart); if(!(dwActFixes&8)) { AdjustCoord3(); if(CheckCoord3()) return; } offsetPSX3(); SetRenderMode(GETLE32(&gpuData[0])); drawPoly3FT(baseAddr); bDoVSyncUpdate=TRUE; } //////////////////////////////////////////////////////////////////////// // cmd: flat shaded Texture4 //////////////////////////////////////////////////////////////////////// void primPolyFT4(unsigned char * baseAddr) { uint32_t *gpuData = ((uint32_t *) baseAddr); short *sgpuData = ((short *) baseAddr); lx0 = GETLEs16(&sgpuData[2]); ly0 = GETLEs16(&sgpuData[3]); lx1 = GETLEs16(&sgpuData[6]); ly1 = GETLEs16(&sgpuData[7]); lx2 = GETLEs16(&sgpuData[10]); ly2 = GETLEs16(&sgpuData[11]); lx3 = GETLEs16(&sgpuData[14]); ly3 = GETLEs16(&sgpuData[15]); lLowerpart=GETLE32(&gpuData[4])>>16; UpdateGlobalTP((unsigned short)lLowerpart); if(!(dwActFixes&8)) { AdjustCoord4(); if(CheckCoord4()) return; } offsetPSX4(); SetRenderMode(GETLE32(&gpuData[0])); drawPoly4FT(baseAddr); bDoVSyncUpdate=TRUE; } //////////////////////////////////////////////////////////////////////// // cmd: smooth shaded Texture3 //////////////////////////////////////////////////////////////////////// void primPolyGT3(unsigned char *baseAddr) { uint32_t *gpuData = ((uint32_t *) baseAddr); short *sgpuData = ((short *) baseAddr); lx0 = GETLEs16(&sgpuData[2]); ly0 = GETLEs16(&sgpuData[3]); lx1 = GETLEs16(&sgpuData[8]); ly1 = GETLEs16(&sgpuData[9]); lx2 = GETLEs16(&sgpuData[14]); ly2 = GETLEs16(&sgpuData[15]); lLowerpart=GETLE32(&gpuData[5])>>16; UpdateGlobalTP((unsigned short)lLowerpart); if(!(dwActFixes&8)) { AdjustCoord3(); if(CheckCoord3()) return; } offsetPSX3(); DrawSemiTrans = (SEMITRANSBIT(GETLE32(&gpuData[0]))) ? TRUE : FALSE; if(SHADETEXBIT(GETLE32(&gpuData[0]))) { gpuData[0] = (gpuData[0]&HOST2LE32(0xff000000))|HOST2LE32(0x00808080); gpuData[3] = (gpuData[3]&HOST2LE32(0xff000000))|HOST2LE32(0x00808080); gpuData[6] = (gpuData[6]&HOST2LE32(0xff000000))|HOST2LE32(0x00808080); } drawPoly3GT(baseAddr); bDoVSyncUpdate=TRUE; } //////////////////////////////////////////////////////////////////////// // cmd: smooth shaded Poly3 //////////////////////////////////////////////////////////////////////// void primPolyG3(unsigned char *baseAddr) { uint32_t *gpuData = ((uint32_t *) baseAddr); short *sgpuData = ((short *) baseAddr); lx0 = GETLEs16(&sgpuData[2]); ly0 = GETLEs16(&sgpuData[3]); lx1 = GETLEs16(&sgpuData[6]); ly1 = GETLEs16(&sgpuData[7]); lx2 = GETLEs16(&sgpuData[10]); ly2 = GETLEs16(&sgpuData[11]); if(!(dwActFixes&8)) { AdjustCoord3(); if(CheckCoord3()) return; } offsetPSX3(); DrawSemiTrans = (SEMITRANSBIT(GETLE32(&gpuData[0]))) ? TRUE : FALSE; drawPoly3G(GETLE32(&gpuData[0]), GETLE32(&gpuData[2]), GETLE32(&gpuData[4])); bDoVSyncUpdate=TRUE; } //////////////////////////////////////////////////////////////////////// // cmd: smooth shaded Texture4 //////////////////////////////////////////////////////////////////////// void primPolyGT4(unsigned char *baseAddr) { uint32_t *gpuData = ((uint32_t *) baseAddr); short *sgpuData = ((short *) baseAddr); lx0 = GETLEs16(&sgpuData[2]); ly0 = GETLEs16(&sgpuData[3]); lx1 = GETLEs16(&sgpuData[8]); ly1 = GETLEs16(&sgpuData[9]); lx2 = GETLEs16(&sgpuData[14]); ly2 = GETLEs16(&sgpuData[15]); lx3 = GETLEs16(&sgpuData[20]); ly3 = GETLEs16(&sgpuData[21]); lLowerpart=GETLE32(&gpuData[5])>>16; UpdateGlobalTP((unsigned short)lLowerpart); if(!(dwActFixes&8)) { AdjustCoord4(); if(CheckCoord4()) return; } offsetPSX4(); DrawSemiTrans = (SEMITRANSBIT(GETLE32(&gpuData[0]))) ? TRUE : FALSE; if(SHADETEXBIT(GETLE32(&gpuData[0]))) { gpuData[0] = (gpuData[0]&HOST2LE32(0xff000000))|HOST2LE32(0x00808080); gpuData[3] = (gpuData[3]&HOST2LE32(0xff000000))|HOST2LE32(0x00808080); gpuData[6] = (gpuData[6]&HOST2LE32(0xff000000))|HOST2LE32(0x00808080); gpuData[9] = (gpuData[9]&HOST2LE32(0xff000000))|HOST2LE32(0x00808080); } drawPoly4GT(baseAddr); bDoVSyncUpdate=TRUE; } //////////////////////////////////////////////////////////////////////// // cmd: smooth shaded Poly3 //////////////////////////////////////////////////////////////////////// void primPolyF3(unsigned char *baseAddr) { uint32_t *gpuData = ((uint32_t *) baseAddr); short *sgpuData = ((short *) baseAddr); lx0 = GETLEs16(&sgpuData[2]); ly0 = GETLEs16(&sgpuData[3]); lx1 = GETLEs16(&sgpuData[4]); ly1 = GETLEs16(&sgpuData[5]); lx2 = GETLEs16(&sgpuData[6]); ly2 = GETLEs16(&sgpuData[7]); if(!(dwActFixes&8)) { AdjustCoord3(); if(CheckCoord3()) return; } offsetPSX3(); SetRenderMode(GETLE32(&gpuData[0])); drawPoly3F(GETLE32(&gpuData[0])); bDoVSyncUpdate=TRUE; } //////////////////////////////////////////////////////////////////////// // cmd: skipping shaded polylines //////////////////////////////////////////////////////////////////////// void primLineGSkip(unsigned char *baseAddr) { uint32_t *gpuData = ((uint32_t *) baseAddr); int iMax=255; int i=2; ly1 = (short)((GETLE32(&gpuData[1])>>16) & 0xffff); lx1 = (short)(GETLE32(&gpuData[1]) & 0xffff); while(!(((GETLE32(&gpuData[i]) & 0xF000F000) == 0x50005000) && i>=4)) { i++; ly1 = (short)((GETLE32(&gpuData[i])>>16) & 0xffff); lx1 = (short)(GETLE32(&gpuData[i]) & 0xffff); i++;if(i>iMax) break; } } //////////////////////////////////////////////////////////////////////// // cmd: shaded polylines //////////////////////////////////////////////////////////////////////// void primLineGEx(unsigned char *baseAddr) { uint32_t *gpuData = ((uint32_t *) baseAddr); int iMax=255; uint32_t lc0,lc1; short slx0,slx1,sly0,sly1;int i=2;BOOL bDraw=TRUE; sly1 = (short)((GETLE32(&gpuData[1])>>16) & 0xffff); slx1 = (short)(GETLE32(&gpuData[1]) & 0xffff); if(!(dwActFixes&8)) { slx1=(short)(((int)slx1<>SIGNSHIFT); sly1=(short)(((int)sly1<>SIGNSHIFT); } lc1 = gpuData[0] & 0xffffff; DrawSemiTrans = (SEMITRANSBIT(GETLE32(&gpuData[0]))) ? TRUE : FALSE; while(!(((GETLE32(&gpuData[i]) & 0xF000F000) == 0x50005000) && i>=4)) { sly0=sly1; slx0=slx1; lc0=lc1; lc1=GETLE32(&gpuData[i]) & 0xffffff; i++; // no check needed on gshaded polyline positions // if((gpuData[i] & 0xF000F000) == 0x50005000) break; sly1 = (short)((GETLE32(&gpuData[i])>>16) & 0xffff); slx1 = (short)(GETLE32(&gpuData[i]) & 0xffff); if(!(dwActFixes&8)) { slx1=(short)(((int)slx1<>SIGNSHIFT); sly1=(short)(((int)sly1<>SIGNSHIFT); if(CheckCoordL(slx0,sly0,slx1,sly1)) bDraw=FALSE; else bDraw=TRUE; } if ((lx0 != lx1) || (ly0 != ly1)) { ly0=sly0; lx0=slx0; ly1=sly1; lx1=slx1; offsetPSX2(); if(bDraw) DrawSoftwareLineShade(lc0, lc1); } i++; if(i>iMax) break; } bDoVSyncUpdate=TRUE; } //////////////////////////////////////////////////////////////////////// // cmd: shaded polyline2 //////////////////////////////////////////////////////////////////////// void primLineG2(unsigned char *baseAddr) { uint32_t *gpuData = ((uint32_t *) baseAddr); short *sgpuData = ((short *) baseAddr); lx0 = GETLEs16(&sgpuData[2]); ly0 = GETLEs16(&sgpuData[3]); lx1 = GETLEs16(&sgpuData[6]); ly1 = GETLEs16(&sgpuData[7]); if(!(dwActFixes&8)) { AdjustCoord2(); if(CheckCoord2()) return; } if((lx0 == lx1) && (ly0 == ly1)) {lx1++;ly1++;} DrawSemiTrans = (SEMITRANSBIT(GETLE32(&gpuData[0]))) ? TRUE : FALSE; offsetPSX2(); DrawSoftwareLineShade(GETLE32(&gpuData[0]),GETLE32(&gpuData[2])); bDoVSyncUpdate=TRUE; } //////////////////////////////////////////////////////////////////////// // cmd: skipping flat polylines //////////////////////////////////////////////////////////////////////// void primLineFSkip(unsigned char *baseAddr) { uint32_t *gpuData = ((uint32_t *) baseAddr); int i=2,iMax=255; ly1 = (short)((GETLE32(&gpuData[1])>>16) & 0xffff); lx1 = (short)(GETLE32(&gpuData[1]) & 0xffff); while(!(((GETLE32(&gpuData[i]) & 0xF000F000) == 0x50005000) && i>=3)) { ly1 = (short)((GETLE32(&gpuData[i])>>16) & 0xffff); lx1 = (short)(GETLE32(&gpuData[i]) & 0xffff); i++;if(i>iMax) break; } } //////////////////////////////////////////////////////////////////////// // cmd: drawing flat polylines //////////////////////////////////////////////////////////////////////// void primLineFEx(unsigned char *baseAddr) { uint32_t *gpuData = ((uint32_t *) baseAddr); int iMax; short slx0,slx1,sly0,sly1;int i=2;BOOL bDraw=TRUE; iMax=255; sly1 = (short)((GETLE32(&gpuData[1])>>16) & 0xffff); slx1 = (short)(GETLE32(&gpuData[1]) & 0xffff); if(!(dwActFixes&8)) { slx1=(short)(((int)slx1<>SIGNSHIFT); sly1=(short)(((int)sly1<>SIGNSHIFT); } SetRenderMode(GETLE32(&gpuData[0])); while(!(((GETLE32(&gpuData[i]) & 0xF000F000) == 0x50005000) && i>=3)) { sly0 = sly1;slx0=slx1; sly1 = (short)((GETLE32(&gpuData[i])>>16) & 0xffff); slx1 = (short)(GETLE32(&gpuData[i]) & 0xffff); if(!(dwActFixes&8)) { slx1=(short)(((int)slx1<>SIGNSHIFT); sly1=(short)(((int)sly1<>SIGNSHIFT); if(CheckCoordL(slx0,sly0,slx1,sly1)) bDraw=FALSE; else bDraw=TRUE; } ly0=sly0; lx0=slx0; ly1=sly1; lx1=slx1; offsetPSX2(); if(bDraw) DrawSoftwareLineFlat(GETLE32(&gpuData[0])); i++;if(i>iMax) break; } bDoVSyncUpdate=TRUE; } //////////////////////////////////////////////////////////////////////// // cmd: drawing flat polyline2 //////////////////////////////////////////////////////////////////////// void primLineF2(unsigned char *baseAddr) { uint32_t *gpuData = ((uint32_t *) baseAddr); short *sgpuData = ((short *) baseAddr); lx0 = GETLEs16(&sgpuData[2]); ly0 = GETLEs16(&sgpuData[3]); lx1 = GETLEs16(&sgpuData[4]); ly1 = GETLEs16(&sgpuData[5]); if(!(dwActFixes&8)) { AdjustCoord2(); if(CheckCoord2()) return; } if((lx0 == lx1) && (ly0 == ly1)) {lx1++;ly1++;} offsetPSX2(); SetRenderMode(GETLE32(&gpuData[0])); DrawSoftwareLineFlat(GETLE32(&gpuData[0])); bDoVSyncUpdate=TRUE; } //////////////////////////////////////////////////////////////////////// // cmd: well, easiest command... not implemented //////////////////////////////////////////////////////////////////////// void primNI(unsigned char *bA) { } //////////////////////////////////////////////////////////////////////// // cmd func ptr table //////////////////////////////////////////////////////////////////////// void (*primTableJ[256])(unsigned char *) = { // 00 primNI,primNI,primBlkFill,primNI,primNI,primNI,primNI,primNI, // 08 primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, // 10 primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, // 18 primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, // 20 primPolyF3,primPolyF3,primPolyF3,primPolyF3,primPolyFT3,primPolyFT3,primPolyFT3,primPolyFT3, // 28 primPolyF4,primPolyF4,primPolyF4,primPolyF4,primPolyFT4,primPolyFT4,primPolyFT4,primPolyFT4, // 30 primPolyG3,primPolyG3,primPolyG3,primPolyG3,primPolyGT3,primPolyGT3,primPolyGT3,primPolyGT3, // 38 primPolyG4,primPolyG4,primPolyG4,primPolyG4,primPolyGT4,primPolyGT4,primPolyGT4,primPolyGT4, // 40 primLineF2,primLineF2,primLineF2,primLineF2,primNI,primNI,primNI,primNI, // 48 primLineFEx,primLineFEx,primLineFEx,primLineFEx,primLineFEx,primLineFEx,primLineFEx,primLineFEx, // 50 primLineG2,primLineG2,primLineG2,primLineG2,primNI,primNI,primNI,primNI, // 58 primLineGEx,primLineGEx,primLineGEx,primLineGEx,primLineGEx,primLineGEx,primLineGEx,primLineGEx, // 60 primTileS,primTileS,primTileS,primTileS,primSprtS,primSprtS,primSprtS,primSprtS, // 68 primTile1,primTile1,primTile1,primTile1,primNI,primNI,primNI,primNI, // 70 primTile8,primTile8,primTile8,primTile8,primSprt8,primSprt8,primSprt8,primSprt8, // 78 primTile16,primTile16,primTile16,primTile16,primSprt16,primSprt16,primSprt16,primSprt16, // 80 primMoveImage,primNI,primNI,primNI,primNI,primNI,primNI,primNI, // 88 primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, // 90 primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, // 98 primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, // a0 primLoadImage,primNI,primNI,primNI,primNI,primNI,primNI,primNI, // a8 primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, // b0 primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, // b8 primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, // c0 primStoreImage,primNI,primNI,primNI,primNI,primNI,primNI,primNI, // c8 primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, // d0 primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, // d8 primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, // e0 primNI,cmdTexturePage,cmdTextureWindow,cmdDrawAreaStart,cmdDrawAreaEnd,cmdDrawOffset,cmdSTP,primNI, // e8 primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, // f0 primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, // f8 primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI }; //////////////////////////////////////////////////////////////////////// // cmd func ptr table for skipping //////////////////////////////////////////////////////////////////////// void (*primTableSkip[256])(unsigned char *) = { // 00 primNI,primNI,primBlkFill,primNI,primNI,primNI,primNI,primNI, // 08 primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, // 10 primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, // 18 primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, // 20 primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, // 28 primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, // 30 primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, // 38 primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, // 40 primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, // 48 primLineFSkip,primLineFSkip,primLineFSkip,primLineFSkip,primLineFSkip,primLineFSkip,primLineFSkip,primLineFSkip, // 50 primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, // 58 primLineGSkip,primLineGSkip,primLineGSkip,primLineGSkip,primLineGSkip,primLineGSkip,primLineGSkip,primLineGSkip, // 60 primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, // 68 primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, // 70 primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, // 78 primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, // 80 primMoveImage,primNI,primNI,primNI,primNI,primNI,primNI,primNI, // 88 primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, // 90 primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, // 98 primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, // a0 primLoadImage,primNI,primNI,primNI,primNI,primNI,primNI,primNI, // a8 primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, // b0 primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, // b8 primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, // c0 primStoreImage,primNI,primNI,primNI,primNI,primNI,primNI,primNI, // c8 primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, // d0 primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, // d8 primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, // e0 primNI,cmdTexturePage,cmdTextureWindow,cmdDrawAreaStart,cmdDrawAreaEnd,cmdDrawOffset,cmdSTP,primNI, // e8 primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, // f0 primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI, // f8 primNI,primNI,primNI,primNI,primNI,primNI,primNI,primNI };