#include #include #include #include #include #include "rwbase.h" #include "rwplugin.h" #include "rwpipeline.h" #include "rwobjects.h" #include "rwps2.h" #include "rwd3d.h" #include "rwxbox.h" #include "gtaplg.h" using namespace std; namespace rw { int32 findPlatform(Clump *c) { FORLIST(lnk, c->atomics){ Geometry *g = Atomic::fromClump(lnk)->geometry; if(g->instData) return g->instData->platform; } return 0; } void switchPipes(Clump *c, int32 platform) { FORLIST(lnk, c->atomics){ Atomic *a = Atomic::fromClump(lnk); if(a->pipeline && a->pipeline->platform != platform){ uint32 plgid = a->pipeline->pluginID; switch(plgid){ case ID_SKIN: a->pipeline = skinGlobals.pipelines[platform]; break; case ID_MATFX: a->pipeline = matFXGlobals.pipelines[platform]; break; } } } } } namespace gta { void attachPlugins(void) { rw::ps2::registerPDSPlugin(12); gta::registerPDSPipes(); rw::ps2::registerNativeRaster(); rw::xbox::registerNativeRaster(); rw::d3d::registerNativeRaster(); rw::registerMeshPlugin(); rw::registerNativeDataPlugin(); rw::registerAtomicRightsPlugin(); rw::registerMaterialRightsPlugin(); rw::xbox::registerVertexFormatPlugin(); rw::registerSkinPlugin(); rw::registerHAnimPlugin(); gta::registerNodeNamePlugin(); rw::registerMatFXPlugin(); rw::registerUVAnimPlugin(); rw::ps2::registerADCPlugin(); gta::registerExtraNormalsPlugin(); gta::registerExtraVertColorPlugin(); gta::registerEnvSpecPlugin(); gta::registerBreakableModelPlugin(); gta::registerCollisionPlugin(); gta::register2dEffectPlugin(); gta::registerPipelinePlugin(); rw::Atomic::init(); } // // Frame // // Node Name int32 nodeNameOffset; static void* createNodeName(void *object, int32 offset, int32) { char *name = PLUGINOFFSET(char, object, offset); name[0] = '\0'; return object; } static void* copyNodeName(void *dst, void *src, int32 offset, int32) { char *dstname = PLUGINOFFSET(char, dst, offset); char *srcname = PLUGINOFFSET(char, src, offset); strncpy(dstname, srcname, 23); return dst; } static void* destroyNodeName(void *object, int32, int32) { return object; } static void readNodeName(Stream *stream, int32 len, void *object, int32 offset, int32) { char *name = PLUGINOFFSET(char, object, offset); stream->read(name, len); name[len] = '\0'; //printf("%s\n", name); } static void writeNodeName(Stream *stream, int32 len, void *object, int32 offset, int32) { char *name = PLUGINOFFSET(char, object, offset); stream->write(name, len); } static int32 getSizeNodeName(void *object, int32 offset, int32) { char *name = PLUGINOFFSET(char, object, offset); int32 len = strlen(name); return len > 0 ? len : 0; } void registerNodeNamePlugin(void) { nodeNameOffset = Frame::registerPlugin(24, ID_NODENAME, createNodeName, destroyNodeName, copyNodeName); Frame::registerPluginStream(ID_NODENAME, readNodeName, writeNodeName, getSizeNodeName); } char* getNodeName(Frame *f) { return PLUGINOFFSET(char, f, nodeNameOffset); } // // Geometry // // Breakable Model int32 breakableOffset; static void* createBreakableModel(void *object, int32 offset, int32) { *PLUGINOFFSET(uint8*, object, offset) = 0; return object; } static void* destroyBreakableModel(void *object, int32 offset, int32) { uint8 *p = *PLUGINOFFSET(uint8*, object, offset); delete[] p; return object; } static void readBreakableModel(Stream *stream, int32, void *object, int32 o, int32) { uint32 header[13]; uint32 hasBreakable = stream->readU32(); if(hasBreakable == 0) return; stream->read(header, 13*4); uint32 size = header[1]*(12+8+4) + header[5]*(6+2) + header[8]*(32+32+12); uint8 *p = new uint8[sizeof(Breakable)+size]; Breakable *breakable = (Breakable*)p; *PLUGINOFFSET(Breakable*, object, o) = breakable; breakable->position = header[0]; breakable->numVertices = header[1]; breakable->numFaces = header[5]; breakable->numMaterials = header[8]; p += sizeof(Breakable); stream->read(p, size); breakable->vertices = (float*)p; p += breakable->numVertices*12; breakable->texCoords = (float*)p; p += breakable->numVertices*8; breakable->colors = (uint8*)p; p += breakable->numVertices*4; breakable->faces = (uint16*)p; p += breakable->numFaces*6; breakable->matIDs = (uint16*)p; p += breakable->numFaces*2; breakable->texNames = (char(*)[32])p; p += breakable->numMaterials*32; breakable->maskNames = (char(*)[32])p; p += breakable->numMaterials*32; breakable->surfaceProps = (float32(*)[3])p; } static void writeBreakableModel(Stream *stream, int32, void *object, int32 o, int32) { uint32 header[13]; Breakable *breakable = *PLUGINOFFSET(Breakable*, object, o); uint8 *p = (uint8*)breakable; if(breakable == NULL){ stream->writeU32(0); return; } stream->writeU32(1); memset((char*)header, 0, 13*4); header[0] = breakable->position; header[1] = breakable->numVertices; header[5] = breakable->numFaces; header[8] = breakable->numMaterials; stream->write(header, 13*4); p += sizeof(Breakable); stream->write(p, breakable->numVertices*(12+8+4) + breakable->numFaces*(6+2) + breakable->numMaterials*(32+32+12)); } static int32 getSizeBreakableModel(void *object, int32 offset, int32) { Breakable *breakable = *PLUGINOFFSET(Breakable*, object, offset); if(breakable == NULL) return 0; //4; return 56 + breakable->numVertices*(12+8+4) + breakable->numFaces*(6+2) + breakable->numMaterials*(32+32+12); } void registerBreakableModelPlugin(void) { breakableOffset = Geometry::registerPlugin(sizeof(Breakable*), ID_BREAKABLE, createBreakableModel, destroyBreakableModel, NULL); Geometry::registerPluginStream(ID_BREAKABLE, readBreakableModel, writeBreakableModel, getSizeBreakableModel); } // Extra normals int32 extraNormalsOffset; static void* createExtraNormals(void *object, int32 offset, int32) { *PLUGINOFFSET(float*, object, offset) = NULL; return object; } static void* destroyExtraNormals(void *object, int32 offset, int32) { float *extranormals = *PLUGINOFFSET(float*, object, offset); delete[] extranormals; *PLUGINOFFSET(float*, object, offset) = NULL; return object; } static void readExtraNormals(Stream *stream, int32, void *object, int32 offset, int32) { Geometry *geo = (Geometry*)object; float **plgp = PLUGINOFFSET(float*, object, offset); if(*plgp) delete[] *plgp; float *extranormals = *plgp = new float[geo->numVertices*3]; stream->read(extranormals, geo->numVertices*3*4); // printf("extra normals\n"); // for(int i = 0; i < geo->numVertices; i++){ // float *nx = extranormals+i*3; // float *n = geo->morphTargets[0].normals; // float len = n[0]*n[0] + n[1]*n[1] + n[2]*n[2]; // printf("%f %f %f %f\n", n[0], n[1], n[2], len); // printf("%f %f %f\n", nx[0], nx[1], nx[2]); // } } static void writeExtraNormals(Stream *stream, int32, void *object, int32 offset, int32) { Geometry *geo = (Geometry*)object; float *extranormals = *PLUGINOFFSET(float*, object, offset); assert(extranormals != NULL); stream->write(extranormals, geo->numVertices*3*4); } static int32 getSizeExtraNormals(void *object, int32 offset, int32) { Geometry *geo = (Geometry*)object; if(*PLUGINOFFSET(float*, object, offset)) return geo->numVertices*3*4; return 0; } void registerExtraNormalsPlugin(void) { extraNormalsOffset = Geometry::registerPlugin(sizeof(void*), ID_EXTRANORMALS, createExtraNormals, destroyExtraNormals, NULL); Geometry::registerPluginStream(ID_EXTRANORMALS, readExtraNormals, writeExtraNormals, getSizeExtraNormals); } // Extra colors 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) { ExtraVertColors *colordata = PLUGINOFFSET(ExtraVertColors, object, offset); colordata->nightColors = NULL; colordata->dayColors = NULL; colordata->balance = 0.0f; return object; } static void* destroyExtraVertColors(void *object, int32 offset, int32) { ExtraVertColors *colordata = PLUGINOFFSET(ExtraVertColors, object, offset); delete[] colordata->nightColors; delete[] colordata->dayColors; return object; } static void readExtraVertColors(Stream *stream, int32, void *object, int32 offset, int32) { uint32 hasData; ExtraVertColors *colordata = PLUGINOFFSET(ExtraVertColors, object, offset); hasData = stream->readU32(); if(!hasData) return; Geometry *geometry = (Geometry*)object; colordata->nightColors = new uint8[geometry->numVertices*4]; colordata->dayColors = new uint8[geometry->numVertices*4]; colordata->balance = 1.0f; stream->read(colordata->nightColors, geometry->numVertices*4); if(geometry->colors) memcpy(colordata->dayColors, geometry->colors, geometry->numVertices*4); } static void writeExtraVertColors(Stream *stream, int32, void *object, int32 offset, int32) { ExtraVertColors *colordata = PLUGINOFFSET(ExtraVertColors, object, offset); stream->writeU32(colordata->nightColors != NULL); if(colordata->nightColors){ Geometry *geometry = (Geometry*)object; stream->write(colordata->nightColors, geometry->numVertices*4); } } static int32 getSizeExtraVertColors(void *object, int32 offset, int32) { ExtraVertColors *colordata = PLUGINOFFSET(ExtraVertColors, object, offset); Geometry *geometry = (Geometry*)object; if(colordata->nightColors) return 4 + geometry->numVertices*4; return 0; } void registerExtraVertColorPlugin(void) { extraVertColorOffset = Geometry::registerPlugin(sizeof(ExtraVertColors), ID_EXTRAVERTCOLORS, createExtraVertColors, destroyExtraVertColors, NULL); Geometry::registerPluginStream(ID_EXTRAVERTCOLORS, readExtraVertColors, writeExtraVertColors, getSizeExtraVertColors); } // Environment mat int32 envMatOffset; static void* createEnvMat(void *object, int32 offset, int32) { *PLUGINOFFSET(EnvMat*, object, offset) = NULL; return object; } static void* destroyEnvMat(void *object, int32 offset, int32) { EnvMat **envmat = PLUGINOFFSET(EnvMat*, object, offset); delete *envmat; *envmat = NULL; return object; } static void* copyEnvMat(void *dst, void *src, int32 offset, int32) { EnvMat *srcenv = *PLUGINOFFSET(EnvMat*, src, offset); if(srcenv == NULL) return dst; EnvMat *dstenv = new EnvMat; dstenv->scaleX = srcenv->scaleX; dstenv->scaleY = srcenv->scaleY; dstenv->transScaleX = srcenv->transScaleX; dstenv->transScaleY = srcenv->transScaleY; dstenv->shininess = srcenv->shininess; dstenv->texture = NULL; *PLUGINOFFSET(EnvMat*, dst, offset) = dstenv; return dst; } struct EnvStream { float scaleX, scaleY; float transScaleX, transScaleY; float shininess; int32 zero; }; static void readEnvMat(Stream *stream, int32, void *object, int32 offset, int32) { EnvStream buf; EnvMat *env = new EnvMat; *PLUGINOFFSET(EnvMat*, object, offset) = env; stream->read(&buf, sizeof(buf)); env->scaleX = (int8)(buf.scaleX*8.0f); env->scaleY = (int8)(buf.scaleY*8.0f); env->transScaleX = (int8)(buf.transScaleX*8.0f); env->transScaleY = (int8)(buf.transScaleY*8.0f); env->shininess = (int8)(buf.shininess*255.0f); env->texture = NULL; } static void writeEnvMat(Stream *stream, int32, void *object, int32 offset, int32) { EnvStream buf; EnvMat *env = *PLUGINOFFSET(EnvMat*, object, offset); buf.scaleX = env->scaleX/8.0f; buf.scaleY = env->scaleY/8.0f; buf.transScaleX = env->transScaleX/8.0f; buf.transScaleY = env->transScaleY/8.0f; buf.shininess = env->shininess/8.0f; buf.zero = 0; stream->write(&buf, sizeof(buf)); } static int32 getSizeEnvMat(void *object, int32 offset, int32) { EnvMat *env = *PLUGINOFFSET(EnvMat*, object, offset); return env ? (int)sizeof(EnvStream) : 0; } // Specular mat int32 specMatOffset; static void* createSpecMat(void *object, int32 offset, int32) { *PLUGINOFFSET(SpecMat*, object, offset) = NULL; return object; } static void* destroySpecMat(void *object, int32 offset, int32) { SpecMat **specmat = PLUGINOFFSET(SpecMat*, object, offset); if(*specmat == NULL) return object; if((*specmat)->texture) (*specmat)->texture->destroy(); delete *specmat; *specmat = NULL; return object; } static void* copySpecMat(void *dst, void *src, int32 offset, int32) { SpecMat *srcspec = *PLUGINOFFSET(SpecMat*, src, offset); if(srcspec == NULL) return dst; SpecMat *dstspec = new SpecMat; *PLUGINOFFSET(SpecMat*, dst, offset) = dstspec; dstspec->specularity = srcspec->specularity; dstspec->texture = srcspec->texture; dstspec->texture->refCount++; return dst; } struct SpecStream { float specularity; char texname[24]; }; static void readSpecMat(Stream *stream, int32, void *object, int32 offset, int32) { SpecStream buf; SpecMat *spec = new SpecMat; *PLUGINOFFSET(SpecMat*, object, offset) = spec; stream->read(&buf, sizeof(buf)); spec->specularity = buf.specularity; spec->texture = Texture::create(NULL); strncpy(spec->texture->name, buf.texname, 24); } static void writeSpecMat(Stream *stream, int32, void *object, int32 offset, int32) { SpecStream buf; SpecMat *spec = *PLUGINOFFSET(SpecMat*, object, offset); buf.specularity = spec->specularity; strncpy(buf.texname, spec->texture->name, 24); stream->write(&buf, sizeof(buf)); } static int32 getSizeSpecMat(void *object, int32 offset, int32) { SpecMat *spec = *PLUGINOFFSET(SpecMat*, object, offset); return spec ? (int)sizeof(SpecStream) : 0; } void registerEnvSpecPlugin(void) { envMatOffset = Material::registerPlugin(sizeof(EnvMat*), ID_ENVMAT, createEnvMat, destroyEnvMat, copyEnvMat); Material::registerPluginStream(ID_ENVMAT, readEnvMat, writeEnvMat, getSizeEnvMat); specMatOffset = Material::registerPlugin(sizeof(SpecMat*), ID_SPECMAT, createSpecMat, destroySpecMat, copySpecMat); Material::registerPluginStream(ID_SPECMAT, readSpecMat, writeSpecMat, getSizeSpecMat); } // Pipeline int32 pipelineOffset; static void* createPipeline(void *object, int32 offset, int32) { *PLUGINOFFSET(uint32, object, offset) = 0; return object; } static void* copyPipeline(void *dst, void *src, int32 offset, int32) { *PLUGINOFFSET(uint32, dst, offset) = *PLUGINOFFSET(uint32, src, offset); return dst; } static void readPipeline(Stream *stream, int32, void *object, int32 offset, int32) { *PLUGINOFFSET(uint32, object, offset) = stream->readU32(); // printf("%x\n", *PLUGINOFFSET(uint32, object, offset)); } static void writePipeline(Stream *stream, int32, void *object, int32 offset, int32) { stream->writeU32(*PLUGINOFFSET(uint32, object, offset)); } static int32 getSizePipeline(void *object, int32 offset, int32) { if(*PLUGINOFFSET(uint32, object, offset)) return 4; return 0; } void registerPipelinePlugin(void) { pipelineOffset = Atomic::registerPlugin(sizeof(uint32), ID_PIPELINE, createPipeline, NULL, copyPipeline); Atomic::registerPluginStream(ID_PIPELINE, readPipeline, writePipeline, getSizePipeline); } uint32 getPipelineID(Atomic *atomic) { return *PLUGINOFFSET(uint32, atomic, pipelineOffset); } void setPipelineID(Atomic *atomic, uint32 id) { *PLUGINOFFSET(uint32, atomic, pipelineOffset) = id; } // 2dEffect struct SizedData { uint32 size; uint8 *data; }; int32 twodEffectOffset; static void* create2dEffect(void *object, int32 offset, int32) { SizedData *data; data = PLUGINOFFSET(SizedData, object, offset); data->size = 0; data->data = NULL; return object; } static void* destroy2dEffect(void *object, int32 offset, int32) { SizedData *data; data = PLUGINOFFSET(SizedData, object, offset); delete[] data->data; data->data = NULL; data->size = 0; return object; } static void* copy2dEffect(void *dst, void *src, int32 offset, int32) { SizedData *srcdata, *dstdata; dstdata = PLUGINOFFSET(SizedData, dst, offset); srcdata = PLUGINOFFSET(SizedData, src, offset); dstdata->size = srcdata->size; if(dstdata->size != 0){ dstdata->data = new uint8[dstdata->size]; memcpy(dstdata->data, srcdata->data, dstdata->size); } return dst; } static void read2dEffect(Stream *stream, int32 size, void *object, int32 offset, int32) { SizedData *data = PLUGINOFFSET(SizedData, object, offset); data->size = size; data->data = new uint8[data->size]; stream->read(data->data, data->size); } static void write2dEffect(Stream *stream, int32, void *object, int32 offset, int32) { SizedData *data = PLUGINOFFSET(SizedData, object, offset); stream->write(data->data, data->size); } static int32 getSize2dEffect(void *object, int32 offset, int32) { SizedData *data = PLUGINOFFSET(SizedData, object, offset); return data->size; } void register2dEffectPlugin(void) { twodEffectOffset = Geometry::registerPlugin(sizeof(SizedData), ID_2DEFFECT, create2dEffect, destroy2dEffect, copy2dEffect); Geometry::registerPluginStream(ID_2DEFFECT, read2dEffect, write2dEffect, getSize2dEffect); } // Collision int32 collisionOffset; static void* createCollision(void *object, int32 offset, int32) { SizedData *data; data = PLUGINOFFSET(SizedData, object, offset); data->size = 0; data->data = NULL; return object; } static void* destroyCollision(void *object, int32 offset, int32) { SizedData *data; data = PLUGINOFFSET(SizedData, object, offset); delete[] data->data; data->data = NULL; data->size = 0; return object; } static void* copyCollision(void *dst, void *src, int32 offset, int32) { SizedData *srcdata, *dstdata; dstdata = PLUGINOFFSET(SizedData, dst, offset); srcdata = PLUGINOFFSET(SizedData, src, offset); dstdata->size = srcdata->size; if(dstdata->size != 0){ dstdata->data = new uint8[dstdata->size]; memcpy(dstdata->data, srcdata->data, dstdata->size); } return dst; } static void readCollision(Stream *stream, int32 size, void *object, int32 offset, int32) { SizedData *data = PLUGINOFFSET(SizedData, object, offset); data->size = size; data->data = new uint8[data->size]; stream->read(data->data, data->size); } static void writeCollision(Stream *stream, int32, void *object, int32 offset, int32) { SizedData *data = PLUGINOFFSET(SizedData, object, offset); stream->write(data->data, data->size); } static int32 getSizeCollision(void *object, int32 offset, int32) { SizedData *data = PLUGINOFFSET(SizedData, object, offset); return data->size; } void registerCollisionPlugin(void) { collisionOffset = Clump::registerPlugin(sizeof(SizedData), ID_COLLISION, createCollision, destroyCollision, copyCollision); Clump::registerPluginStream(ID_COLLISION, readCollision, writeCollision, getSizeCollision); } /* * PS2 */ using namespace ps2; rw::PipeAttribute saXYZADC = { "saXYZADC", AT_V4_16 | AT_RW }; rw::PipeAttribute saUV = { "saUV", AT_V2_16 | AT_RW }; rw::PipeAttribute saUV2 = { "saUV2", AT_V4_16 | AT_RW }; rw::PipeAttribute saRGBA = { "saRGBA", AT_V4_8 | AT_UNSGN | AT_RW }; rw::PipeAttribute saRGBA2 = { "saRGBA2", AT_V4_16 | AT_UNSGN | AT_RW }; rw::PipeAttribute saNormal = { "saNormal", AT_V4_8 | AT_RW }; 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 : ps2::Vertex { float32 w[4]; uint8 i[4]; float32 t1[2]; uint8 c1[4]; }; static void saPreCB(MatPipeline *p, Geometry *geo) { 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->c[0] && cols0[1] == v->c[1] && cols0[2] == v->c[2] && cols0[3] == v->c[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->t[0] && tex0[1] == v->t[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); if(mask & 0x2000) memcpy(&geo->texCoords[1][i*2], v->t1, 8); 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.c[0] = colors[0]; v.c[1] = colors[2]; v.c[2] = colors[4]; v.c[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.c[0] = colors[0]; v.c[1] = colors[1]; v.c[2] = colors[2]; v.c[3] = colors[3]; } if(mask & 0x1000){ v.t[0] = texcoords[0]/4096.0f; v.t[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 instanceSAPositions(Geometry *g, Mesh *m, int8 *adc, int16 *dst, float32 scale) { float32 *verts = g->morphTargets[0].vertices; uint16 j; for(uint32 i = 0; i < m->numIndices; i++){ j = m->indices[i]; dst[0] = verts[j*3+0]*scale; dst[1] = verts[j*3+1]*scale; dst[2] = verts[j*3+2]*scale; dst[3] = adc ? 0x8000*adc[i] : 0; dst += 4; } } static void instanceSATex(Geometry *g, Mesh *m, int16 *dst) { float32 *tex = g->texCoords[0]; uint16 j; for(uint32 i = 0; i < m->numIndices; i++){ j = m->indices[i]; if(tex){ dst[0] = tex[j*2+0]*4096.0f; dst[1] = tex[j*2+1]*4096.0f; }else{ dst[0] = 0; dst[1] = 0; } dst += 2; } } static void instanceSADualTex(Geometry *g, Mesh *m, int16 *dst) { float32 *tex0 = g->texCoords[0]; float32 *tex1 = g->texCoords[1]; uint16 j; for(uint32 i = 0; i < m->numIndices; i++){ j = m->indices[i]; if(tex0){ dst[0] = tex0[j*2+0]*4096.0f; dst[1] = tex0[j*2+1]*4096.0f; }else{ dst[0] = 0; dst[1] = 0; } if(tex1){ dst[2] = tex1[j*2+0]*4096.0f; dst[3] = tex1[j*2+1]*4096.0f; }else{ dst[2] = 0; dst[3] = 0; } dst += 4; } } static void instanceSAColors(Geometry *g, Mesh *m, uint8 *dst) { uint8 *c = g->colors; uint16 j; for(uint32 i = 0; i < m->numIndices; i++){ j = m->indices[i]; if(c) memcpy(dst, &c[j*4], 4); else memset(dst, 0xFF, 4); dst += 4; } } static void instanceSADualColors(Geometry *g, Mesh *m, uint8 *dst) { uint8 *c0 = g->colors; uint8 *c1 = PLUGINOFFSET(ExtraVertColors, g, extraVertColorOffset)->nightColors; uint16 j; for(uint32 i = 0; i < m->numIndices; i++){ j = m->indices[i]; if(c0){ dst[0] = c0[j*4+0]; dst[2] = c0[j*4+1]; dst[4] = c0[j*4+2]; dst[6] = c0[j*4+3]; }else{ dst[0] = 0xFF; dst[2] = 0xFF; dst[4] = 0xFF; dst[6] = 0xFF; } if(c1){ dst[1] = c1[j*4+0]; dst[3] = c1[j*4+1]; dst[6] = c1[j*4+2]; dst[7] = c1[j*4+3]; }else{ dst[1] = 0xFF; dst[3] = 0xFF; dst[6] = 0xFF; dst[7] = 0xFF; } dst += 8; } } static void instanceSANormals(Geometry *g, Mesh *m, int8 *dst) { float32 *norms = g->morphTargets[0].normals; uint16 j; for(uint32 i = 0; i < m->numIndices; i++){ j = m->indices[i]; if(norms){ dst[0] = norms[j*3+0]*127.0f; dst[1] = norms[j*3+1]*127.0f; dst[2] = norms[j*3+2]*127.0f; dst[3] = 0; }else memset(dst, 0, 4); dst += 4; } } static void saInstanceCB(MatPipeline *pipe, Geometry *g, Mesh *m, uint8 **data) { uint32 id = pipe->pluginData; float vertScale = 128.0f; if(id == 0x53f20085 || id == 0x53f20087 || id == 0x53f20089 || id == 0x53f2008b) vertScale = 1024.0f; ADCData *adc = PLUGINOFFSET(ADCData, g, adcOffset); for(uint32 i = 0; i < nelem(pipe->attribs); i++){ rw::PipeAttribute *a = pipe->attribs[i]; if(a == &saXYZADC) instanceSAPositions(g, m, adc->adcFormatted ? adc->adcBits : NULL, (int16*)data[i], vertScale); if(a == &saUV) instanceSATex(g, m, (int16*)data[i]); if(a == &saUV2) instanceSADualTex(g, m, (int16*)data[i]); if(a == &saRGBA) instanceSAColors(g, m, (uint8*)data[i]); if(a == &saRGBA2) instanceSADualColors(g, m, (uint8*)data[i]); if(a == &saNormal) instanceSANormals(g, m, (int8*)data[i]); if(a == &saWeights){ Skin *skin = *PLUGINOFFSET(Skin*, g, skinGlobals.offset); instanceSkinData(g, m, skin, (uint32*)data[i]); } } } 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); } }