www.pudn.com > potemkin_sourceforPSP.rar > DSFifo.cpp
#include "stdafx.h" /* #include#include #include */ #include "../MemMap.h" #include "DSFifo.h" #include "DSGeom.h" inline int SEX10(int i) {return (i&0x200) ? (i|0xFFFFFC00) : (i&0x1ff);} #define DS_FIFO_SIZE 4096 u32 fifo[DS_FIFO_SIZE]; int fifopos; int readpos; typedef void (*FifoInstruction)(u32 *dataptr); inline float FF6(int x) { return (float)x * (1.0f/4096.0f); } inline float FF12(int x) { return (float)x * (1.0f/4096.0f); } inline float FF10(int x) { return (float)x * (1.0f/1024.0f); } inline float FF10s(int x) { return (float)x * (1.0f/512.0f); } inline float FF5(int x) { return (float)x * (1.0f/32.0f); } inline float FF5c(int x) { return (float)x * (1.0f/31.0f); } //FifoInstruction fifoTable union PolyAttr { u32 hex; struct { unsigned lightsMask : 4; unsigned polyMode : 2; unsigned bk : 1; unsigned fr : 1; unsigned unused : 3; unsigned translucentZWrite : 1; unsigned farClip : 1; // 1=clip or 0=kill unsigned oneDot : 1; //display if only 1 pixel? unsigned zEqual : 1; //zless or zequal unsigned fogEnable : 1; unsigned alpha : 5; unsigned id : 5; }; }; union TexImageParam { u32 hex; struct { unsigned texAddr : 16; unsigned repeat : 2; unsigned flip : 2; unsigned s_size : 3; unsigned t_size : 3; unsigned texfmt : 3; unsigned color0transparent : 1; unsigned tgen : 2; }; }; const GLuint Begin[4] = { GL_TRIANGLES, GL_QUADS, GL_TRIANGLE_STRIP, GL_QUAD_STRIP }; const GLuint CullMode[4] = { GL_FRONT_AND_BACK, GL_FRONT, GL_BACK, GL_FRONT, }; const GLboolean CullEnable[4] = { GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE }; const GLuint ClampUMode[4] = { GL_CLAMP, GL_REPEAT, GL_CLAMP, GL_REPEAT }; const GLuint ClampVMode[4] = { GL_CLAMP, GL_CLAMP, GL_REPEAT, GL_REPEAT }; enum PolyMode { PM_MODULATE, PM_DECAL, PM_TOON, PM_SHADOW }; enum TexGen { TG_NONE, TG_TEXCOORD, TG_NORMAL, TG_VERTEX, }; void DSFifoReset() { fifopos=0; readpos=0; } void DSWriteFifo(u32 word) { fifo[fifopos++] = word; } static float vpos[3]; void DSRunFifo() { while (readpos >5)&0x1f, b = (color>>10)&0x1f; LOG(G3D,"r: %i g: %i b: %i",r,g,b); glColor3f(FF5c(r),FF5c(g),FF5c(b)); } break; case 0x21: //NORMAL { u32 normal = fifo[readpos++]; float n[3] = {FF10s(SEX10(normal)), FF10s(SEX10(normal>>10)), FF10s(SEX10(normal>>20))}; //we have the power, why not normalize? float invlength = 1.0f/sqrtf(n[0]*n[0]+n[1]*n[1]+n[2]*n[2]); for (int i=0; i<3; i++) n[i]*=invlength; glNormal3fv(n); LOG(G3D,"nx: %f ny: %f nz: %f",n[0],n[1],n[2]); } break; case 0x22: //TEXCOORD { u32 tc = fifo[readpos++]; int u = (s32)(s16)(tc&0xffff), v = (s32)(s16)(tc>>16); glTexCoord2f(FF12(u),FF12(v)); LOG(G3D,"u: %i v: %i",u,v); } break; case 0x23: //VTX16 { u32 part1 = fifo[readpos++]; u32 part2 = fifo[readpos++]; vpos[0] = FF12((s32)(s16)(part1)); vpos[1] = FF12((s32)(s16)(part1>>16)); vpos[2] = FF12((s32)(s16)(part2)); //readpos++; glVertex3fv(vpos); LOG(G3D,"x: %f y: %f z: %f *16",vpos[0],vpos[1],vpos[2]); } break; case 0x24: //VTX10 { u32 vtx = fifo[readpos++]; vpos[0] = FF12(SEX10(vtx)<<6); vpos[1] = FF12(SEX10(vtx>>10)<<6); vpos[2] = FF12(SEX10(vtx>>20)<<6); glVertex3fv(vpos); LOG(G3D,"x: %f y: %f z: %f *10",vpos[0],vpos[1],vpos[2]); } break; case 0x25: //VTXXY { u32 value = fifo[readpos++]; vpos[0] = FF12((s32)(s16)(value)); vpos[1] = FF12((s32)(s16)(value>>16)); glVertex3fv(vpos); LOG(G3D,"x: %f y: %f z: %f *XY",vpos[0],vpos[1],vpos[2]); } break; case 0x26: //VTXXZ { u32 value = fifo[readpos++]; vpos[0] = FF12((s32)(s16)(value)); vpos[2] = FF12((s32)(s16)(value>>16)); glVertex3fv(vpos); LOG(G3D,"x: %f y: %f z: %f *XZ",vpos[0],vpos[1],vpos[2]); } break; case 0x27: //VTXYZ { u32 value = fifo[readpos++]; vpos[1] = FF12((s32)(s16)(value)); vpos[2] = FF12((s32)(s16)(value>>16)); glVertex3fv(vpos); LOG(G3D,"x: %f y: %f z: %f *YZ",vpos[0],vpos[1],vpos[2]); } break; case 0x28: //VTXDIFF { u32 value = fifo[readpos++]; float d[3] = {FF10s(SEX10(value)), FF10s(SEX10(value>>10)), FF10s(SEX10(value>>20))}; for (int i=0; i<3; i++) vpos[i]+=d[i]; glVertex3fv(vpos); LOG(G3D,"x: %f y: %f z: %f *DIFFED*",vpos[0],vpos[1],vpos[2]); } break; case 0x29: //POLYATTR { PolyAttr pa; pa.hex = fifo[readpos++]; for (int i=0; i<4; i++) (pa.lightsMask&(1<>5)&0x1f), FF5((value>>10)&0x1f), 1.0f }; GLfloat ambient[4] = { FF5((value>>16)&0x1f), FF5((value>>21)&0x1f), FF5((value>>26)&0x1f), 1.0f }; glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,diffuse); glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT,ambient); int c = (value>>15)&1; //also set current vertex color to diffuse? if (c) { glColor3f(diffuse[0],diffuse[1],diffuse[2]); } LOG(G3D,"Diff/ambi"); //LOG(G3D,"C%i: diffuse: r: %f g: %f b: %f ambient: r: %f g: %f b: %f",c,dr,dg,db,ar,ag,ab); } break; case 0x31: //SPE_EMI { u32 value=fifo[readpos++]; GLfloat specular[4] = { FF5(value&0x1f), FF5((value>>5)&0x1f), FF5((value>>10)&0x1f), 1.0f }; GLfloat emission[4] = { FF5((value>>16)&0x1f), FF5((value>>21)&0x1f), FF5((value>>26)&0x1f), 1.0f }; glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specular); glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, emission); int c = (value>>15)&1; //use specular table? if (c) { //do whatever.. } LOG(G3D,"Spec/emis"); //LOG(G3D,"C%i: specular: r: %f g: %f b: %f emissive: r: %i g: %i b: %i",c,sr,sg,sb,er,eg,eb); } break; case 0x32: //LIGHT_VECTOR { u32 light=fifo[readpos++]; GLenum lightNum = light>>30; GLfloat d[4] = { FF10(SEX10(light)), FF10(SEX10(light>>10)), FF10(SEX10(light>>20)), 0.0f }; glLightfv(lightNum, GL_POSITION, d); LOG(G3D,"Light %i: x: %f y: %f z: %f",lightNum,d[0],d[1],d[2]); } break; case 0x33: //LIGHT_COLOR { u32 color=fifo[readpos++]; GLenum lightNum = color>>30; GLfloat c[4] = { FF5(color&0x1f), FF5((color>>5)&0x1f), FF5((color>>10)&0x1f), 1.0f }; glLightfv(lightNum, GL_DIFFUSE, c); LOG(G3D,"Light %i: r: %f g: %f b: %f",lightNum,c[0],c[1],c[2]); } break; case 0x34: //LIGHT_SHININESS { //for (int i=0; i<32; i++) readpos+=32; LOG(G3D,"Shininess table set"); } break; case 0x40: //BEGIN { //if textureChanged u32 params=fifo[readpos++]; glBegin(Begin[params&3]); //&3 for safety LOG(G3D,"Begin %i",params); } break; case 0x41: //END { glEnd(); LOG(G3D,"End"); } break; case 0x50: //SWAPBUFFERS { u32 difamb=fifo[readpos++]; } break; case 0x60: //VIEWPORT { u32 viewport=fifo[readpos++]; int x1=viewport&0xFF; int y1=(viewport>>8)&0xFF; int x2=(viewport>>16)&0xFF; int y2=(viewport>>24)&0xFF; //glViewport(x1,y1,x2-x1,y2-y1); // TODO fixup } break; //tests case 0x70: { u32 box1=fifo[readpos++]; u32 box2=fifo[readpos++]; u32 box3=fifo[readpos++]; // } break; case 0x71: { u32 pos1=fifo[readpos++]; u32 pos2=fifo[readpos++]; } break; case 0x72: { u32 vec=fifo[readpos++]; } break; default: LOG(G3D,"Illegal FIFO command %i (0x%08x)",cmd,cmd); break; } } }