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; 
		} 
	} 
}