5 #include "OpcodeDecoding.h"
6 #include "VertexLoader.h"
7 #include "VertexHandler.h"
8 #include "DataReader.h"
10 #include "CPStructs.h"
11 #include "XFStructs.h"
12 #include "DLCompiler.h"
17 CompiledDList::CompiledDList(u32 _addr
, u32 _size
)
29 CompiledDList::~CompiledDList()
40 bool CompiledDList::Call()
43 case 0: // First compiling pass : find data size
51 case 1: // Second compiling pass : actually compile
52 //if pass1 succeeded, pass2 will too
56 case 2: // Run pass - we have a compiled dlist, just call it
66 bool CompiledDList::Pass1()
68 /* //find the size of code + data, if the dlist is worth recompiling etc
69 // at the same time, do the ordinary stuff
70 g_pDataReader = &dlistReader;
71 OpcodeReaders::SetDListReader(addr, addr+size);
75 bool lastIsPrim = false;
76 while (OpcodeReaders::IsDListOKToRead())
78 int Cmd = g_pDataReader->Read8();
81 case GX_LOAD_CP_REG: //0x08
83 u32 SubCmd = g_pDataReader->Read8();
84 u32 Value = g_pDataReader->Read32();
85 LoadCPReg(SubCmd,Value);
93 u32 Cmd2 = g_pDataReader->Read32();
94 int dwTransferSize = ((Cmd2>>16)&15) + 1;
95 DWORD dwAddress = Cmd2 & 0xFFFF;
97 for (int i=0; i<dwTransferSize; i++)
98 pData[i] = g_pDataReader->Read32();
99 LoadXFReg(dwTransferSize,dwAddress,pData);
101 dataSize+=dwTransferSize;
106 case GX_LOAD_BP_REG: //0x61
108 u32 cmd=g_pDataReader->Read32();
114 case GX_LOAD_INDX_A: //used for position matrices
115 LoadIndexedXF(g_pDataReader->Read32(),0xC);
118 case GX_LOAD_INDX_B: //used for normal matrices
119 LoadIndexedXF(g_pDataReader->Read32(),0xD);
122 case GX_LOAD_INDX_C: //used for postmatrices
123 LoadIndexedXF(g_pDataReader->Read32(),0xE);
126 case GX_LOAD_INDX_D: //used for lights
127 LoadIndexedXF(g_pDataReader->Read32(),0xF);
132 MessageBox(0,"Display lists can't recurse!!","error",0);
135 case GX_CMD_INVL_VC:// Invalidate (vertex cache?)
142 int primitive = (Cmd&GX_PRIMITIVE_MASK) >> GX_PRIMITIVE_SHIFT;
149 //finish up last and commit
151 u16 numVertices = g_pDataReader->Read16();
153 VertexLoader::SetVArray(&tempvarray);
154 VertexLoader *loader = &VertexLoader[Cmd&GX_VAT_MASK];
156 loader->PrepareRun();
157 int vsize = loader->GetVertexSize();
158 loader->RunVertices(numVertices);
159 CVertexHandler::DrawVertices(primitive, numVertices, &tempvarray);
160 CVertexHandler::Flush();
171 //finish up last and commit
178 void CompiledDList::Pass2()
180 /* OpcodeReaders::SetDListReader(addr, addr+size);
182 data = new u32[dataSize];
183 code = new u8[codeSize]; //at least
185 batches = new Batch[numBatches];
190 x86SetPtr((s8*)code);
193 //actually do the recompiling, emit code and data, protect the memory
194 // but again, at the same time do the ordinary stuff
195 // so the compiled display list won't be run until the third time actually
196 bool dump = false,lastIsGeom=false;
202 f=fopen("D:\\dlistlogs.txt","a");
203 fprintf(f,"===========================================\n");
207 while (OpcodeReaders::IsDListOKToRead())
209 int Cmd = g_pDataReader->Read8();
212 case GX_LOAD_CP_REG: //0x08
215 u32 SubCmd = g_pDataReader->Read8();
216 u32 Value = g_pDataReader->Read32();
218 fprintf(f,"CP | %02x %08x\n",SubCmd,Value);
220 LoadCPReg(SubCmd,Value);
222 PUSH_WordToStack(Value);
223 PUSH_WordToStack(SubCmd);
224 CALLFunc((u32)LoadCPReg);
231 u32 Cmd2 = g_pDataReader->Read32();
232 int dwTransferSize = ((Cmd2>>16)&15) + 1;
233 u32 dwAddress = Cmd2 & 0xFFFF;
234 static u32 pData[16];
236 u32 *oldDataPtr = dataptr;
240 fprintf(f,"XF | %01xx %04x\n",dwTransferSize,dwAddress);
241 for (int i=0; i<dwTransferSize; i++)
242 fprintf(f, "%08x | %f\n",oldDataPtr[i], *((float*)oldDataPtr+i));
246 for (int i=0; i<dwTransferSize; i++) // a little compiler here too
247 *dataptr++ = g_pDataReader->Read32();
250 LoadXFReg(dwTransferSize,dwAddress,oldDataPtr);
253 PUSH_WordToStack((u32)oldDataPtr);
254 PUSH_WordToStack(dwAddress);
255 PUSH_WordToStack(dwTransferSize);
256 CALLFunc((u32)LoadXFReg);
260 case GX_LOAD_BP_REG: //0x61
263 u32 cmd=g_pDataReader->Read32();
265 fprintf(f,"BP | %08x\n",cmd);
269 PUSH_WordToStack(cmd);
270 CALLFunc((u32)LoadBPReg);
274 case GX_LOAD_INDX_A: //usually used for position matrices
277 u32 value = g_pDataReader->Read32();
278 LoadIndexedXF(value,0xC);
280 PUSH_WordToStack(0xC);
281 PUSH_WordToStack(value);
282 CALLFunc((u32)LoadIndexedXF);
284 fprintf(f,"LOADINDEXA | pos matrix\n");
287 case GX_LOAD_INDX_B: //usually used for normal matrices
290 u32 value = g_pDataReader->Read32();
291 LoadIndexedXF(value,0xD);
293 PUSH_WordToStack(0xD);
294 PUSH_WordToStack(value);
295 CALLFunc((u32)LoadIndexedXF);
297 fprintf(f,"LOADINDEXB | nrm matrix\n");
300 case GX_LOAD_INDX_C: //usually used for postmatrices
303 u32 value = g_pDataReader->Read32();
304 LoadIndexedXF(value,0xE);
306 PUSH_WordToStack(0xE);
307 PUSH_WordToStack(value);
308 CALLFunc((u32)LoadIndexedXF);
310 fprintf(f,"LOADINDEXC | post matrix\n");
313 case GX_LOAD_INDX_D: //usually used for lights
316 u32 value = g_pDataReader->Read32();
317 LoadIndexedXF(value,0xF);
319 PUSH_WordToStack(0xF);
320 PUSH_WordToStack(value);
321 CALLFunc((u32)LoadIndexedXF);
323 fprintf(f,"LOADINDEXD | light\n");
330 case GX_CMD_INVL_VC:// Invalidate (vertex cache?)
332 fprintf(f,"invalidate vc\n");
341 int primitive = (Cmd&GX_PRIMITIVE_MASK) >> GX_PRIMITIVE_SHIFT;
342 //if (lastIsGeom) INCSTAT(stats.numJoins);
343 u16 numVertices = g_pDataReader->Read16();
345 fprintf(f,"DP: prim=%02x numv=%i\n",primitive,numVertices);
346 DecodedVArray &va = batches[batchCount].varray;
348 VertexLoader *loader = &VertexLoader[Cmd&GX_VAT_MASK];
349 TVtxDesc &vd = loader->GetVtxDesc();
351 VertexLoader::SetVArray(&va);
353 loader->PrepareRun();
354 // va.numColors = loader->GetNumColors();
355 // va.numUVs = loader->GetNumTCs();
356 // va.numNormals = loader->GetNumNormals();
358 va.Create(numVertices,vd.PosMatIdx,
359 vd.Tex0MatIdx+vd.Tex1MatIdx+vd.Tex2MatIdx+vd.Tex3MatIdx+
360 vd.Tex4MatIdx+vd.Tex5MatIdx+vd.Tex6MatIdx+vd.Tex7MatIdx,
361 va.numNormals, va.numColors, va.numTCs);
363 int vsize = loader->GetVertexSize();
364 loader->RunVertices(numVertices);
365 CVertexHandler::DrawVertices(primitive, numVertices, &va);
366 CVertexHandler::Flush();
367 // YES we have now filled our varray
369 PUSH_WordToStack(primitive);
370 PUSH_WordToStack(batchCount);
371 PUSH_WordToStack((u32)this);
372 CALLFunc((u32)DrawHelperHelper);
376 fprintf(f,"DRAW PRIMITIVE: prim=%02x numv=%i\n",primitive,numVertices);
383 fprintf(f,"***************************************\n\n\n");
388 //we're done, next time just kick the compiled list off, much much faster than interpreting!
391 void CompiledDList::DrawHelperHelper(CompiledDList
*dl
, int vno
, int prim
)
393 Batch
&b
= dl
->batches
[vno
];
394 CVertexHandler::DrawVertices(prim
, b
.varray
.GetSize(), &b
.varray
);
397 void CompiledDList::Run()
400 ((void (*)())(code
))();
401 CVertexHandler::Flush();
404 DListCache::DLCache
DListCache::dlists
;
408 void DListCache::Init()
414 void DListCache::Shutdown()
416 DLCache::iterator iter
= dlists
.begin();
417 for (;iter
!=dlists
.end();iter
++)
418 iter
->second
.Destroy();
423 void DListCache::Call(u32 _addr
, u32 _size
)
425 DLCache::iterator iter
;
426 iter
= dlists
.find(_addr
);
428 if (iter
!= dlists
.end())
430 if (iter
->second
.size
== _size
)
432 iter
->second
.dlist
->Call();
435 else // wrong size, need to recompile
437 iter
->second
.Destroy();
438 iter
=dlists
.erase(iter
);
442 //Make an entry in the table
444 entry
.dlist
= new CompiledDList(_addr
, _size
);
446 entry
.frameCount
= frameCount
;
448 dlists
[_addr
] = entry
;
450 INCSTAT(stats
.numDListsCreated
);
451 SETSTAT(stats
.numDListsAlive
,(int)dlists
.size());
454 void DListCache::Cleanup()
456 for (DLCache::iterator iter
=dlists
.begin(); iter
!=dlists
.end();iter
++)
458 DLCacheEntry
&entry
= iter
->second
;
459 if (entry
.frameCount
<frameCount
-80)
462 iter
= dlists
.erase(iter
);
465 SETSTAT(stats
.numDListsAlive
,(int)dlists
.size());