From 32dfcf0fd236dfd4236cb7797a5aa9949b66ae30 Mon Sep 17 00:00:00 2001 From: aap Date: Wed, 16 Dec 2015 20:25:22 +0100 Subject: [PATCH] implemented PDS plugin and uninstancing in SA pipes --- src/geometry.cpp | 15 +- src/gtaplg.cpp | 431 ++++++++++++++++++++++++++++++++++++++++++++++- src/gtaplg.h | 4 + src/ps2.cpp | 193 +++++++++++---------- src/rwobjects.h | 2 +- src/rwps2.h | 41 ++++- 6 files changed, 574 insertions(+), 112 deletions(-) diff --git a/src/geometry.cpp b/src/geometry.cpp index 598d41d..7db2f16 100644 --- a/src/geometry.cpp +++ b/src/geometry.cpp @@ -289,33 +289,36 @@ Geometry::allocateData(void) static int isDegenerate(uint16 *idx) { - // TODO: maybe check position instead of index? return idx[0] == idx[1] || idx[0] == idx[2] || idx[1] == idx[2]; } void -Geometry::generateTriangles(void) +Geometry::generateTriangles(int8 *adc) { MeshHeader *header = this->meshHeader; assert(header != NULL); this->numTriangles = 0; Mesh *m = header->mesh; + int8 *adcbits = adc; for(uint32 i = 0; i < header->numMeshes; i++){ if(m->numIndices < 3){ // shouldn't happen but it does + adcbits += m->numIndices; m++; continue; } if(header->flags == 1){ // tristrip for(uint32 j = 0; j < m->numIndices-2; j++){ - if(!isDegenerate(&m->indices[j])) + if(!(adc && adcbits[j+2]) && + !isDegenerate(&m->indices[j])) this->numTriangles++; } }else this->numTriangles += m->numIndices/3; + adcbits += m->numIndices; m++; } @@ -324,8 +327,10 @@ Geometry::generateTriangles(void) uint16 *f = this->triangles; m = header->mesh; + adcbits = adc; for(uint32 i = 0; i < header->numMeshes; i++){ if(m->numIndices < 3){ + adcbits += m->numIndices; m++; continue; } @@ -334,7 +339,8 @@ Geometry::generateTriangles(void) this->numMaterials); if(header->flags == 1) // tristrip for(uint32 j = 0; j < m->numIndices-2; j++){ - if(isDegenerate(&m->indices[j])) + if(adc && adcbits[j+2] || + isDegenerate(&m->indices[j])) continue; *f++ = m->indices[j+1 + (j%2)]; *f++ = m->indices[j+0]; @@ -348,6 +354,7 @@ Geometry::generateTriangles(void) *f++ = matid; *f++ = m->indices[j+2]; } + adcbits += m->numIndices; m++; } } diff --git a/src/gtaplg.cpp b/src/gtaplg.cpp index 328a895..77e4eb2 100644 --- a/src/gtaplg.cpp +++ b/src/gtaplg.cpp @@ -21,7 +21,8 @@ namespace gta { void attachPlugins(void) { - rw::ps2::registerPDSPlugin(); + rw::ps2::registerPDSPlugin(12); + gta::registerPDSPipes(); rw::ps2::registerNativeRaster(); rw::xbox::registerNativeRaster(); @@ -36,12 +37,12 @@ attachPlugins(void) rw::registerHAnimPlugin(); gta::registerNodeNamePlugin(); rw::registerMatFXPlugin(); -// rw::registerUVAnimPlugin(); + rw::registerUVAnimPlugin(); rw::ps2::registerADCPlugin(); gta::registerExtraNormalsPlugin(); gta::registerExtraVertColorPlugin(); gta::registerEnvSpecPlugin(); -// gta::registerBreakableModelPlugin(); + gta::registerBreakableModelPlugin(); gta::registerCollisionPlugin(); gta::register2dEffectPlugin(); gta::registerPipelinePlugin(); @@ -300,6 +301,16 @@ registerExtraNormalsPlugin(void) int32 extraVertColorOffset; +void +allocateExtraVertColors(Geometry *g) +{ + ExtraVertColors *colordata = + PLUGINOFFSET(ExtraVertColors, g, extraVertColorOffset); + colordata->nightColors = new uint8[g->numVertices*4]; + colordata->dayColors = new uint8[g->numVertices*4]; + colordata->balance = 1.0f; +} + static void* createExtraVertColors(void *object, int32 offset, int32) { @@ -759,4 +770,418 @@ registerCollisionPlugin(void) writeCollision, getSizeCollision); } +/* + * PS2 + */ + +using namespace ps2; + +PipeAttribute saXYZADC = { + "saXYZADC", + AT_V4_16 | AT_RW +}; + +PipeAttribute saUV = { + "saUV", + AT_V2_16 | AT_RW +}; + +PipeAttribute saUV2 = { + "saUV2", + AT_V4_16 | AT_RW +}; + +PipeAttribute saRGBA = { + "saRGBA", + AT_V4_8 | AT_UNSGN | AT_RW +}; + +PipeAttribute saRGBA2 = { + "saRGBA2", + AT_V4_16 | AT_UNSGN | AT_RW +}; + +PipeAttribute saNormal = { + "saNormal", + AT_V4_8 | AT_RW +}; + +PipeAttribute saWeights = { + "saWeights", + AT_V4_32 | AT_RW +}; + +static bool hasTex2(uint32 id) +{ + return id == 0x53f2008b; +} +static bool hasNormals(uint32 id) +{ + return id == 0x53f20085 || id == 0x53f20087 || id == 0x53f20089 || + id == 0x53f2008b || id == 0x53f2008d || id == 0x53f2008f; +} +static bool hasColors(uint32 id) +{ + return id == 0x53f20081 || id == 0x53f20083 || id == 0x53f2008d || id == 0x53f2008f; +} +static bool hasColors2(uint32 id) +{ + return id == 0x53f20083 || id == 0x53f2008f; +} + +struct SaVert { + float32 p[3]; + float32 n[3]; + float32 t0[2]; + float32 t1[2]; + uint8 c0[4]; + uint8 c1[4]; + float32 w[4]; + uint8 i[4]; +}; + +static void +saPreCB(MatPipeline *p, Geometry *geo) +{ + // allocate ADC, extra colors, skin + allocateADC(geo); + if(hasColors2(p->pluginData) && extraVertColorOffset) + allocateExtraVertColors(geo); + if(p->pluginData == 0x53f20089) + skinPreCB(p, geo); +} + +static void +saPostCB(MatPipeline *p, Geometry *geo) +{ + skinPostCB(p, geo); +} + +int32 +findSAVertex(Geometry *g, uint32 flags[], uint32 mask, SaVert *v) +{ + Skin *skin = *PLUGINOFFSET(Skin*, g, skinGlobals.offset); + float32 *wghts = NULL; + uint8 *inds = NULL; + if(skin){ + wghts = skin->weights; + inds = skin->indices; + } + float32 *verts = g->morphTargets[0].vertices; + float32 *tex0 = g->texCoords[0]; + float32 *tex1 = g->texCoords[1]; + float32 *norms = g->morphTargets[0].normals; + uint8 *cols0 = g->colors; + uint8 *cols1 = NULL; + if(extraVertColorOffset) + cols1 = PLUGINOFFSET(ExtraVertColors, g, extraVertColorOffset)->nightColors; + + for(int32 i = 0; i < g->numVertices; i++){ + if(mask & flags[i] & 0x1 && + !(verts[0] == v->p[0] && verts[1] == v->p[1] && verts[2] == v->p[2])) + goto cont; + if(mask & flags[i] & 0x10 && + !(norms[0] == v->n[0] && norms[1] == v->n[1] && norms[2] == v->n[2])) + goto cont; + if(mask & flags[i] & 0x100 && + !(cols0[0] == v->c0[0] && cols0[1] == v->c0[1] && + cols0[2] == v->c0[2] && cols0[3] == v->c0[3])) + goto cont; + if(mask & flags[i] & 0x200 && + !(cols1[0] == v->c1[0] && cols1[1] == v->c1[1] && + cols1[2] == v->c1[2] && cols1[3] == v->c1[3])) + goto cont; + if(mask & flags[i] & 0x1000 && + !(tex0[0] == v->t0[0] && tex0[1] == v->t0[1])) + goto cont; + if(mask & flags[i] & 0x2000 && + !(tex1[0] == v->t1[0] && tex1[1] == v->t1[1])) + goto cont; + if(mask & flags[i] & 0x10000 && + !(wghts[0] == v->w[0] && wghts[1] == v->w[1] && + wghts[2] == v->w[2] && wghts[3] == v->w[3] && + inds[0] == v->i[0] && inds[1] == v->i[1] && + inds[2] == v->i[2] && inds[3] == v->i[3])) + goto cont; + return i; + cont: + verts += 3; + tex0 += 2; + tex1 += 2; + norms += 3; + cols0 += 4; + cols1 += 4; + wghts += 4; + inds += 4; + } + return -1; +} + +void +insertSAVertex(Geometry *geo, int32 i, uint32 mask, SaVert *v) +{ + insertVertex(geo, i, mask, v->p, v->t0, v->t1, v->c0, v->n); + if(mask & 0x200 && extraVertColorOffset){ + uint8 *cols1 = + &PLUGINOFFSET(ExtraVertColors, geo, extraVertColorOffset)->nightColors[i*4]; + cols1[0] = v->c1[0]; + cols1[1] = v->c1[1]; + cols1[2] = v->c1[2]; + cols1[3] = v->c1[3]; + } + if(mask & 0x10000 && skinGlobals.offset){ + Skin *skin = *PLUGINOFFSET(Skin*, geo, skinGlobals.offset); + memcpy(&skin->weights[i*4], v->w, 16); + memcpy(&skin->indices[i*4], v->i, 4); + } +} + +static void +saUninstanceCB(ps2::MatPipeline *pipe, Geometry *geo, uint32 flags[], Mesh *mesh, uint8 *data[]) +{ + uint32 id = pipe->pluginData; + int16 *verts = (int16*)data[0]; + int16 *texcoords = (int16*)data[1]; + uint8 *colors = (uint8*)data[2]; + int8 *norms = (int8*)data[id == 0x53f20089 ? 2 : 3]; + uint32 *wghts = (uint32*)data[3]; + float vertScale = 1.0f/128.0f; + if(id == 0x53f20085 || id == 0x53f20087 || + id == 0x53f20089 || id == 0x53f2008b) + vertScale = 1.0f/1024.0f; + uint32 mask = 0x1; // vertices + int cinc = 4; + int tinc = 2; + if((geo->geoflags & Geometry::NORMALS) && hasNormals(id)) + mask |= 0x10; + if((geo->geoflags & Geometry::PRELIT) && hasColors(id)) + mask |= 0x100; + if(hasColors2(id)){ + mask |= 0x200; + cinc *= 2; + } + if(geo->numTexCoordSets > 0) + mask |= 0x1000; + if(geo->numTexCoordSets > 0 && hasTex2(id)){ + mask |= 0x2000; + tinc *= 2; + } + if(id == 0x53f20089) + mask |= 0x10000; + SaVert v; + int32 idxstart = 0; + for(Mesh *m = geo->meshHeader->mesh; m < mesh; m++) + idxstart += m->numIndices; + int8 *adc = PLUGINOFFSET(ADCData, geo, adcOffset)->adcBits; + for(uint32 i = 0; i < mesh->numIndices; i++){ + v.p[0] = verts[0]*vertScale; + v.p[1] = verts[1]*vertScale; + v.p[2] = verts[2]*vertScale; + if(mask & 0x10){ + v.n[0] = norms[0]/127.0f; + v.n[1] = norms[1]/127.0f; + v.n[2] = norms[2]/127.0f; + } + if(mask & 0x200){ + v.c0[0] = colors[0]; + v.c0[1] = colors[2]; + v.c0[2] = colors[4]; + v.c0[3] = colors[6]; + v.c1[0] = colors[1]; + v.c1[1] = colors[3]; + v.c1[2] = colors[5]; + v.c1[3] = colors[7]; + }else if(mask & 0x100){ + v.c0[0] = colors[0]; + v.c0[1] = colors[1]; + v.c0[2] = colors[2]; + v.c0[3] = colors[3]; + } + if(mask & 0x1000){ + v.t0[0] = texcoords[0]/4096.0f; + v.t0[1] = texcoords[1]/4096.0f; + } + if(mask & 0x2000){ + v.t1[0] = texcoords[2]/4096.0f; + v.t1[1] = texcoords[3]/4096.0f; + } + if(mask & 0x10000){ + for(int j = 0; j < 4; j++){ + ((uint32*)v.w)[j] = wghts[j] & ~0x3FF; + v.i[j] = (wghts[j] & 0x3FF) >> 2; + if(v.i[j]) v.i[j]--; + if(v.w[j] == 0.0f) v.i[j] = 0; + } + } + int32 idx = findSAVertex(geo, flags, mask, &v); + if(idx < 0) + idx = geo->numVertices++; + mesh->indices[i] = idx; + adc[idxstart+i] = !!verts[3]; + flags[idx] = mask; + insertSAVertex(geo, idx, mask, &v); + + verts += 4; + texcoords += tinc; + colors += cinc; + norms += 4; + wghts += 4; + } + +} + +static void +saInstanceCB(MatPipeline *, Geometry *g, Mesh *m, uint8 **data, int32 n) +{ +} + +void +registerPDSPipes(void) +{ + Pipeline *pipe; + MatPipeline *mpipe; + + // Atomic pipes + + pipe = new ps2::ObjPipeline(PLATFORM_PS2); + pipe->pluginID = ID_PDS; + pipe->pluginData = 0x53f20080; + ps2::registerPDSPipe(pipe); + + pipe = new ps2::ObjPipeline(PLATFORM_PS2); + pipe->pluginID = ID_PDS; + pipe->pluginData = 0x53f20082; + ps2::registerPDSPipe(pipe); + + pipe = new ps2::ObjPipeline(PLATFORM_PS2); + pipe->pluginID = ID_PDS; + pipe->pluginData = 0x53f20084; + ps2::registerPDSPipe(pipe); + + pipe = new ps2::ObjPipeline(PLATFORM_PS2); + pipe->pluginID = ID_PDS; + pipe->pluginData = 0x53f20088; + ps2::registerPDSPipe(pipe); + + // Material pipes + + mpipe = new MatPipeline(PLATFORM_PS2); + mpipe->pluginID = ID_PDS; + mpipe->pluginData = 0x53f20081; + mpipe->attribs[0] = &saXYZADC; + mpipe->attribs[1] = &saUV; + mpipe->attribs[2] = &saRGBA; + uint32 vertCount = MatPipeline::getVertCount(VU_Lights, 3, 3, 2); + mpipe->setTriBufferSizes(3, vertCount); + mpipe->vifOffset = mpipe->inputStride*vertCount; + mpipe->instanceCB = saInstanceCB; + mpipe->preUninstCB = saPreCB; + mpipe->uninstanceCB = saUninstanceCB; + ps2::registerPDSPipe(mpipe); + + mpipe = new MatPipeline(PLATFORM_PS2); + mpipe->pluginID = ID_PDS; + mpipe->pluginData = 0x53f20083; + mpipe->attribs[0] = &saXYZADC; + mpipe->attribs[1] = &saUV; + mpipe->attribs[2] = &saRGBA2; + vertCount = MatPipeline::getVertCount(VU_Lights, 3, 3, 2); + mpipe->setTriBufferSizes(3, vertCount); + mpipe->vifOffset = mpipe->inputStride*vertCount; + mpipe->instanceCB = saInstanceCB; + mpipe->preUninstCB = saPreCB; + mpipe->uninstanceCB = saUninstanceCB; + ps2::registerPDSPipe(mpipe); + + mpipe = new MatPipeline(PLATFORM_PS2); + mpipe->pluginID = ID_PDS; + mpipe->pluginData = 0x53f20085; + mpipe->attribs[0] = &saXYZADC; + mpipe->attribs[1] = &saUV; + mpipe->attribs[3] = &saNormal; + vertCount = MatPipeline::getVertCount(VU_Lights, 4, 3, 2); + mpipe->setTriBufferSizes(4, vertCount); + mpipe->vifOffset = mpipe->inputStride*vertCount; + mpipe->instanceCB = saInstanceCB; + mpipe->preUninstCB = saPreCB; + mpipe->uninstanceCB = saUninstanceCB; + ps2::registerPDSPipe(mpipe); + + mpipe = new MatPipeline(PLATFORM_PS2); + mpipe->pluginID = ID_PDS; + mpipe->pluginData = 0x53f20087; + mpipe->attribs[0] = &saXYZADC; + mpipe->attribs[1] = &saUV; + mpipe->attribs[3] = &saNormal; + vertCount = MatPipeline::getVertCount(0x3BD, 4, 3, 3); + mpipe->setTriBufferSizes(4, vertCount); + mpipe->vifOffset = mpipe->inputStride*vertCount; + mpipe->instanceCB = saInstanceCB; + mpipe->preUninstCB = saPreCB; + mpipe->uninstanceCB = saUninstanceCB; + ps2::registerPDSPipe(mpipe); + + mpipe = new MatPipeline(PLATFORM_PS2); + mpipe->pluginID = ID_PDS; + mpipe->pluginData = 0x53f20089; + mpipe->attribs[0] = &saXYZADC; + mpipe->attribs[1] = &saUV; + mpipe->attribs[2] = &saNormal; + mpipe->attribs[3] = &saWeights; +// these values give vertCount = 0x33 :/ +// vertCount = MatPipeline::getVertCount(0x2D0, 4, 3, 2); + vertCount = 0x30; + mpipe->setTriBufferSizes(4, vertCount); + mpipe->vifOffset = mpipe->inputStride*vertCount; + mpipe->instanceCB = saInstanceCB; + mpipe->preUninstCB = saPreCB; + mpipe->uninstanceCB = saUninstanceCB; + mpipe->postUninstCB = saPostCB; + ps2::registerPDSPipe(mpipe); + + mpipe = new MatPipeline(PLATFORM_PS2); + mpipe->pluginID = ID_PDS; + mpipe->pluginData = 0x53f2008b; + mpipe->attribs[0] = &saXYZADC; + mpipe->attribs[1] = &saUV2; + mpipe->attribs[3] = &saNormal; + vertCount = MatPipeline::getVertCount(0x3BD, 4, 3, 3); + mpipe->setTriBufferSizes(4, vertCount); + mpipe->vifOffset = mpipe->inputStride*vertCount; + mpipe->instanceCB = saInstanceCB; + mpipe->preUninstCB = saPreCB; + mpipe->uninstanceCB = saUninstanceCB; + ps2::registerPDSPipe(mpipe); + + mpipe = new MatPipeline(PLATFORM_PS2); + mpipe->pluginID = ID_PDS; + mpipe->pluginData = 0x53f2008d; + mpipe->attribs[0] = &saXYZADC; + mpipe->attribs[1] = &saUV; + mpipe->attribs[2] = &saRGBA; + mpipe->attribs[3] = &saNormal; + vertCount = MatPipeline::getVertCount(0x3BD, 4, 3, 3); + mpipe->setTriBufferSizes(4, vertCount); + mpipe->vifOffset = mpipe->inputStride*vertCount; + mpipe->instanceCB = saInstanceCB; + mpipe->preUninstCB = saPreCB; + mpipe->uninstanceCB = saUninstanceCB; + ps2::registerPDSPipe(mpipe); + + mpipe = new MatPipeline(PLATFORM_PS2); + mpipe->pluginID = ID_PDS; + mpipe->pluginData = 0x53f2008f; + mpipe->attribs[0] = &saXYZADC; + mpipe->attribs[1] = &saUV; + mpipe->attribs[2] = &saRGBA2; + mpipe->attribs[3] = &saNormal; + vertCount = MatPipeline::getVertCount(0x3BD, 4, 3, 3); + mpipe->setTriBufferSizes(4, vertCount); + mpipe->vifOffset = mpipe->inputStride*vertCount; + mpipe->instanceCB = saInstanceCB; + mpipe->preUninstCB = saPreCB; + mpipe->uninstanceCB = saUninstanceCB; + ps2::registerPDSPipe(mpipe); +} + } diff --git a/src/gtaplg.h b/src/gtaplg.h index 9b43b2c..664d642 100644 --- a/src/gtaplg.h +++ b/src/gtaplg.h @@ -116,4 +116,8 @@ extern int32 collisionOffset; void registerCollisionPlugin(void); +// PDS pipes + +void registerPDSPipes(void); + } diff --git a/src/ps2.cpp b/src/ps2.cpp index f8109cb..df7de32 100644 --- a/src/ps2.cpp +++ b/src/ps2.cpp @@ -58,6 +58,7 @@ readNativeData(Stream *stream, int32, void *object, int32, int32) assert(a % 0x10 == 0); #endif stream->read(instance->data, instance->dataSize); + instance->material = geometry->meshHeader->mesh[i].material; // sizedebug(instance); } } @@ -189,28 +190,6 @@ unfixDmaOffsets(InstanceData *inst) // Pipeline -enum PS2Attribs { - AT_V2_32 = 0x64000000, - AT_V2_16 = 0x65000000, - AT_V2_8 = 0x66000000, - AT_V3_32 = 0x68000000, - AT_V3_16 = 0x69000000, - AT_V3_8 = 0x6A000000, - AT_V4_32 = 0x6C000000, - AT_V4_16 = 0x6D000000, - AT_V4_8 = 0x6E000000, - AT_UNSGN = 0x00004000, - - AT_RW = 0x6 -}; - -enum PS2AttibTypes { - AT_XYZ = 0, - AT_UV = 1, - AT_RGBA = 2, - AT_NORMAL = 3 -}; - PipeAttribute attribXYZ = { "XYZ", AT_V3_32 @@ -254,10 +233,10 @@ static uint32 getBatchSize(MatPipeline *pipe, uint32 vertCount) { PipeAttribute *a; - uint32 size = 1; + uint32 size = 1; // ITOP &c. at the end for(uint i = 0; i < nelem(pipe->attribs); i++) if((a = pipe->attribs[i]) && (a->attrib & AT_RW) == 0){ - size++; + size++; // UNPACK &c. size += QWC(vertCount*attribSize(a->attrib)); } return size; @@ -345,7 +324,7 @@ instanceNormal(uint32 *wp, Geometry *g, Mesh *m, uint32 idx, uint32 n) MatPipeline::MatPipeline(uint32 platform) : rw::Pipeline(platform), instanceCB(NULL), uninstanceCB(NULL), - allocateCB(NULL), finishCB(NULL) + preUninstCB(NULL), postUninstCB(NULL) { for(int i = 0; i < 10; i++) this->attribs[i] = NULL; @@ -436,7 +415,7 @@ getInstMeshInfo(MatPipeline *pipe, Geometry *g, Mesh *m) if(im.numBrokenAttribs == 0) im.size = 1 + im.batchSize*(im.numBatches-1) + im.lastBatchSize; else - im.size = 2*im.numBatches + + im.size = 2*im.numBrokenAttribs*im.numBatches + (1+im.batchSize)*(im.numBatches-1) + 1+im.lastBatchSize; /* figure out size and addresses of broken out sections */ @@ -492,8 +471,11 @@ MatPipeline::instance(Geometry *g, InstanceData *inst, Mesh *m) *p++ = im.attribPos[i]; *p++ = 0x01000100 | this->inputStride; // STCYCL + // Round up nverts so UNPACK will fit exactly into the DMA packet + // (can't pad with zeroes in broken out sections). + // TODO: check for clash with vifOffset somewhere *p++ = (a->attrib&0xFF004000) - | 0x8000 | nverts << 16 | i; // UNPACK + | 0x8000 | (QWC(nverts*atsz)<<4)/atsz << 16 | i; // UNPACK *p++ = 0x10000000; *p++ = 0x0; @@ -572,10 +554,7 @@ MatPipeline::collectData(Geometry *g, InstanceData *inst, Mesh *m, uint8 *data[] } uint8 *datap[nelem(this->attribs)]; - for(uint i = 0; i < nelem(this->attribs); i++){ - datap[i] = data[i]; - //printf("%p %x, %x\n", datap[i], datap[i]-datap[0], im.attribPos[i]*0x10); - } + memcpy(datap, data, sizeof(datap)); uint32 overlap = g->meshHeader->flags == 1 ? 2 : 0; uint32 *p = (uint32*)inst->data; @@ -630,6 +609,7 @@ ObjPipeline::instance(Atomic *atomic) if(m == NULL) m = defaultMatPipe; m->instance(geo, instance, mesh); + instance->material = mesh->material; } geo->geoflags |= Geometry::NATIVE; } @@ -638,6 +618,9 @@ void printVertCounts(InstanceData *inst, int flag) { uint32 *d = (uint32*)inst->data; + uint32 id = 0; + if(inst->material->pipeline) + id = inst->material->pipeline->pluginData; int stride; if(inst->arePointersFixed){ d += 4; @@ -646,15 +629,16 @@ printVertCounts(InstanceData *inst, int flag) d += 4 + 4*QWC(attribSize(d[3])*((d[3]>>16)&0xFF)); } if(d[2] == 0) - printf("ITOP %x %d (%d)\n", *d, stride, flag); + printf("ITOP %x %d (%d) %x\n", *d, stride, flag, id); }else{ while((*d&0x70000000) == 0x30000000){ stride = d[2]&0xFF; + printf("UNPACK %x %d (%d) %x\n", d[3], stride, flag, id); d += 8; } if((*d&0x70000000) == 0x10000000){ d += (*d&0xFFFF)*4; - printf("ITOP %x %d (%d)\n", *d, stride, flag); + printf("ITOP %x %d (%d) %x\n", *d, stride, flag, id); } } } @@ -667,6 +651,7 @@ ObjPipeline::uninstance(Atomic *atomic) return; assert(geo->instData != NULL); assert(geo->instData->platform == PLATFORM_PS2); + InstanceDataHeader *header = (InstanceDataHeader*)geo->instData; // highest possible number of vertices geo->numVertices = geo->meshHeader->totalIndices; geo->geoflags &= ~Geometry::NATIVE; @@ -675,18 +660,24 @@ ObjPipeline::uninstance(Atomic *atomic) uint32 *flags = new uint32[geo->numVertices]; memset(flags, 0, 4*geo->numVertices); memset(geo->meshHeader->mesh[0].indices, 0, 2*geo->meshHeader->totalIndices); - geo->numVertices = 0; - InstanceDataHeader *header = (InstanceDataHeader*)geo->instData; for(uint32 i = 0; i < header->numMeshes; i++){ Mesh *mesh = &geo->meshHeader->mesh[i]; - InstanceData *instance = &header->instanceMeshes[i]; - MatPipeline *m; m = this->groupPipeline ? this->groupPipeline : (MatPipeline*)mesh->material->pipeline; if(m == NULL) m = defaultMatPipe; - if(m->allocateCB) m->allocateCB(m, geo); + if(m->preUninstCB) m->preUninstCB(m, geo); + } + geo->numVertices = 0; + for(uint32 i = 0; i < header->numMeshes; i++){ + Mesh *mesh = &geo->meshHeader->mesh[i]; + InstanceData *instance = &header->instanceMeshes[i]; + MatPipeline *m; + m = this->groupPipeline ? + this->groupPipeline : + (MatPipeline*)mesh->material->pipeline; + if(m == NULL) m = defaultMatPipe; uint8 *data[nelem(m->attribs)] = { NULL }; uint8 *raw = m->collectData(geo, instance, mesh, data); @@ -701,21 +692,28 @@ ObjPipeline::uninstance(Atomic *atomic) this->groupPipeline : (MatPipeline*)mesh->material->pipeline; if(m == NULL) m = defaultMatPipe; - if(m->finishCB) m->finishCB(m, geo); + if(m->postUninstCB) m->postUninstCB(m, geo); } - geo->generateTriangles(); + int8 *bits = NULL; + if(adcOffset){ + ADCData *adc = PLUGINOFFSET(ADCData, geo, adcOffset); + if(adc->adcFormatted) + bits = adc->adcBits; + } + geo->generateTriangles(bits); delete[] flags; destroyNativeData(geo, 0, 0); geo->instData = NULL; - -/* for(uint32 i = 0; i < header->numMeshes; i++){ - Mesh *mesh = &geometry->meshHeader->mesh[i]; +/* + for(uint32 i = 0; i < header->numMeshes; i++){ + Mesh *mesh = &geo->meshHeader->mesh[i]; InstanceData *instance = &header->instanceMeshes[i]; // printf("numIndices: %d\n", mesh->numIndices); // printDMA(instance); - printVertCounts(instance, geometry->meshHeader->flags); - }*/ + printVertCounts(instance, geo->meshHeader->flags); + } +*/ } int32 @@ -832,8 +830,6 @@ makeDefaultPipeline(void) static void skinInstanceCB(MatPipeline*, Geometry*, Mesh*, uint8**, int32); static void skinUninstanceCB(MatPipeline*, Geometry*, uint32*, Mesh*, uint8**); -static void skinAllocateCB(MatPipeline*, Geometry*); -static void skinFinishCB(MatPipeline*, Geometry*); ObjPipeline* makeSkinPipeline(void) @@ -851,8 +847,8 @@ makeSkinPipeline(void) pipe->vifOffset = pipe->inputStride*vertCount; pipe->instanceCB = skinInstanceCB; pipe->uninstanceCB = skinUninstanceCB; - pipe->allocateCB = skinAllocateCB; - pipe->finishCB = skinFinishCB; + pipe->preUninstCB = skinPreCB; + pipe->postUninstCB = skinPostCB; ObjPipeline *opipe = new ObjPipeline(PLATFORM_PS2); opipe->pluginID = ID_SKIN; @@ -1108,15 +1104,12 @@ skinUninstanceCB(MatPipeline *pipe, Geometry *geo, uint32 flags[], Mesh *mesh, u } } -static void -skinAllocateCB(MatPipeline*, Geometry *geo) +void +skinPreCB(MatPipeline*, Geometry *geo) { Skin *skin = *PLUGINOFFSET(Skin*, geo, skinGlobals.offset); - // If weight/index data is allocated don't do it again as this function - // can be called multiple times per geometry. - if(skin == NULL || skin->weights) + if(skin == NULL) return; - uint8 *data = skin->data; float *invMats = skin->inverseMatrices; // meshHeader->totalIndices is highest possible number of vertices again @@ -1125,8 +1118,8 @@ skinAllocateCB(MatPipeline*, Geometry *geo) delete[] data; } -static void -skinFinishCB(MatPipeline*, Geometry *geo) +void +skinPostCB(MatPipeline*, Geometry *geo) { Skin *skin = *PLUGINOFFSET(Skin*, geo, skinGlobals.offset); skin->findNumWeights(geo->numVertices); @@ -1135,6 +1128,8 @@ skinFinishCB(MatPipeline*, Geometry *geo) // ADC +int32 adcOffset; + // TODO: look at PC SA rccam.dff bloodrb.dff, Xbox csbigbear.dff static void @@ -1217,6 +1212,17 @@ debugadc(Geometry *g, MeshHeader *mh, ADCData *adc) return n; } +void +allocateADC(Geometry *geo) +{ + ADCData *adc = PLUGINOFFSET(ADCData, geo, adcOffset); + adc->adcFormatted = 1; + adc->numBits = geo->meshHeader->totalIndices; + int32 size = adc->numBits+3 & ~3; + adc->adcBits = new int8[size]; + memset(adc->adcBits, 0, size); +} + static void* createADC(void *object, int32 offset, int32) { @@ -1311,8 +1317,8 @@ getSizeADC(void *object, int32 offset, int32) void registerADCPlugin(void) { - Geometry::registerPlugin(sizeof(ADCData), ID_ADC, - createADC, destroyADC, copyADC); + adcOffset = Geometry::registerPlugin(sizeof(ADCData), ID_ADC, + createADC, destroyADC, copyADC); Geometry::registerPluginStream(ID_ADC, readADC, writeADC, @@ -1322,29 +1328,50 @@ registerADCPlugin(void) // PDS plugin +struct PdsGlobals +{ + Pipeline **pipes; + int32 maxPipes; + int32 numPipes; +}; +PdsGlobals pdsGlobals; + +Pipeline* +getPDSPipe(uint32 data) +{ + for(int32 i = 0; i < pdsGlobals.numPipes; i++) + if(pdsGlobals.pipes[i]->pluginData == data) + return pdsGlobals.pipes[i]; + return NULL; +} + +void +registerPDSPipe(Pipeline *pipe) +{ + assert(pdsGlobals.numPipes < pdsGlobals.maxPipes); + pdsGlobals.pipes[pdsGlobals.numPipes++] = pipe; +} + static void atomicPDSRights(void *object, int32, int32, uint32 data) { Atomic *a = (Atomic*)object; - // TODO: lookup pipeline by data - a->pipeline = new ObjPipeline(PLATFORM_PS2); - a->pipeline->pluginID = ID_PDS; - a->pipeline->pluginData = data; + a->pipeline = (ObjPipeline*)getPDSPipe(data); } static void materialPDSRights(void *object, int32, int32, uint32 data) { Material *m = (Material*)object; - // TODO: lookup pipeline by data - m->pipeline = new Pipeline(PLATFORM_PS2); - m->pipeline->pluginID = ID_PDS; - m->pipeline->pluginData = data; + m->pipeline = (ObjPipeline*)getPDSPipe(data); } void -registerPDSPlugin(void) +registerPDSPlugin(int32 n) { + pdsGlobals.maxPipes = n; + pdsGlobals.numPipes = 0; + pdsGlobals.pipes = new Pipeline*[n]; Atomic::registerPlugin(0, ID_PDS, NULL, NULL, NULL); Atomic::setStreamRightsCallback(ID_PDS, atomicPDSRights); @@ -1381,36 +1408,6 @@ printDMA(InstanceData *inst) } } -/* Function to specifically walk geometry chains */ -void -walkDMA(InstanceData *inst, void (*f)(uint32 *data, int32 size)) -{ - if(inst->arePointersFixed == 2) - return; - uint32 *base = (uint32*)inst->data; - uint32 *tag = (uint32*)inst->data; - for(;;){ - switch(tag[0]&0x70000000){ - // DMAcnt - case 0x10000000: - f(tag+2, 2+(tag[0]&0xFFFF)*4); - tag += (1+(tag[0]&0xFFFF))*4; - break; - - // DMAref - case 0x30000000: - f(base + tag[1]*4, (tag[0]&0xFFFF)*4); - tag += 4; - break; - - // DMAret - case 0x60000000: - f(tag+2, 2+(tag[0]&0xFFFF)*4); - return; - } - } -} - void sizedebug(InstanceData *inst) { diff --git a/src/rwobjects.h b/src/rwobjects.h index 8ac983c..0aec5b2 100644 --- a/src/rwobjects.h +++ b/src/rwobjects.h @@ -333,7 +333,7 @@ struct Geometry : PluginBase, Object uint32 streamGetSize(void); void addMorphTargets(int32 n); void allocateData(void); - void generateTriangles(void); + void generateTriangles(int8 *adc = NULL); enum Flags { diff --git a/src/rwps2.h b/src/rwps2.h index b5b87c5..ca61145 100644 --- a/src/rwps2.h +++ b/src/rwps2.h @@ -23,6 +23,28 @@ enum { VU_Lights = 0x3d0 }; +enum PS2Attribs { + AT_V2_32 = 0x64000000, + AT_V2_16 = 0x65000000, + AT_V2_8 = 0x66000000, + AT_V3_32 = 0x68000000, + AT_V3_16 = 0x69000000, + AT_V3_8 = 0x6A000000, + AT_V4_32 = 0x6C000000, + AT_V4_16 = 0x6D000000, + AT_V4_8 = 0x6E000000, + AT_UNSGN = 0x00004000, + + AT_RW = 0x6 +}; + +enum PS2AttibTypes { + AT_XYZ = 0, + AT_UV = 1, + AT_RGBA = 2, + AT_NORMAL = 3 +}; + void *destroyNativeData(void *object, int32, int32); void readNativeData(Stream *stream, int32 len, void *object, int32, int32); void writeNativeData(Stream *stream, int32 len, void *object, int32, int32); @@ -30,7 +52,6 @@ int32 getSizeNativeData(void *object, int32, int32); void registerNativeDataPlugin(void); void printDMA(InstanceData *inst); -void walkDMA(InstanceData *inst, void (*f)(uint32 *data, int32 size)); void sizedebug(InstanceData *inst); // only RW_PS2 @@ -47,8 +68,8 @@ public: PipeAttribute *attribs[10]; void (*instanceCB)(MatPipeline*, Geometry*, Mesh*, uint8**, int32); void (*uninstanceCB)(MatPipeline*, Geometry*, uint32*, Mesh*, uint8**); - void (*allocateCB)(MatPipeline*, Geometry*); - void (*finishCB)(MatPipeline*, Geometry*); + void (*preUninstCB)(MatPipeline*, Geometry*); + void (*postUninstCB)(MatPipeline*, Geometry*); static uint32 getVertCount(uint32 top, uint32 inAttribs, uint32 outAttribs, uint32 outBufs) { @@ -72,6 +93,8 @@ public: virtual void uninstance(Atomic *atomic); }; +void insertVertex(Geometry *geo, int32 i, uint32 mask, float *v, float *t0, float *t1, uint8 *c, float *n); + extern ObjPipeline *defaultObjPipe; extern MatPipeline *defaultMatPipe; @@ -86,6 +109,9 @@ void readNativeSkin(Stream *stream, int32, void *object, int32 offset); void writeNativeSkin(Stream *stream, int32 len, void *object, int32 offset); int32 getSizeNativeSkin(void *object, int32 offset); +void skinPreCB(MatPipeline*, Geometry*); +void skinPostCB(MatPipeline*, Geometry*); + // ADC plugin // Each element in adcBits corresponds to an index in Mesh->indices, @@ -101,9 +127,11 @@ struct ADCData int8 *adcBits; int32 numBits; }; - +extern int32 adcOffset; void registerADCPlugin(void); +void allocateADC(Geometry *geo); + // PDS plugin // IDs used by SA @@ -117,8 +145,9 @@ void registerADCPlugin(void); // 4640 53f20084 53f2008b // vehicles // 418 53f20088 53f20089 // peds - -void registerPDSPlugin(void); +Pipeline *getPDSPipe(uint32 data); +void registerPDSPipe(Pipeline *pipe); +void registerPDSPlugin(int32 n); // Native Texture and Raster