diff --git a/README.md b/README.md index 70c0efa..f20ae75 100644 --- a/README.md +++ b/README.md @@ -13,14 +13,7 @@ File formats are already supported rather well, although rasters as used by TXD files still need some work, especially for PS2. As for rendering, D3D9 and OpenGL 3 work somewhat well but both still need -work. Rendering some things on the PS2 worked in the past but the code -is not maintained, it was only a test. - -# Roadmap - -* Work on platform independent rendering functions (setting render states etc.) - -* Get a solid GL3 driver working +work. Rendering some things on the PS2 is working as a test only. # Building diff --git a/TODO b/TODO index a533ce0..9df3fd0 100644 --- a/TODO +++ b/TODO @@ -1,7 +1,11 @@ TODO: - maintain the TODO list properly -- skeleton +- get the error system in better shape +- move everything to custom malloc +- proper cleanup! and check for memory leaks +- skeleton (partially done) - examples +- morph targets and morphing - geometry lock/unlock -> reinstance -> revisit pipelines @@ -13,16 +17,13 @@ TODO: - PS2 rendering! - Im2d and Im3d - change naming convention? make globals stand out more +- Pipelines (PDS, Xbox, PC) +- ADC conversion BUGS: - fseek with negative offset on ps2 over ps2link messes up the current position Clump & related: - - !!! work on ref counts, destruction, copying etc. - - define and use types: - color - triangle - texcoord - implement plugins: Clump Animation (old III dffs) @@ -37,7 +38,3 @@ Clump & related: - only stubs: R* 2dfx 0x253F2F8 R* Collision 0x253F2FA - -- Pipelines (PDS, Xbox, PC) - -- ADC conversion diff --git a/src/base.cpp b/src/base.cpp index 838a780..0dfccf7 100755 --- a/src/base.cpp +++ b/src/base.cpp @@ -863,7 +863,7 @@ getFileContents(char *name, uint32 *len) fseek(cf, 0, SEEK_END); *len = ftell(cf); fseek(cf, 0, SEEK_SET); - uint8 *data = new uint8[*len]; + uint8 *data = rwNewT(uint8, *len, MEMDUR_EVENT); fread(data, *len, 1, cf); fclose(cf); return data; diff --git a/src/d3d/d3d.cpp b/src/d3d/d3d.cpp index 49d7b5e..c12f52b 100644 --- a/src/d3d/d3d.cpp +++ b/src/d3d/d3d.cpp @@ -187,7 +187,7 @@ createIndexBuffer(uint32 length) d3ddevice->CreateIndexBuffer(length, D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_MANAGED, &ibuf, 0); return ibuf; #else - return new uint8[length]; + return rwNewT(uint8, length, MEMDUR_EVENT | ID_DRIVER); #endif } @@ -230,7 +230,7 @@ createVertexBuffer(uint32 length, uint32 fvf, int32 pool) #else (void)fvf; (void)pool; - return new uint8[length]; + return rwNewT(uint8, length, MEMDUR_EVENT | ID_DRIVER); #endif } @@ -282,7 +282,8 @@ createTexture(int32 width, int32 height, int32 numlevels, uint32 format) h /= 2; if(h == 0) h = 1; } - uint8 *data = new uint8[sizeof(RasterLevels)+sizeof(RasterLevels::Level)*(numlevels-1)+size]; + uint8 *data = (uint8*)rwNew(sizeof(RasterLevels)+sizeof(RasterLevels::Level)*(numlevels-1)+size, + MEMDUR_EVENT | ID_DRIVER); RasterLevels *levels = (RasterLevels*)data; data += sizeof(RasterLevels)+sizeof(RasterLevels::Level)*(numlevels-1); levels->numlevels = numlevels; @@ -338,7 +339,7 @@ deleteObject(void *object) IUnknown *unk = (IUnknown*)object; unk->Release(); #else - delete[] (uint*)object; + rwFree(object); #endif } @@ -379,7 +380,7 @@ rasterCreate(Raster *raster) uint32 format; if(raster->format & (Raster::PAL4 | Raster::PAL8)){ format = D3DFMT_P8; - natras->palette = new uint8[4*256]; + natras->palette = (uint8*)rwNew(4*256, MEMDUR_EVENT | ID_DRIVER); }else format = formatMap[(raster->format >> 8) & 0xF]; natras->format = 0; diff --git a/src/d3d/d3d8.cpp b/src/d3d/d3d8.cpp index 2404b8a..265dad3 100644 --- a/src/d3d/d3d8.cpp +++ b/src/d3d/d3d8.cpp @@ -91,8 +91,8 @@ destroyNativeData(void *object, int32, int32) deleteObject(inst->vertexBuffer); inst++; } - delete[] header->inst; - delete header; + rwFree(header->inst); + rwFree(header); return object; } @@ -110,17 +110,17 @@ readNativeData(Stream *stream, int32, void *object, int32, int32) RWERROR((ERR_PLATFORM, platform)); return nil; } - InstanceDataHeader *header = new InstanceDataHeader; + InstanceDataHeader *header = rwNewT(InstanceDataHeader, 1, MEMDUR_EVENT | ID_GEOMETRY); geometry->instData = header; header->platform = PLATFORM_D3D8; int32 size = stream->readI32(); - uint8 *data = new uint8[size]; + uint8 *data = rwNewT(uint8, size, MEMDUR_FUNCTION | ID_GEOMETRY); stream->read(data, size); uint8 *p = data; header->serialNumber = *(uint16*)p; p += 2; header->numMeshes = *(uint16*)p; p += 2; - header->inst = new InstanceData[header->numMeshes]; + header->inst = rwNewT(InstanceData, header->numMeshes, MEMDUR_EVENT | ID_GEOMETRY); InstanceData *inst = header->inst; for(uint32 i = 0; i < header->numMeshes; i++){ @@ -140,7 +140,7 @@ readNativeData(Stream *stream, int32, void *object, int32, int32) inst->remapped = 0; p++; // TODO: really unused? and what's that anyway? inst++; } - delete[] data; + rwFree(data); inst = header->inst; for(uint32 i = 0; i < header->numMeshes; i++){ @@ -172,7 +172,7 @@ writeNativeData(Stream *stream, int32 len, void *object, int32, int32) InstanceDataHeader *header = (InstanceDataHeader*)geometry->instData; int32 size = 4 + geometry->meshHeader->numMeshes*0x2C; - uint8 *data = new uint8[size]; + uint8 *data = rwNewT(uint8, size, MEMDUR_FUNCTION | ID_GEOMETRY); stream->writeI32(size); uint8 *p = data; *(uint16*)p = header->serialNumber; p += 2; @@ -197,7 +197,7 @@ writeNativeData(Stream *stream, int32 len, void *object, int32, int32) inst++; } stream->write(data, size); - delete[] data; + rwFree(data); inst = header->inst; for(uint32 i = 0; i < header->numMeshes; i++){ @@ -251,17 +251,17 @@ instance(rw::ObjPipeline *rwpipe, Atomic *atomic) // TODO: allow for REINSTANCE if(geo->instData) return; - InstanceDataHeader *header = new InstanceDataHeader; + InstanceDataHeader *header = rwNewT(InstanceDataHeader, 1, MEMDUR_EVENT | ID_GEOMETRY); MeshHeader *meshh = geo->meshHeader; geo->instData = header; header->platform = PLATFORM_D3D8; header->serialNumber = 0; header->numMeshes = meshh->numMeshes; - header->inst = new InstanceData[header->numMeshes]; + header->inst = rwNewT(InstanceData, header->numMeshes, MEMDUR_EVENT | ID_GEOMETRY); InstanceData *inst = header->inst; - Mesh *mesh = meshh->mesh; + Mesh *mesh = meshh->getMeshes(); for(uint32 i = 0; i < header->numMeshes; i++){ findMinVertAndNumVertices(mesh->indices, mesh->numIndices, &inst->minVert, &inst->numVertices); @@ -299,13 +299,13 @@ uninstance(rw::ObjPipeline *rwpipe, Atomic *atomic) return; assert(geo->instData != nil); assert(geo->instData->platform == PLATFORM_D3D8); - geo->flags &= ~Geometry::NATIVE; + geo->numTriangles = geo->meshHeader->guessNumTriangles(); geo->allocateData(); - geo->meshHeader->allocateIndices(); + geo->allocateMeshes(geo->meshHeader->numMeshes, geo->meshHeader->totalIndices, 0); InstanceDataHeader *header = (InstanceDataHeader*)geo->instData; InstanceData *inst = header->inst; - Mesh *mesh = geo->meshHeader->mesh; + Mesh *mesh = geo->meshHeader->getMeshes(); for(uint32 i = 0; i < header->numMeshes; i++){ uint16 *indices = lockIndices(inst->indexBuffer, 0, 0, 0); if(inst->minVert == 0) @@ -320,6 +320,7 @@ uninstance(rw::ObjPipeline *rwpipe, Atomic *atomic) inst++; } geo->generateTriangles(); + geo->flags &= ~Geometry::NATIVE; destroyNativeData(geo, 0, 0); } @@ -448,7 +449,7 @@ readAsImage(Stream *stream, int32 width, int32 height, int32 depth, int32 format for(int32 i = 0; i < numLevels; i++){ uint32 size = stream->readU32(); if(i == 0){ - data = new uint8[size]; + data = rwNewT(uint8, size, MEMDUR_FUNCTION | ID_IMAGE); stream->read(data, size); }else stream->seek(size); @@ -471,7 +472,7 @@ readAsImage(Stream *stream, int32 width, int32 height, int32 depth, int32 format } } - delete[] data; + rwFree(data); Raster *ras = Raster::createFromImage(img, PLATFORM_D3D8); img->destroy(); return ras; diff --git a/src/d3d/d3d9.cpp b/src/d3d/d3d9.cpp index 9e9f9c4..9e15456 100644 --- a/src/d3d/d3d9.cpp +++ b/src/d3d/d3d9.cpp @@ -71,7 +71,7 @@ createVertexDeclaration(VertexElement *elements) VertexElement *e = (VertexElement*)elements; while(e[n++].stream != 0xFF) ; - e = (VertexElement*)new uint8[n*sizeof(VertexElement)]; + e = rwNewT(VertexElement, n, MEMDUR_EVENT | ID_DRIVER); memcpy(e, elements, n*sizeof(VertexElement)); return e; #endif @@ -111,8 +111,8 @@ destroyNativeData(void *object, int32, int32) deleteObject(header->indexBuffer); deleteObject(header->vertexStream[0].vertexBuffer); deleteObject(header->vertexStream[1].vertexBuffer); - delete[] header->inst; - delete header; + rwFree(header->inst); + rwFree(header); return object; } @@ -130,12 +130,12 @@ readNativeData(Stream *stream, int32, void *object, int32, int32) RWERROR((ERR_PLATFORM, platform)); return nil; } - InstanceDataHeader *header = new InstanceDataHeader; + InstanceDataHeader *header = rwNewT(InstanceDataHeader, 1, MEMDUR_EVENT | ID_GEOMETRY); geometry->instData = header; header->platform = PLATFORM_D3D9; int32 size = stream->readI32(); - uint8 *data = new uint8[size]; + uint8 *data = rwNewT(uint8, size, MEMDUR_FUNCTION | ID_GEOMETRY); stream->read(data, size); uint8 *p = data; header->serialNumber = *(uint32*)p; p += 4; @@ -147,7 +147,7 @@ readNativeData(Stream *stream, int32, void *object, int32, int32) header->vertexDeclaration = nil; p += 4; header->totalNumIndex = *(uint32*)p; p += 4; header->totalNumVertex = *(uint32*)p; p += 4; - header->inst = new InstanceData[header->numMeshes]; + header->inst = rwNewT(InstanceData, header->numMeshes, MEMDUR_EVENT | ID_GEOMETRY); InstanceData *inst = header->inst; for(uint32 i = 0; i < header->numMeshes; i++){ @@ -203,7 +203,7 @@ readNativeData(Stream *stream, int32, void *object, int32, int32) inst++; } - delete[] data; + rwFree(data); return stream; } @@ -218,7 +218,7 @@ writeNativeData(Stream *stream, int32 len, void *object, int32, int32) stream->writeU32(PLATFORM_D3D9); InstanceDataHeader *header = (InstanceDataHeader*)geometry->instData; int32 size = 64 + geometry->meshHeader->numMeshes*36; - uint8 *data = new uint8[size]; + uint8 *data = rwNewT(uint8, size, MEMDUR_FUNCTION | ID_GEOMETRY); stream->writeI32(size); uint8 *p = data; @@ -276,7 +276,7 @@ writeNativeData(Stream *stream, int32 len, void *object, int32, int32) unlockVertices(s->vertexBuffer); } - delete[] data; + rwFree(data); return stream; } @@ -316,7 +316,7 @@ instance(rw::ObjPipeline *rwpipe, Atomic *atomic) // TODO: allow for REINSTANCE if(geo->instData) return; - InstanceDataHeader *header = new InstanceDataHeader; + InstanceDataHeader *header = rwNewT(InstanceDataHeader, 1, MEMDUR_EVENT | ID_GEOMETRY); MeshHeader *meshh = geo->meshHeader; geo->instData = header; header->platform = PLATFORM_D3D9; @@ -327,13 +327,13 @@ instance(rw::ObjPipeline *rwpipe, Atomic *atomic) header->useOffsets = 0; header->totalNumVertex = geo->numVertices; header->totalNumIndex = meshh->totalIndices; - header->inst = new InstanceData[header->numMeshes]; + header->inst = rwNewT(InstanceData, header->numMeshes, MEMDUR_EVENT | ID_GEOMETRY); header->indexBuffer = createIndexBuffer(header->totalNumIndex*2); uint16 *indices = lockIndices(header->indexBuffer, 0, 0, 0); InstanceData *inst = header->inst; - Mesh *mesh = meshh->mesh; + Mesh *mesh = meshh->getMeshes(); uint32 startindex = 0; for(uint32 i = 0; i < header->numMeshes; i++){ findMinVertAndNumVertices(mesh->indices, mesh->numIndices, @@ -370,14 +370,14 @@ uninstance(rw::ObjPipeline *rwpipe, Atomic *atomic) return; assert(geo->instData != nil); assert(geo->instData->platform == PLATFORM_D3D9); - geo->flags &= ~Geometry::NATIVE; + geo->numTriangles = geo->meshHeader->guessNumTriangles(); geo->allocateData(); - geo->meshHeader->allocateIndices(); + geo->allocateMeshes(geo->meshHeader->numMeshes, geo->meshHeader->totalIndices, 0); InstanceDataHeader *header = (InstanceDataHeader*)geo->instData; uint16 *indices = lockIndices(header->indexBuffer, 0, 0, 0); InstanceData *inst = header->inst; - Mesh *mesh = geo->meshHeader->mesh; + Mesh *mesh = geo->meshHeader->getMeshes(); for(uint32 i = 0; i < header->numMeshes; i++){ if(inst->minVert == 0) memcpy(mesh->indices, &indices[inst->startIndex], inst->numIndex*2); @@ -391,6 +391,7 @@ uninstance(rw::ObjPipeline *rwpipe, Atomic *atomic) pipe->uninstanceCB(geo, header); geo->generateTriangles(); + geo->flags &= ~Geometry::NATIVE; destroyNativeData(geo, 0, 0); } diff --git a/src/d3d/xbox.cpp b/src/d3d/xbox.cpp index 8994f43..6bfc33b 100644 --- a/src/d3d/xbox.cpp +++ b/src/d3d/xbox.cpp @@ -57,10 +57,10 @@ destroyNativeData(void *object, int32, int32) InstanceDataHeader *header = (InstanceDataHeader*)geometry->instData; geometry->instData = nil; - delete[] (uint8*)header->vertexBuffer; - delete[] header->begin; - delete[] header->data; - delete header; + rwFree(header->vertexBuffer); + rwFree(header->begin); + rwFree(header->data); + rwFree(header); return object; } @@ -83,14 +83,14 @@ readNativeData(Stream *stream, int32, void *object, int32, int32) RWERROR((ERR_VERSION, vers)); return nil; } - InstanceDataHeader *header = new InstanceDataHeader; + InstanceDataHeader *header = rwNewT(InstanceDataHeader, 1, MEMDUR_EVENT | ID_GEOMETRY); geometry->instData = header; header->platform = PLATFORM_XBOX; int32 size = stream->readI32(); // The 0x18 byte are the resentryheader. // We don't have it but it's used for alignment. - header->data = new uint8[size + 0x18]; + header->data = rwNewT(uint8, size + 0x18, MEMDUR_EVENT | ID_GEOMETRY); uint8 *p = header->data+0x18+4; stream->read(p, size-4); @@ -105,7 +105,7 @@ readNativeData(Stream *stream, int32, void *object, int32, int32) header->vertexAlpha = *(bool32*)p; p += 4; p += 8; // skip begin, end pointers - InstanceData *inst = new InstanceData[header->numMeshes]; + InstanceData *inst = rwNewT(InstanceData, header->numMeshes, MEMDUR_EVENT | ID_GEOMETRY); header->begin = inst; for(int i = 0; i < header->numMeshes; i++){ inst->minVert = *(uint32*)p; p += 4; @@ -119,7 +119,7 @@ readNativeData(Stream *stream, int32, void *object, int32, int32) } header->end = inst; - header->vertexBuffer = new uint8[header->stride*header->numVertices]; + header->vertexBuffer = rwNewT(uint8, header->stride*header->numVertices, MEMDUR_EVENT | ID_GEOMETRY); stream->read(header->vertexBuffer, header->stride*header->numVertices); return stream; } @@ -200,18 +200,18 @@ instance(rw::ObjPipeline *rwpipe, Atomic *atomic) // TODO: allow for REINSTANCE (or not, xbox can't render) if(geo->instData) return; - InstanceDataHeader *header = new InstanceDataHeader; + InstanceDataHeader *header = rwNewT(InstanceDataHeader, 1, MEMDUR_EVENT | ID_GEOMETRY); MeshHeader *meshh = geo->meshHeader; geo->instData = header; header->platform = PLATFORM_XBOX; header->size = 0x24 + meshh->numMeshes*0x18 + 0x10; - Mesh *mesh = meshh->mesh; + Mesh *mesh = meshh->getMeshes(); for(uint32 i = 0; i < meshh->numMeshes; i++) header->size += (mesh++->numIndices*2 + 0xF) & ~0xF; // The 0x18 byte are the resentryheader. // We don't have it but it's used for alignment. - header->data = new uint8[header->size + 0x18]; + header->data = rwNewT(uint8, header->size + 0x18, MEMDUR_EVENT | ID_GEOMETRY); header->serialNumber = 0; header->numMeshes = meshh->numMeshes; header->primType = meshh->flags == 1 ? D3DPT_TRIANGLESTRIP : D3DPT_TRIANGLELIST; @@ -221,9 +221,9 @@ instance(rw::ObjPipeline *rwpipe, Atomic *atomic) header->stride = 0; header->vertexBuffer = nil; - InstanceData *inst = new InstanceData[header->numMeshes]; + InstanceData *inst = rwNewT(InstanceData, header->numMeshes, MEMDUR_EVENT | ID_GEOMETRY); header->begin = inst; - mesh = meshh->mesh; + mesh = meshh->getMeshes(); uint8 *indexbuf = (uint8*)header->data + ((0x18 + 0x24 + header->numMeshes*0x18 + 0xF)&~0xF); for(uint32 i = 0; i < header->numMeshes; i++){ findMinVertAndNumVertices(mesh->indices, mesh->numIndices, @@ -251,13 +251,13 @@ uninstance(rw::ObjPipeline *rwpipe, Atomic *atomic) return; assert(geo->instData != nil); assert(geo->instData->platform == PLATFORM_XBOX); - geo->flags &= ~Geometry::NATIVE; + geo->numTriangles = geo->meshHeader->guessNumTriangles(); geo->allocateData(); - geo->meshHeader->allocateIndices(); + geo->allocateMeshes(geo->meshHeader->numMeshes, geo->meshHeader->totalIndices, 0); InstanceDataHeader *header = (InstanceDataHeader*)geo->instData; InstanceData *inst = header->begin; - Mesh *mesh = geo->meshHeader->mesh; + Mesh *mesh = geo->meshHeader->getMeshes(); for(uint32 i = 0; i < header->numMeshes; i++){ uint16 *indices = (uint16*)inst->indexBuffer; memcpy(mesh->indices, indices, inst->numIndices*2); @@ -267,6 +267,7 @@ uninstance(rw::ObjPipeline *rwpipe, Atomic *atomic) pipe->uninstanceCB(geo, header); geo->generateTriangles(); + geo->flags &= ~Geometry::NATIVE; destroyNativeData(geo, 0, 0); } @@ -295,7 +296,7 @@ defaultInstanceCB(Geometry *geo, InstanceDataHeader *header) if(*vertexFmt == 0) *vertexFmt = makeVertexFmt(geo->flags, geo->numTexCoordSets); header->stride = getVertexFmtStride(*vertexFmt); - header->vertexBuffer = new uint8[header->stride*header->numVertices]; + header->vertexBuffer = rwNewT(uint8, header->stride*header->numVertices, MEMDUR_EVENT | ID_GEOMETRY); uint8 *dst = (uint8*)header->vertexBuffer; uint32 fmt = *vertexFmt; @@ -476,7 +477,8 @@ createTexture(int32 width, int32 height, int32 numlevels, uint32 format) if(h == 0) h = 1; } size = (size+3)&~3; - uint8 *data = new uint8[sizeof(RasterLevels)+sizeof(RasterLevels::Level)*(numlevels-1)+size]; + uint8 *data = (uint8*)rwNew(sizeof(RasterLevels)+sizeof(RasterLevels::Level)*(numlevels-1)+size, + MEMDUR_EVENT | ID_DRIVER); RasterLevels *levels = (RasterLevels*)data; data += sizeof(RasterLevels)+sizeof(RasterLevels::Level)*(numlevels-1); levels->numlevels = numlevels; @@ -536,7 +538,7 @@ rasterCreate(Raster *raster) uint32 format; if(raster->format & (Raster::PAL4 | Raster::PAL8)){ format = D3DFMT_P8; - natras->palette = new uint8[4*256]; + natras->palette = (uint8*)rwNew(4*256, MEMDUR_EVENT | ID_DRIVER); }else format = formatMap[(raster->format >> 8) & 0xF]; natras->format = 0; diff --git a/src/d3d/xboxplugins.cpp b/src/d3d/xboxplugins.cpp index 8dc6eca..ae59de6 100644 --- a/src/d3d/xboxplugins.cpp +++ b/src/d3d/xboxplugins.cpp @@ -48,12 +48,12 @@ readNativeSkin(Stream *stream, int32, void *object, int32 offset) return nil; } - Skin *skin = new Skin; + Skin *skin = rwNewT(Skin, 1, MEMDUR_EVENT | ID_SKIN); *PLUGINOFFSET(Skin*, geometry, offset) = skin; int32 numBones = stream->readI32(); skin->init(numBones, 0, 0); - NativeSkin *natskin = new NativeSkin; + NativeSkin *natskin = rwNewT(NativeSkin, 1, MEMDUR_EVENT | ID_SKIN); skin->platformData = natskin; stream->read(natskin->table1, 256*sizeof(int32)); stream->read(natskin->table2, 256*sizeof(int32)); @@ -62,7 +62,7 @@ readNativeSkin(Stream *stream, int32, void *object, int32 offset) stream->seek(4); // skip pointer to vertexBuffer natskin->stride = stream->readI32(); int32 size = geometry->numVertices*natskin->stride; - natskin->vertexBuffer = new uint8[size]; + natskin->vertexBuffer = rwNewT(uint8, size, MEMDUR_EVENT | ID_SKIN); stream->read(natskin->vertexBuffer, size); stream->read(skin->inverseMatrices, skin->numBones*64); @@ -119,7 +119,7 @@ skinInstanceCB(Geometry *geo, InstanceDataHeader *header) Skin *skin = Skin::get(geo); if(skin == nil) return; - NativeSkin *natskin = new NativeSkin; + NativeSkin *natskin = rwNewT(NativeSkin, 1, MEMDUR_EVENT | ID_SKIN); skin->platformData = natskin; natskin->numUsedBones = skin->numUsedBones; @@ -131,7 +131,7 @@ skinInstanceCB(Geometry *geo, InstanceDataHeader *header) } natskin->stride = 3*skin->numWeights; - uint8 *vbuf = new uint8[header->numVertices*natskin->stride]; + uint8 *vbuf = rwNewT(uint8, header->numVertices*natskin->stride, MEMDUR_EVENT | ID_SKIN); natskin->vertexBuffer = vbuf; int32 w[4]; @@ -179,7 +179,7 @@ skinUninstanceCB(Geometry *geo, InstanceDataHeader *header) float *invMats = skin->inverseMatrices; skin->init(skin->numBones, natskin->numUsedBones, geo->numVertices); memcpy(skin->inverseMatrices, invMats, skin->numBones*64); - delete[] data; + rwFree(data); for(int32 j = 0; j < skin->numUsedBones; j++) skin->usedBones[j] = natskin->table1[j]; @@ -211,8 +211,8 @@ skinUninstanceCB(Geometry *geo, InstanceDataHeader *header) } } - delete[] (uint8*)natskin->vertexBuffer; - delete natskin; + rwFree(natskin->vertexBuffer); + rwFree(natskin); } static void* diff --git a/src/engine.cpp b/src/engine.cpp index 77fa22a..50ef83e 100755 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -18,6 +18,14 @@ #define PLUGIN_ID 0 +// on windows +//#ifdef DEBUG +//#include +//#define free(p) _free_dbg(p, _NORMAL_BLOCK); +//#define malloc(sz) _malloc_dbg(sz, _NORMAL_BLOCK, __FILE__, __LINE__) +//#define realloc(p, sz) _realloc_dbg(p, sz, _NORMAL_BLOCK, __FILE__, __LINE__) +//#endif + namespace rw { Engine *engine; @@ -25,8 +33,29 @@ PluginList Driver::s_plglist[NUM_PLATFORMS]; Engine::State Engine::state = Dead; MemoryFunctions Engine::memfuncs; -void *malloc_h(size_t sz, uint32 hint) { return malloc(sz); } +void *malloc_h(size_t sz, uint32 hint) { if(sz == 0) return nil; return malloc(sz); } void *realloc_h(void *p, size_t sz, uint32 hint) { return realloc(p, sz); } +// TODO: make the debug out configurable +void *mustmalloc_h(size_t sz, uint32 hint) +{ + void *ret; + ret = rwMalloc(sz, hint); + if(ret) + return ret; + fprintf(stderr, "Error: out of memory\n"); + exit(1); + return nil; +} +void *mustrealloc_h(void *p, size_t sz, uint32 hint) +{ + void *ret; + ret = rwRealloc(p, sz, hint); + if(ret) + return ret; + fprintf(stderr, "Error: out of memory\n"); + exit(1); + return nil; +} // This function mainly registers engine plugins // RW initializes memory related things here too and @@ -40,9 +69,11 @@ Engine::init(void) return 0; } - memfuncs.malloc = malloc_h; - memfuncs.realloc = realloc_h; - memfuncs.free = free; + memfuncs.rwmalloc = malloc_h; + memfuncs.rwrealloc = realloc_h; + memfuncs.rwfree = free; + memfuncs.rwmustmalloc = mustmalloc_h; + memfuncs.rwmustrealloc = mustrealloc_h; PluginList init = { sizeof(Driver), sizeof(Driver), nil, nil }; for(uint i = 0; i < NUM_PLATFORMS; i++) @@ -72,7 +103,7 @@ Engine::open(void) } // Allocate engine - engine = (Engine*)rwMalloc(sizeof(Engine), MEMDUR_GLOBAL); + engine = rwNewT(Engine, 1, MEMDUR_GLOBAL); engine->currentCamera = nil; engine->currentWorld = nil; engine->currentTexDictionary = nil; @@ -97,7 +128,8 @@ Engine::open(void) // TODO: init driver functions ObjPipeline *defpipe = new ObjPipeline(PLATFORM_NULL); for(uint i = 0; i < NUM_PLATFORMS; i++){ - rw::engine->driver[i] = (Driver*)malloc(Driver::s_plglist[i].size); + rw::engine->driver[i] = (Driver*)rwNew(Driver::s_plglist[i].size, + MEMDUR_GLOBAL); engine->driver[i]->defaultPipeline = defpipe; diff --git a/src/geometry.cpp b/src/geometry.cpp index 63f3d81..40835d2 100644 --- a/src/geometry.cpp +++ b/src/geometry.cpp @@ -18,9 +18,9 @@ namespace rw { PluginList Geometry::s_plglist = { sizeof(Geometry), sizeof(Geometry), nil, nil }; PluginList Material::s_plglist = { sizeof(Material), sizeof(Material), nil, nil }; -SurfaceProperties defaultSurfaceProps = { 1.0f, 1.0f, 1.0f }; +static SurfaceProperties defaultSurfaceProps = { 1.0f, 1.0f, 1.0f }; -// TODO: allocate everything in one chunk +// We allocate twice because we have to allocate the data separately for uninstancing Geometry* Geometry::create(int32 numVerts, int32 numTris, uint32 flags) { @@ -37,32 +37,41 @@ Geometry::create(int32 numVerts, int32 numTris, uint32 flags) (geo->flags & TEXTURED2) ? 2 : 0; geo->numTriangles = numTris; geo->numVertices = numVerts; - geo->numMorphTargets = 1; geo->colors = nil; - for(int32 i = 0; i < geo->numTexCoordSets; i++) + for(int32 i = 0; i < 8; i++) geo->texCoords[i] = nil; geo->triangles = nil; - if(!(geo->flags & NATIVE) && geo->numVertices){ + // Allocate all attributes at once. The triangle pointer + // will hold the first address (even when there are no triangles) + // so we can free easily. + if(!(geo->flags & NATIVE)){ + int32 sz = geo->numTriangles*sizeof(Triangle); if(geo->flags & PRELIT) - geo->colors = new RGBA[geo->numVertices]; - if((geo->flags & TEXTURED) || (geo->flags & TEXTURED2)) - for(int32 i = 0; i < geo->numTexCoordSets; i++) - geo->texCoords[i] = - new TexCoords[geo->numVertices]; - geo->triangles = new Triangle[geo->numTriangles]; - } - geo->morphTargets = new MorphTarget[1]; - MorphTarget *m = geo->morphTargets; - m->boundingSphere.center.set(0.0f, 0.0f, 0.0f); - m->boundingSphere.radius = 0.0f; - m->vertices = nil; - m->normals = nil; - if(!(geo->flags & NATIVE) && geo->numVertices){ - m->vertices = new V3d[geo->numVertices]; - if(geo->flags & NORMALS) - m->normals = new V3d[geo->numVertices]; + sz += geo->numVertices*sizeof(RGBA); + sz += geo->numTexCoordSets*geo->numVertices*sizeof(TexCoords); + + uint8 *data = (uint8*)rwNew(sz, MEMDUR_EVENT | ID_GEOMETRY); + geo->triangles = (Triangle*)data; + data += geo->numTriangles*sizeof(Triangle); + if(geo->flags & PRELIT && geo->numVertices){ + geo->colors = (RGBA*)data; + data += geo->numVertices*sizeof(RGBA); + } + if(geo->numVertices) + for(int32 i = 0; i < geo->numTexCoordSets; i++){ + geo->texCoords[i] = (TexCoords*)data; + data += geo->numVertices*sizeof(TexCoords); + } + + // init triangles + for(int32 i = 0; i < geo->numTriangles; i++) + geo->triangles[i].matId = 0xFFFF; } + geo->numMorphTargets = 0; + geo->morphTargets = nil; + geo->addMorphTargets(1); + geo->matList.init(); geo->meshHeader = nil; geo->instData = nil; @@ -78,18 +87,12 @@ Geometry::destroy(void) this->refCount--; if(this->refCount <= 0){ s_plglist.destruct(this); - delete[] this->colors; - for(int32 i = 0; i < this->numTexCoordSets; i++) - delete[] this->texCoords[i]; - delete[] this->triangles; - - for(int32 i = 0; i < this->numMorphTargets; i++){ - MorphTarget *m = &this->morphTargets[i]; - delete[] m->vertices; - delete[] m->normals; - } - delete[] this->morphTargets; - delete this->meshHeader; + // Also frees colors and tex coords + rwFree(this->triangles); + // Also frees their data + rwFree(this->morphTargets); + // Also frees indices + rwFree(this->meshHeader); this->matList.deinit(); rwFree(this); } @@ -158,6 +161,7 @@ Geometry::streamRead(Stream *stream) } if(version < 0x34000) defaultSurfaceProps = surfProps; + ret = MaterialList::streamRead(stream, &geo->matList); if(version < 0x34000) defaultSurfaceProps = reset; @@ -271,20 +275,52 @@ Geometry::addMorphTargets(int32 n) if(n == 0) return; n += this->numMorphTargets; - MorphTarget *morphTargets = new MorphTarget[n]; - memcpy(morphTargets, this->morphTargets, - this->numMorphTargets*sizeof(MorphTarget)); - delete[] this->morphTargets; - this->morphTargets = morphTargets; - for(int32 i = this->numMorphTargets; i < n; i++){ - MorphTarget *m = &morphTargets[i]; - m->vertices = nil; - m->normals = nil; - if(!(this->flags & NATIVE)){ - m->vertices = new V3d[this->numVertices]; - if(this->flags & NORMALS) - m->normals = new V3d[this->numVertices]; + + int32 sz; + sz = sizeof(MorphTarget); + if(!(this->flags & NATIVE)){ + sz += this->numVertices*sizeof(V3d); + if(this->flags & NORMALS) + sz += this->numVertices*sizeof(V3d); + } + + // Memory layout: MorphTarget[n]; (vertices and normals)[n] + MorphTarget *mts; + if(this->numMorphTargets){ + mts = (MorphTarget*)rwResize(this->morphTargets, n*sz, MEMDUR_EVENT | ID_GEOMETRY); + this->morphTargets = mts; + // Since we now have more morph targets than before, move the vertex data up + uint8 *src = (uint8*)mts + sz*this->numMorphTargets; + uint8 *dst = (uint8*)mts + sz*n; + uint32 len = (sz-sizeof(MorphTarget))*this->numMorphTargets; + while(len--) + *--dst = *--src; + }else{ + mts = (MorphTarget*)rwNew(n*sz, MEMDUR_EVENT | ID_GEOMETRY); + this->morphTargets = mts; + } + + // Set up everything and initialize the bounding sphere for new morph targets + V3d *data = (V3d*)&mts[n]; + for(int32 i = 0; i < n; i++){ + mts->parent = this; + mts->vertices = nil; + mts->normals = nil; + if(i >= this->numMorphTargets){ + mts->boundingSphere.center.x = 0.0f; + mts->boundingSphere.center.y = 0.0f; + mts->boundingSphere.center.z = 0.0f; + mts->boundingSphere.radius = 0.0f; } + if(!(this->flags & NATIVE) && this->numVertices){ + mts->vertices = data; + data += this->numVertices; + if(this->flags & NORMALS){ + mts->normals = data; + data += this->numVertices; + } + } + mts++; } this->numMorphTargets = n; } @@ -324,21 +360,54 @@ Geometry::hasColoredMaterial(void) return 0; } -// TODO: allocate as one chunk +// Force allocate data, even when native flag is set void Geometry::allocateData(void) { + // Geometry data + // Pretty much copy pasted from ::create above + int32 sz = this->numTriangles*sizeof(Triangle); if(this->flags & PRELIT) - this->colors = new RGBA[this->numVertices]; - if((this->flags & TEXTURED) || (this->flags & TEXTURED2)) - for(int32 i = 0; i < this->numTexCoordSets; i++) - this->texCoords[i] = - new TexCoords[this->numVertices]; + sz += this->numVertices*sizeof(RGBA); + sz += this->numTexCoordSets*this->numVertices*sizeof(TexCoords); + + uint8 *data = (uint8*)rwNew(sz, MEMDUR_EVENT | ID_GEOMETRY); + this->triangles = (Triangle*)data; + data += this->numTriangles*sizeof(Triangle); + for(int32 i = 0; i < this->numTriangles; i++) + this->triangles[i].matId = 0xFFFF; + if(this->flags & PRELIT){ + this->colors = (RGBA*)data; + data += this->numVertices*sizeof(RGBA); + } + for(int32 i = 0; i < this->numTexCoordSets; i++){ + this->texCoords[i] = (TexCoords*)data; + data += this->numVertices*sizeof(TexCoords); + } + + // MorphTarget data + // Bounding sphere is copied by realloc. + sz = sizeof(MorphTarget) + this->numVertices*sizeof(V3d); + if(this->flags & NORMALS) + sz += this->numVertices*sizeof(V3d); + + MorphTarget *mt = (MorphTarget*)rwResize(this->morphTargets, + sz*this->numMorphTargets, MEMDUR_EVENT | ID_GEOMETRY); + this->morphTargets = mt; + V3d *vdata = (V3d*)&mt[this->numMorphTargets]; for(int32 i = 0; i < this->numMorphTargets; i++){ - MorphTarget *m = &morphTargets[i]; - m->vertices = new V3d[this->numVertices]; - if(this->flags & NORMALS) - m->normals = new V3d[this->numVertices]; + mt->parent = this; + mt->vertices = nil; + mt->normals = nil; + if(this->numVertices){ + mt->vertices = vdata; + vdata += this->numVertices; + if(this->flags & NORMALS){ + mt->normals = vdata; + vdata += this->numVertices; + } + } + mt++; } } @@ -350,6 +419,9 @@ isDegenerate(uint16 *idx) idx[1] == idx[2]; } +// This functions assumes there is enough space allocated +// for triangles. Use MeshHeader::guessNumTriangles() and +// Geometry::allocateData() void Geometry::generateTriangles(int8 *adc) { @@ -357,7 +429,7 @@ Geometry::generateTriangles(int8 *adc) assert(header != nil); this->numTriangles = 0; - Mesh *m = header->mesh; + Mesh *m = header->getMeshes(); int8 *adcbits = adc; for(uint32 i = 0; i < header->numMeshes; i++){ if(m->numIndices < 3){ @@ -378,11 +450,8 @@ Geometry::generateTriangles(int8 *adc) m++; } - delete[] this->triangles; - this->triangles = new Triangle[this->numTriangles]; - Triangle *tri = this->triangles; - m = header->mesh; + m = header->getMeshes(); adcbits = adc; for(uint32 i = 0; i < header->numMeshes; i++){ if(m->numIndices < 3){ @@ -434,38 +503,44 @@ dumpMesh(Mesh *m) void Geometry::buildMeshes(void) { -//dumpMesh(this->meshHeader->mesh); - delete this->meshHeader; - Triangle *tri; - MeshHeader *h = new MeshHeader; - this->meshHeader = h; + Mesh *mesh; + + rwFree(this->meshHeader); + this->meshHeader = nil; + int32 numMeshes = this->matList.numMaterials; if((this->flags & Geometry::TRISTRIP) == 0){ - h->flags = 0; - h->totalIndices = this->numTriangles*3; - h->numMeshes = this->matList.numMaterials; - h->mesh = new Mesh[h->numMeshes]; - for(uint32 i = 0; i < h->numMeshes; i++){ - h->mesh[i].material = this->matList.materials[i]; - h->mesh[i].numIndices = 0; - } + int32 *numIndices = rwNewT(int32, numMeshes, + MEMDUR_FUNCTION | ID_GEOMETRY); + memset(numIndices, 0, numMeshes*sizeof(int32)); + // count indices per mesh tri = this->triangles; for(int32 i = 0; i < this->numTriangles; i++){ - h->mesh[tri->matId].numIndices += 3; + assert(tri->matId >= 0 && tri->matId < numMeshes); + numIndices[tri->matId] += 3; tri++; } - h->allocateIndices(); - for(uint32 i = 0; i < h->numMeshes; i++) - h->mesh[i].numIndices = 0; - // same as above but fill with indices + // setup meshes + this->allocateMeshes(numMeshes, this->numTriangles*3, 0); + mesh = this->meshHeader->getMeshes(); + for(int32 i = 0; i < numMeshes; i++){ + mesh[i].material = this->matList.materials[i]; + mesh[i].numIndices = numIndices[i]; + } + this->meshHeader->setupIndices(); + rwFree(numIndices); + + // now fill in the indices + for(int32 i = 0; i < numMeshes; i++) + mesh[i].numIndices = 0; tri = this->triangles; for(int32 i = 0; i < this->numTriangles; i++){ - uint32 idx = h->mesh[tri->matId].numIndices; - h->mesh[tri->matId].indices[idx++] = tri->v[0]; - h->mesh[tri->matId].indices[idx++] = tri->v[1]; - h->mesh[tri->matId].indices[idx++] = tri->v[2]; - h->mesh[tri->matId].numIndices = idx; + uint32 idx = mesh[tri->matId].numIndices; + mesh[tri->matId].indices[idx++] = tri->v[0]; + mesh[tri->matId].indices[idx++] = tri->v[1]; + mesh[tri->matId].indices[idx++] = tri->v[2]; + mesh[tri->matId].numIndices = idx; tri++; } }else @@ -479,19 +554,19 @@ void Geometry::correctTristripWinding(void) { MeshHeader *header = this->meshHeader; - if(header == nil || header->flags != MeshHeader::TRISTRIP || - this->instData) + if(this->flags & NATIVE || header == nil || + header->flags != MeshHeader::TRISTRIP) return; - MeshHeader *newhead = new MeshHeader; + this->meshHeader = nil; + // Allocate no indices, we realloc later + MeshHeader *newhead = this->allocateMeshes(header->numMeshes, 0, 1); newhead->flags = header->flags; - newhead->numMeshes = header->numMeshes; - newhead->totalIndices = 0; - newhead->mesh = new Mesh[newhead->numMeshes]; /* get a temporary working buffer */ - uint16 *indices = new uint16[header->totalIndices*2]; + uint16 *indices = rwNewT(uint16, header->totalIndices*2, + MEMDUR_FUNCTION | ID_GEOMETRY); - Mesh *mesh = header->mesh; - Mesh *newmesh = newhead->mesh; + Mesh *mesh = header->getMeshes(); + Mesh *newmesh = newhead->getMeshes(); for(uint16 i = 0; i < header->numMeshes; i++){ newmesh->numIndices = 0; newmesh->indices = &indices[newhead->totalIndices]; @@ -523,11 +598,11 @@ Geometry::correctTristripWinding(void) mesh++; newmesh++; } - newhead->allocateIndices(); - memcpy(newhead->mesh[0].indices, indices, newhead->totalIndices*2); - delete[] indices; - this->meshHeader = newhead; - delete header; + rwFree(header); + // Now allocate indices and copy them + this->allocateMeshes(newhead->numMeshes, newhead->totalIndices, 0); + memcpy(this->meshHeader->getMeshes()->indices, indices, newhead->totalIndices*2); + rwFree(indices); } void @@ -536,16 +611,18 @@ Geometry::removeUnusedMaterials(void) if(this->meshHeader == nil) return; MeshHeader *mh = this->meshHeader; + Mesh *m = mh->getMeshes(); for(uint32 i = 0; i < mh->numMeshes; i++) - if(mh->mesh[i].indices == nil) + if(m[i].indices == nil) return; - int32 *map = new int32[this->matList.numMaterials]; - Material **materials = new Material*[this->matList.numMaterials]; + int32 *map = rwNewT(int32, this->matList.numMaterials, + MEMDUR_FUNCTION | ID_GEOMETRY); + Material **materials = rwNewT(Material*,this->matList.numMaterials, + MEMDUR_EVENT | ID_MATERIAL); int32 numMaterials = 0; /* Build new material list and map */ for(uint32 i = 0; i < mh->numMeshes; i++){ - Mesh *m = &mh->mesh[i]; if(m->numIndices <= 0) continue; materials[numMaterials] = m->material; @@ -553,6 +630,7 @@ Geometry::removeUnusedMaterials(void) int32 oldid = this->matList.findIndex(m->material); map[oldid] = numMaterials; numMaterials++; + m++; } for(int32 i = 0; i < this->matList.numMaterials; i++) this->matList.materials[i]->destroy(); @@ -562,38 +640,35 @@ Geometry::removeUnusedMaterials(void) this->matList.numMaterials = numMaterials; /* Build new meshes */ - MeshHeader *newmh = new MeshHeader; + this->meshHeader = nil; + MeshHeader *newmh = this->allocateMeshes(numMaterials, mh->totalIndices, 0); newmh->flags = mh->flags; - newmh->numMeshes = numMaterials; - newmh->mesh = new Mesh[newmh->numMeshes]; - newmh->totalIndices = mh->totalIndices; - Mesh *newm = newmh->mesh; + Mesh *newm = newmh->getMeshes(); + m = mh->getMeshes(); for(uint32 i = 0; i < mh->numMeshes; i++){ - Mesh *oldm = &mh->mesh[i]; - if(oldm->numIndices <= 0) + if(m[i].numIndices <= 0) continue; - newm->numIndices = oldm->numIndices; - newm->material = oldm->material; + newm->numIndices = m[i].numIndices; + newm->material = m[i].material; newm++; } - newmh->allocateIndices(); + newmh->setupIndices(); /* Copy indices */ - newm = newmh->mesh; + newm = newmh->getMeshes();; + m = mh->getMeshes(); for(uint32 i = 0; i < mh->numMeshes; i++){ - Mesh *oldm = &mh->mesh[i]; - if(oldm->numIndices <= 0) + if(m[i].numIndices <= 0) continue; - memcpy(newm->indices, oldm->indices, - oldm->numIndices*sizeof(*oldm->indices)); + memcpy(newm->indices, m[i].indices, + m[i].numIndices*sizeof(*m[i].indices)); newm++; } - delete this->meshHeader; - this->meshHeader = newmh; + rwFree(mh); /* Remap triangle material IDs */ for(int32 i = 0; i < this->numTriangles; i++) this->triangles[i].matId = map[this->triangles[i].matId]; - delete[] map; + rwFree(map); } // @@ -628,12 +703,10 @@ MaterialList::appendMaterial(Material *mat) if(this->numMaterials >= this->space){ space = this->space + 20; if(this->materials) - ml = (Material**)rwRealloc(this->materials, - space*sizeof(Material*), + ml = rwReallocT(Material*, this->materials, space, MEMDUR_EVENT | ID_MATERIAL); else - ml = (Material**)rwMalloc(space*sizeof(Material*), - MEMDUR_EVENT | ID_MATERIAL); + ml = rwMallocT(Material*, space, MEMDUR_EVENT | ID_MATERIAL); if(ml == nil) return -1; this->space = space; @@ -666,7 +739,7 @@ MaterialList::streamRead(Stream *stream, MaterialList *matlist) numMat = stream->readI32(); if(numMat == 0) return matlist; - matlist->materials = (Material**)rwMalloc(numMat*sizeof(Material*), MEMDUR_EVENT | ID_MATERIAL); + matlist->materials = rwMallocT(Material*,numMat, MEMDUR_EVENT | ID_MATERIAL); if(matlist->materials == nil) goto fail; matlist->space = numMat; diff --git a/src/geoplg.cpp b/src/geoplg.cpp index 821735f..749c330 100644 --- a/src/geoplg.cpp +++ b/src/geoplg.cpp @@ -25,39 +25,119 @@ namespace rw { // Mesh +// Allocate a mesh header, meshes and optionally indices. +// If existing meshes already exist, retain their information. +MeshHeader* +Geometry::allocateMeshes(int32 numMeshes, uint32 numIndices, bool32 noIndices) +{ + uint32 sz; + MeshHeader *mh; + Mesh *m; + uint16 *indices; + int32 oldNumMeshes; + int32 i; + sz = sizeof(MeshHeader) + numMeshes*sizeof(Mesh); + if(!noIndices) + sz += numIndices*sizeof(uint16); + if(this->meshHeader){ + oldNumMeshes = this->meshHeader->numMeshes; + mh = (MeshHeader*)rwResize(this->meshHeader, sz, MEMDUR_EVENT | ID_GEOMETRY); + }else{ + oldNumMeshes = 0; + mh = (MeshHeader*)rwNew(sz, MEMDUR_EVENT | ID_GEOMETRY); + mh->flags = 0; + this->meshHeader = mh; + } + mh->numMeshes = numMeshes; + mh->serialNum = 0; // TODO + mh->totalIndices = numIndices; + m = mh->getMeshes(); + indices = (uint16*)&m[numMeshes]; + for(i = 0; i < mh->numMeshes; i++){ + // keep these + if(i >= oldNumMeshes){ + m->material = nil; + m->numIndices = 0; + } + // always init indices + if(noIndices) + m->indices = nil; + else{ + m->indices = indices; + indices += m->numIndices; + } + m++; + } + return mh; +} + +void +MeshHeader::setupIndices(void) +{ + int32 i; + uint16 *indices; + Mesh *m; + m = this->getMeshes(); + indices = m->indices; + // return if native + if(indices == nil) + return; + for(i = 0; i < this->numMeshes; i++){ + m->indices = indices; + indices += m->numIndices; + m++; + } +} + +struct MeshHeaderStream +{ + uint32 flags; + uint32 numMeshes; + uint32 totalIndices; +}; + +struct MeshStream +{ + uint32 numIndices; + int32 matIndex; +}; + static Stream* readMesh(Stream *stream, int32 len, void *object, int32, int32) { - Geometry *geo = (Geometry*)object; + MeshHeaderStream mhs; + MeshStream ms; + MeshHeader *mh; + Mesh *mesh; int32 indbuf[256]; - uint32 buf[3]; - stream->read(buf, 12); - geo->meshHeader = new MeshHeader; - geo->meshHeader->flags = buf[0]; - geo->meshHeader->numMeshes = buf[1]; - geo->meshHeader->totalIndices = buf[2]; - geo->meshHeader->mesh = new Mesh[geo->meshHeader->numMeshes]; - Mesh *mesh = geo->meshHeader->mesh; - bool hasData = len > 12+geo->meshHeader->numMeshes*8; - uint16 *p = nil; - if(!(geo->flags & Geometry::NATIVE) || hasData) - p = new uint16[geo->meshHeader->totalIndices]; - for(uint32 i = 0; i < geo->meshHeader->numMeshes; i++){ - stream->read(buf, 8); - mesh->numIndices = buf[0]; - mesh->material = geo->matList.materials[buf[1]]; - mesh->indices = nil; + uint16 *indices; + Geometry *geo = (Geometry*)object; + + stream->read(&mhs, sizeof(MeshHeaderStream)); + // Have to do this dance for War Drum's meshes + bool32 hasData = len > sizeof(MeshHeaderStream)+mhs.numMeshes*sizeof(MeshStream); + assert(geo->meshHeader == nil); + geo->meshHeader = nil; + mh = geo->allocateMeshes(mhs.numMeshes, mhs.totalIndices, + geo->flags & Geometry::NATIVE && !hasData); + + mesh = mh->getMeshes(); + indices = mesh->indices; + for(uint32 i = 0; i < mh->numMeshes; i++){ + stream->read(&ms, sizeof(MeshStream)); + mesh->numIndices = ms.numIndices; + mesh->material = geo->matList.materials[ms.matIndex]; if(geo->flags & Geometry::NATIVE){ - // OpenGL stores uint16 indices here + // War Drum OpenGL stores uint16 indices here if(hasData){ - mesh->indices = p; - p += mesh->numIndices; + mesh->indices = indices; + indices += mesh->numIndices; stream->read(mesh->indices, mesh->numIndices*2); } }else{ - mesh->indices = p; - p += mesh->numIndices; + mesh->indices = indices; + indices += mesh->numIndices; uint16 *ind = mesh->indices; int32 numIndices = mesh->numIndices; for(; numIndices > 0; numIndices -= 256){ @@ -76,18 +156,19 @@ readMesh(Stream *stream, int32 len, void *object, int32, int32) static Stream* writeMesh(Stream *stream, int32, void *object, int32, int32) { - Geometry *geo = (Geometry*)object; + MeshHeaderStream mhs; + MeshStream ms; int32 indbuf[256]; - uint32 buf[3]; - buf[0] = geo->meshHeader->flags; - buf[1] = geo->meshHeader->numMeshes; - buf[2] = geo->meshHeader->totalIndices; - stream->write(buf, 12); - Mesh *mesh = geo->meshHeader->mesh; + Geometry *geo = (Geometry*)object; + mhs.flags = geo->meshHeader->flags; + mhs.numMeshes = geo->meshHeader->numMeshes; + mhs.totalIndices = geo->meshHeader->totalIndices; + stream->write(&mhs, sizeof(MeshHeaderStream)); + Mesh *mesh = geo->meshHeader->getMeshes(); for(uint32 i = 0; i < geo->meshHeader->numMeshes; i++){ - buf[0] = mesh->numIndices; - buf[1] = geo->matList.findIndex(mesh->material); - stream->write(buf, 8); + ms.numIndices = mesh->numIndices; + ms.matIndex = geo->matList.findIndex(mesh->material); + stream->write(&ms, sizeof(MeshStream)); if(geo->flags & Geometry::NATIVE){ assert(geo->instData != nil); if(geo->instData->platform == PLATFORM_WDGL) @@ -133,23 +214,17 @@ registerMeshPlugin(void) Geometry::registerPluginStream(0x50E, readMesh, writeMesh, getSizeMesh); } -MeshHeader::~MeshHeader(void) +// Returns the maximum number of triangles. Just so +// we can allocate enough before instancing. This does not +// take into account degerate triangles or ADC bits as +// we don't look at the data. +uint32 +MeshHeader::guessNumTriangles(void) { - // first mesh holds pointer to all indices - delete[] this->mesh[0].indices; - delete[] this->mesh; -} - -void -MeshHeader::allocateIndices(void) -{ - uint16 *p = new uint16[this->totalIndices]; - Mesh *mesh = this->mesh; - for(uint32 i = 0; i < this->numMeshes; i++){ - mesh->indices = p; - p += mesh->numIndices; - mesh++; - } + if(this->flags == MeshHeader::TRISTRIP) + return this->totalIndices - 2*this->numMeshes; + else + return this->totalIndices/3; } // Native Data diff --git a/src/gl/gl3pipe.cpp b/src/gl/gl3pipe.cpp index 2eb6130..44b685a 100644 --- a/src/gl/gl3pipe.cpp +++ b/src/gl/gl3pipe.cpp @@ -30,7 +30,7 @@ instance(rw::ObjPipeline *rwpipe, Atomic *atomic) // TODO: allow for REINSTANCE if(geo->instData) return; - InstanceDataHeader *header = new InstanceDataHeader; + InstanceDataHeader *header = rwNewT(InstanceDataHeader, 1, MEMDUR_EVENT | ID_GEOMETRY); MeshHeader *meshh = geo->meshHeader; geo->instData = header; header->platform = PLATFORM_GL3; @@ -40,11 +40,11 @@ instance(rw::ObjPipeline *rwpipe, Atomic *atomic) header->primType = meshh->flags == 1 ? GL_TRIANGLE_STRIP : GL_TRIANGLES; header->totalNumVertex = geo->numVertices; header->totalNumIndex = meshh->totalIndices; - header->inst = new InstanceData[header->numMeshes]; + header->inst = rwNewT(InstanceData, header->numMeshes, MEMDUR_EVENT | ID_GEOMETRY); - header->indexBuffer = new uint16[header->totalNumIndex]; + header->indexBuffer = rwNewT(uint16, header->totalNumIndex, MEMDUR_EVENT | ID_GEOMETRY); InstanceData *inst = header->inst; - Mesh *mesh = meshh->mesh; + Mesh *mesh = meshh->getMeshes(); uint32 offset = 0; for(uint32 i = 0; i < header->numMeshes; i++){ findMinVertAndNumVertices(mesh->indices, mesh->numIndices, @@ -167,14 +167,14 @@ defaultInstanceCB(Geometry *geo, InstanceDataHeader *header) header->numAttribs = a - attribs; for(a = attribs; a != &attribs[header->numAttribs]; a++) a->stride = stride; - header->attribDesc = new AttribDesc[header->numAttribs]; + header->attribDesc = rwNewT(AttribDesc, header->numAttribs, MEMDUR_EVENT | ID_GEOMETRY); memcpy(header->attribDesc, attribs, header->numAttribs*sizeof(AttribDesc)); // // Allocate and fill vertex buffer // - uint8 *verts = new uint8[header->totalNumVertex*stride]; + uint8 *verts = rwNewT(uint8, header->totalNumVertex*stride, MEMDUR_EVENT | ID_GEOMETRY); header->vertexBuffer = verts; // Positions diff --git a/src/gl/gl3plugins.cpp b/src/gl/gl3plugins.cpp index 518b1cf..9aea327 100644 --- a/src/gl/gl3plugins.cpp +++ b/src/gl/gl3plugins.cpp @@ -342,7 +342,7 @@ skinInstanceCB(Geometry *geo, InstanceDataHeader *header) header->numAttribs = a - attribs; for(a = attribs; a != &attribs[header->numAttribs]; a++) a->stride = stride; - header->attribDesc = new AttribDesc[header->numAttribs]; + header->attribDesc = rwNewT(AttribDesc, header->numAttribs, MEMDUR_EVENT | ID_GEOMETRY); memcpy(header->attribDesc, attribs, header->numAttribs*sizeof(AttribDesc)); @@ -350,7 +350,7 @@ skinInstanceCB(Geometry *geo, InstanceDataHeader *header) // Allocate and fill vertex buffer // Skin *skin = Skin::get(geo); - uint8 *verts = new uint8[header->totalNumVertex*stride]; + uint8 *verts = rwNewT(uint8, header->totalNumVertex*stride, MEMDUR_EVENT | ID_GEOMETRY); header->vertexBuffer = verts; // Positions diff --git a/src/gl/gl3shader.cpp b/src/gl/gl3shader.cpp index 445bc98..dc14dc6 100644 --- a/src/gl/gl3shader.cpp +++ b/src/gl/gl3shader.cpp @@ -154,7 +154,7 @@ Shader::fromStrings(const char *vsrc, const char *fsrc) glDeleteProgram(vs); glDeleteProgram(fs); - Shader *sh = new Shader; + Shader *sh = rwNewT(Shader, 1, MEMDUR_EVENT | ID_DRIVER); // or global? // set uniform block binding for(i = 0; i < uniformRegistry.numBlocks; i++){ @@ -166,7 +166,7 @@ Shader::fromStrings(const char *vsrc, const char *fsrc) // query uniform locations sh->program = program; - sh->uniformLocations = new GLint[uniformRegistry.numUniforms]; + sh->uniformLocations = rwNewT(GLint, uniformRegistry.numUniforms, MEMDUR_EVENT | ID_DRIVER); for(i = 0; i < uniformRegistry.numUniforms; i++) sh->uniformLocations[i] = glGetUniformLocation(program, uniformRegistry.uniformNames[i]); diff --git a/src/gl/wdgl.cpp b/src/gl/wdgl.cpp index 1981f6d..ffeb7ea 100644 --- a/src/gl/wdgl.cpp +++ b/src/gl/wdgl.cpp @@ -95,7 +95,7 @@ uploadGeo(Geometry *geo) 0, GL_STATIC_DRAW); GLintptr offset = 0; for(uint32 i = 0; i < meshHeader->numMeshes; i++){ - Mesh *mesh = &meshHeader->mesh[i]; + Mesh *mesh = &meshHeader->getMeshes()[i]; glBufferSubData(GL_ARRAY_BUFFER, offset, mesh->numIndices*2, mesh->indices); offset += mesh->numIndices*2; @@ -240,9 +240,9 @@ destroyNativeData(void *object, int32, int32) (InstanceDataHeader*)geometry->instData; geometry->instData = nil; // TODO: delete ibo and vbo - delete[] header->attribs; - delete[] header->data; - delete header; + rwFree(header->attribs); + rwFree(header->data); + rwFree(header); return object; } @@ -250,17 +250,17 @@ Stream* readNativeData(Stream *stream, int32, void *object, int32, int32) { Geometry *geometry = (Geometry*)object; - InstanceDataHeader *header = new InstanceDataHeader; + InstanceDataHeader *header = rwNewT(InstanceDataHeader, 1, MEMDUR_EVENT | ID_GEOMETRY); geometry->instData = header; header->platform = PLATFORM_WDGL; header->vbo = 0; header->ibo = 0; header->numAttribs = stream->readU32(); - header->attribs = new AttribDesc[header->numAttribs]; + header->attribs = rwNewT(AttribDesc, header->numAttribs, MEMDUR_EVENT | ID_GEOMETRY); stream->read(header->attribs, header->numAttribs*sizeof(AttribDesc)); header->dataSize = header->attribs[0].stride*geometry->numVertices; - header->data = new uint8[header->dataSize]; + header->data = rwNewT(uint8, header->dataSize, MEMDUR_EVENT | ID_GEOMETRY); stream->read(header->data, header->dataSize); return stream; } @@ -325,7 +325,7 @@ instance(rw::ObjPipeline *rwpipe, Atomic *atomic) // TODO: allow for REINSTANCE (or not, wdgl can't render) if(geo->instData) return; - InstanceDataHeader *header = new InstanceDataHeader; + InstanceDataHeader *header = rwNewT(InstanceDataHeader, 1, MEMDUR_EVENT | ID_GEOMETRY); geo->instData = header; header->platform = PLATFORM_WDGL; header->vbo = 0; @@ -337,7 +337,7 @@ instance(rw::ObjPipeline *rwpipe, Atomic *atomic) if(geo->flags & Geometry::NORMALS) header->numAttribs++; int32 offset = 0; - header->attribs = new AttribDesc[header->numAttribs]; + header->attribs = rwNewT(AttribDesc, header->numAttribs, MEMDUR_EVENT | ID_GEOMETRY); AttribDesc *a = header->attribs; // Vertices @@ -388,7 +388,7 @@ instance(rw::ObjPipeline *rwpipe, Atomic *atomic) offset += pipe->instanceCB(geo, firstCustom, offset); else{ header->dataSize = offset*geo->numVertices; - header->data = new uint8[header->dataSize]; + header->data = rwNewT(uint8, header->dataSize, MEMDUR_EVENT | ID_GEOMETRY); } a = header->attribs; @@ -453,7 +453,7 @@ uninstance(rw::ObjPipeline *rwpipe, Atomic *atomic) return; assert(geo->instData != nil); assert(geo->instData->platform == PLATFORM_WDGL); - geo->flags &= ~Geometry::NATIVE; + geo->numTriangles = geo->meshHeader->guessNumTriangles(); geo->allocateData(); uint8 *p; @@ -513,6 +513,7 @@ uninstance(rw::ObjPipeline *rwpipe, Atomic *atomic) geo->generateTriangles(); + geo->flags &= ~Geometry::NATIVE; destroyNativeData(geo, 0, 0); } @@ -549,7 +550,7 @@ readNativeSkin(Stream *stream, int32, void *object, int32 offset) RWERROR((ERR_PLATFORM, platform)); return nil; } - Skin *skin = new Skin; + Skin *skin = rwNewT(Skin, 1, MEMDUR_EVENT | ID_SKIN); *PLUGINOFFSET(Skin*, geometry, offset) = skin; int32 numBones = stream->readI32(); @@ -602,7 +603,7 @@ skinInstanceCB(Geometry *g, int32 i, uint32 offset) offset += 4; header->dataSize = offset*g->numVertices; - header->data = new uint8[header->dataSize]; + header->data = rwNewT(uint8, header->dataSize, MEMDUR_EVENT | ID_GEOMETRY); Skin *skin = Skin::get(g); if(skin == nil) @@ -640,7 +641,7 @@ skinUninstanceCB(Geometry *geo) float *invMats = skin->inverseMatrices; skin->init(skin->numBones, skin->numBones, geo->numVertices); memcpy(skin->inverseMatrices, invMats, skin->numBones*64); - delete[] data; + rwFree(data); uint8 *p; float *weights = skin->weights; diff --git a/src/hanim.cpp b/src/hanim.cpp index 1cfd219..57379c3 100644 --- a/src/hanim.cpp +++ b/src/hanim.cpp @@ -45,12 +45,11 @@ HAnimHierarchy::create(int32 numNodes, int32 *nodeFlags, int32 *nodeIDs, hier->matrices = nil; hier->matricesUnaligned = nil; }else{ - hier->matricesUnaligned = - (void*) new uint8[hier->numNodes*64 + 15]; + hier->matricesUnaligned = rwNew(hier->numNodes*64 + 0xF, MEMDUR_EVENT | ID_HANIM); hier->matrices = (Matrix*)((uintptr)hier->matricesUnaligned & ~0xF); } - hier->nodeInfo = new HAnimNodeInfo[hier->numNodes]; + hier->nodeInfo = rwNewT(HAnimNodeInfo, hier->numNodes, MEMDUR_EVENT | ID_HANIM); for(int32 i = 0; i < hier->numNodes; i++){ hier->nodeInfo[i].id = nodeIDs[i]; hier->nodeInfo[i].index = i; @@ -63,8 +62,8 @@ HAnimHierarchy::create(int32 numNodes, int32 *nodeFlags, int32 *nodeIDs, void HAnimHierarchy::destroy(void) { - delete[] (uint8*)this->matricesUnaligned; - delete[] this->nodeInfo; + rwFree(this->matricesUnaligned); + rwFree(this->nodeInfo); rwFree(this); } @@ -208,8 +207,10 @@ readHAnim(Stream *stream, int32, void *object, int32 offset, int32) int32 maxKeySize = stream->readI32(); // Sizes are fucked for 64 bit pointers but // AnimInterpolator::create() will take care of that - int32 *nodeFlags = new int32[numNodes]; - int32 *nodeIDs = new int32[numNodes]; + int32 *nodeFlags = rwNewT(int32, numNodes, + MEMDUR_FUNCTION | ID_HANIM); + int32 *nodeIDs = rwNewT(int32, numNodes, + MEMDUR_FUNCTION | ID_HANIM); for(int32 i = 0; i < numNodes; i++){ nodeIDs[i] = stream->readI32(); stream->readI32(); // index...unused @@ -218,8 +219,8 @@ readHAnim(Stream *stream, int32, void *object, int32 offset, int32) hanim->hierarchy = HAnimHierarchy::create(numNodes, nodeFlags, nodeIDs, flags, maxKeySize); hanim->hierarchy->parentFrame = (Frame*)object; - delete[] nodeFlags; - delete[] nodeIDs; + rwFree(nodeFlags); + rwFree(nodeIDs); } return stream; } @@ -325,7 +326,7 @@ registerHAnimPlugin(void) writeHAnim, getSizeHAnim); - AnimInterpolatorInfo *info = new AnimInterpolatorInfo; + AnimInterpolatorInfo *info = rwNewT(AnimInterpolatorInfo, 1, MEMDUR_GLOBAL | ID_HANIM); info->id = 1; info->interpKeyFrameSize = sizeof(HAnimInterpFrame); info->animKeyFrameSize = sizeof(HAnimKeyFrame); diff --git a/src/image.cpp b/src/image.cpp index d5a5850..ab4cf18 100644 --- a/src/image.cpp +++ b/src/image.cpp @@ -51,12 +51,12 @@ Image::allocate(void) { if(this->pixels == nil){ this->stride = this->width*(this->depth==4 ? 1 : this->depth/8); - this->pixels = new uint8[this->stride*this->height]; + this->pixels = rwNewT(uint8, this->stride*this->height, MEMDUR_EVENT | ID_IMAGE); this->flags |= 1; } if(this->palette == nil){ if(this->depth == 4 || this->depth == 8) - this->palette = new uint8[(this->depth==4? 16 : 256)*4]; + this->palette = rwNewT(uint8, (this->depth==4? 16 : 256)*4, MEMDUR_EVENT | ID_IMAGE); this->flags |= 2; } } @@ -65,11 +65,11 @@ void Image::free(void) { if(this->flags&1){ - delete[] this->pixels; + rwFree(this->pixels); this->pixels = nil; } if(this->flags&2){ - delete[] this->palette; + rwFree(this->palette); this->palette = nil; } } @@ -355,7 +355,7 @@ Image::unindex(void) int32 ndepth = this->hasAlpha() ? 32 : 24; int32 nstride = this->width*ndepth/8; - uint8 *npixels = new uint8[nstride*this->height]; + uint8 *npixels = rwNewT(uint8, nstride*this->height, MEMDUR_EVENT | ID_IMAGE); uint8 *line = this->pixels; uint8 *nline = npixels; diff --git a/src/matfx.cpp b/src/matfx.cpp index 70bea42..b0875bf 100755 --- a/src/matfx.cpp +++ b/src/matfx.cpp @@ -101,7 +101,7 @@ MatFX::setEffects(Material *mat, uint32 type) matfx = MatFX::get(mat); if(matfx == nil){ - matfx = new MatFX; + matfx = rwNewT(MatFX, 1, MEMDUR_EVENT | ID_MATFX); memset(matfx, 0, sizeof(MatFX)); *PLUGINOFFSET(MatFX*, mat, matFXGlobals.materialOffset) = matfx; } @@ -231,7 +231,7 @@ destroyMaterialMatFX(void *object, int32 offset, int32) MatFX *matfx = *PLUGINOFFSET(MatFX*, object, offset); if(matfx){ clearMatFX(matfx); - delete matfx; + rwFree(matfx); } return object; } @@ -242,7 +242,7 @@ copyMaterialMatFX(void *dst, void *src, int32 offset, int32) MatFX *srcfx = *PLUGINOFFSET(MatFX*, src, offset); if(srcfx == nil) return dst; - MatFX *dstfx = new MatFX; + MatFX *dstfx = rwNewT(MatFX, 1, MEMDUR_EVENT | ID_MATFX); *PLUGINOFFSET(MatFX*, dst, offset) = dstfx; memcpy(dstfx, srcfx, sizeof(MatFX)); for(int i = 0; i < 2; i++) diff --git a/src/ps2/pds.cpp b/src/ps2/pds.cpp index 53d977d..cf75eef 100755 --- a/src/ps2/pds.cpp +++ b/src/ps2/pds.cpp @@ -61,7 +61,7 @@ registerPDSPlugin(int32 n) { pdsGlobals.maxPipes = n; pdsGlobals.numPipes = 0; - pdsGlobals.pipes = new Pipeline*[n]; + pdsGlobals.pipes = rwNewT(Pipeline*, n, MEMDUR_GLOBAL | ID_PDS); Atomic::registerPlugin(0, ID_PDS, nil, nil, nil); Atomic::setStreamRightsCallback(ID_PDS, atomicPDSRights); diff --git a/src/ps2/ps2.cpp b/src/ps2/ps2.cpp index f83f02d..a89fb5a 100755 --- a/src/ps2/ps2.cpp +++ b/src/ps2/ps2.cpp @@ -61,9 +61,10 @@ destroyNativeData(void *object, int32, int32) return object; InstanceDataHeader *header = (InstanceDataHeader*)geometry->instData; for(uint32 i = 0; i < header->numMeshes; i++) - delete[] header->instanceMeshes[i].data; - delete[] header->instanceMeshes; - delete header; + rwFree(header->instanceMeshes[i].data); + rwFree(header->instanceMeshes); + rwFree(header); + geometry->instData = nil; return object; } @@ -81,19 +82,20 @@ readNativeData(Stream *stream, int32, void *object, int32, int32) RWERROR((ERR_PLATFORM, platform)); return nil; } - InstanceDataHeader *header = new InstanceDataHeader; + InstanceDataHeader *header = rwNewT(InstanceDataHeader, 1, MEMDUR_EVENT | ID_GEOMETRY); geometry->instData = header; header->platform = PLATFORM_PS2; assert(geometry->meshHeader != nil); header->numMeshes = geometry->meshHeader->numMeshes; - header->instanceMeshes = new InstanceData[header->numMeshes]; + header->instanceMeshes = rwNewT(InstanceData, header->numMeshes, MEMDUR_EVENT | ID_GEOMETRY); + Mesh *m = geometry->meshHeader->getMeshes(); for(uint32 i = 0; i < header->numMeshes; i++){ InstanceData *instance = &header->instanceMeshes[i]; uint32 buf[2]; stream->read(buf, 8); instance->dataSize = buf[0]; // TODO: force alignment - instance->data = new uint8[instance->dataSize]; + instance->data = rwNewT(uint8, instance->dataSize, MEMDUR_EVENT | ID_GEOMETRY); #ifdef RW_PS2 uint32 a = (uint32)instance->data; assert(a % 0x10 == 0); @@ -103,8 +105,9 @@ readNativeData(Stream *stream, int32, void *object, int32, int32) if(!buf[1]) fixDmaOffsets(instance); #endif - instance->material = geometry->meshHeader->mesh[i].material; + instance->material = m->material; // sizedebug(instance); + m++; } return stream; } @@ -591,7 +594,7 @@ MatPipeline::instance(Geometry *g, InstanceData *inst, Mesh *m) inst->dataSize = (im.size+im.size2)<<4; // TODO: force alignment - inst->data = new uint8[inst->dataSize]; + inst->data = rwNewT(uint8, inst->dataSize, MEMDUR_EVENT | ID_GEOMETRY); /* make array of addresses of broken out sections */ uint8 *datap[nelem(this->attribs)]; @@ -700,8 +703,7 @@ MatPipeline::collectData(Geometry *g, InstanceData *inst, Mesh *m, uint8 *data[] PipeAttribute *a; InstMeshInfo im = getInstMeshInfo(this, g, m); - uint8 *raw = im.vertexSize*m->numIndices ? - new uint8[im.vertexSize*m->numIndices] : nil; + uint8 *raw = rwNewT(uint8, im.vertexSize*m->numIndices, MEMDUR_EVENT | ID_GEOMETRY); uint8 *dp = raw; for(uint i = 0; i < nelem(this->attribs); i++) if(a = this->attribs[i]) @@ -752,14 +754,14 @@ objInstance(rw::ObjPipeline *rwpipe, Atomic *atomic) // TODO: allow for REINSTANCE if(geo->instData) return; - InstanceDataHeader *header = new InstanceDataHeader; + InstanceDataHeader *header = rwNewT(InstanceDataHeader, 1, MEMDUR_EVENT | ID_GEOMETRY); geo->instData = header; header->platform = PLATFORM_PS2; assert(geo->meshHeader != nil); header->numMeshes = geo->meshHeader->numMeshes; - header->instanceMeshes = new InstanceData[header->numMeshes]; + header->instanceMeshes = rwNewT(InstanceData, header->numMeshes, MEMDUR_EVENT | ID_GEOMETRY); for(uint32 i = 0; i < header->numMeshes; i++){ - Mesh *mesh = &geo->meshHeader->mesh[i]; + Mesh *mesh = &geo->meshHeader->getMeshes()[i]; InstanceData *instance = &header->instanceMeshes[i]; MatPipeline *m; @@ -816,14 +818,15 @@ objUninstance(rw::ObjPipeline *rwpipe, Atomic *atomic) InstanceDataHeader *header = (InstanceDataHeader*)geo->instData; // highest possible number of vertices geo->numVertices = geo->meshHeader->totalIndices; - geo->flags &= ~Geometry::NATIVE; + geo->numTriangles = geo->meshHeader->guessNumTriangles(); geo->allocateData(); - geo->meshHeader->allocateIndices(); - uint32 *flags = new uint32[geo->numVertices]; + geo->allocateMeshes(geo->meshHeader->numMeshes, geo->meshHeader->totalIndices, 0); + uint32 *flags = rwNewT(uint32, geo->numVertices, + MEMDUR_FUNCTION | ID_GEOMETRY); memset(flags, 0, 4*geo->numVertices); - memset(geo->meshHeader->mesh[0].indices, 0, 2*geo->meshHeader->totalIndices); + memset(geo->meshHeader->getMeshes()->indices, 0, 2*geo->meshHeader->totalIndices); for(uint32 i = 0; i < header->numMeshes; i++){ - Mesh *mesh = &geo->meshHeader->mesh[i]; + Mesh *mesh = &geo->meshHeader->getMeshes()[i]; MatPipeline *m; m = pipe->groupPipeline ? pipe->groupPipeline : @@ -833,7 +836,7 @@ objUninstance(rw::ObjPipeline *rwpipe, Atomic *atomic) } geo->numVertices = 0; for(uint32 i = 0; i < header->numMeshes; i++){ - Mesh *mesh = &geo->meshHeader->mesh[i]; + Mesh *mesh = &geo->meshHeader->getMeshes()[i]; InstanceData *instance = &header->instanceMeshes[i]; MatPipeline *m; m = pipe->groupPipeline ? @@ -845,10 +848,10 @@ objUninstance(rw::ObjPipeline *rwpipe, Atomic *atomic) uint8 *raw = m->collectData(geo, instance, mesh, data); assert(m->uninstanceCB); m->uninstanceCB(m, geo, flags, mesh, data); - if(raw) delete[] raw; + rwFree(raw); } for(uint32 i = 0; i < header->numMeshes; i++){ - Mesh *mesh = &geo->meshHeader->mesh[i]; + Mesh *mesh = &geo->meshHeader->getMeshes()[i]; MatPipeline *m; m = pipe->groupPipeline ? pipe->groupPipeline : @@ -859,9 +862,9 @@ objUninstance(rw::ObjPipeline *rwpipe, Atomic *atomic) int8 *bits = getADCbits(geo); geo->generateTriangles(bits); - delete[] flags; + rwFree(flags); + geo->flags &= ~Geometry::NATIVE; destroyNativeData(geo, 0, 0); - geo->instData = nil; /* for(uint32 i = 0; i < header->numMeshes; i++){ Mesh *mesh = &geo->meshHeader->mesh[i]; @@ -1085,9 +1088,9 @@ getADCbitsForMesh(Geometry *geo, Mesh *mesh) int8 *bits = getADCbits(geo); if(bits == nil) return nil; - int32 n = mesh - geo->meshHeader->mesh; + int32 n = mesh - geo->meshHeader->getMeshes(); for(int32 i = 0; i < n; i++) - bits += geo->meshHeader->mesh[i].numIndices; + bits += geo->meshHeader->getMeshes()[i].numIndices; return bits; } @@ -1105,28 +1108,30 @@ unconvertADC(Geometry *g) if(!adc->adcFormatted) return; int8 *b = adc->adcBits; - MeshHeader *h = new MeshHeader; - h->flags = g->meshHeader->flags; // should be tristrip - h->numMeshes = g->meshHeader->numMeshes; - h->mesh = new Mesh[h->numMeshes]; - Mesh *oldm = g->meshHeader->mesh; - Mesh *newm = h->mesh; - h->totalIndices = 0; - for(int32 i = 0; i < h->numMeshes; i++){ + + MeshHeader *oldmh = g->meshHeader; + g->meshHeader = nil; + // Don't allocate indices for now + MeshHeader *newmh = g->allocateMeshes(oldmh->numMeshes, 0, 1); + newmh->flags = oldmh->flags; // should be tristrip + Mesh *oldm = oldmh->getMeshes(); + Mesh *newm = newmh->getMeshes(); + for(int32 i = 0; i < newmh->numMeshes; i++){ newm->material = oldm->material; newm->numIndices = oldm->numIndices; for(uint32 j = 0; j < oldm->numIndices; j++) if(*b++) newm->numIndices += 2; - h->totalIndices += newm->numIndices; + newmh->totalIndices += newm->numIndices; newm++; oldm++; } - h->allocateIndices(); + // Now re-allocate with indices + newmh = g->allocateMeshes(newmh->numMeshes, newmh->totalIndices, 0); b = adc->adcBits; - oldm = g->meshHeader->mesh; - newm = h->mesh; - for(int32 i = 0; i < h->numMeshes; i++){ + oldm = oldmh->getMeshes(); + newm = newmh->getMeshes(); + for(int32 i = 0; i < newmh->numMeshes; i++){ int32 n = 0; for(uint32 j = 0; j < oldm->numIndices; j++){ if(*b++){ @@ -1138,10 +1143,9 @@ unconvertADC(Geometry *g) newm++; oldm++; } - delete g->meshHeader; - g->meshHeader = h; + rwFree(oldmh); adc->adcFormatted = 0; - delete[] adc->adcBits; + rwFree(adc->adcBits); adc->adcBits = nil; adc->numBits = 0; } @@ -1153,7 +1157,7 @@ allocateADC(Geometry *geo) adc->adcFormatted = 1; adc->numBits = geo->meshHeader->totalIndices; int32 size = adc->numBits+3 & ~3; - adc->adcBits = new int8[size]; + adc->adcBits = rwNewT(int8, size, MEMDUR_EVENT | ID_ADC); memset(adc->adcBits, 0, size); } @@ -1175,7 +1179,7 @@ copyADC(void *dst, void *src, int32 offset, int32) return dst; dstadc->numBits = srcadc->numBits; int32 size = dstadc->numBits+3 & ~3; - dstadc->adcBits = new int8[size]; + dstadc->adcBits = rwNewT(int8, size, MEMDUR_EVENT | ID_ADC); memcpy(dstadc->adcBits, srcadc->adcBits, size); return dst; } @@ -1185,7 +1189,7 @@ destroyADC(void *object, int32 offset, int32) { ADCData *adc = PLUGINOFFSET(ADCData, object, offset); if(adc->adcFormatted) - delete[] adc->adcBits; + rwFree(adc->adcBits); return object; } @@ -1205,7 +1209,7 @@ readADC(Stream *stream, int32, void *object, int32 offset, int32) return stream; } int32 size = adc->numBits+3 & ~3; - adc->adcBits = new int8[size]; + adc->adcBits = rwNewT(int8, size, MEMDUR_EVENT | ID_ADC); stream->read(adc->adcBits, size); return stream; } diff --git a/src/ps2/ps2skin.cpp b/src/ps2/ps2skin.cpp index 36609b4..41fa65e 100644 --- a/src/ps2/ps2skin.cpp +++ b/src/ps2/ps2skin.cpp @@ -83,7 +83,7 @@ readNativeSkin(Stream *stream, int32, void *object, int32 offset) return nil; } stream->read(header, 4); - Skin *skin = new Skin; + Skin *skin = rwNewT(Skin, 1, MEMDUR_EVENT | ID_SKIN); *PLUGINOFFSET(Skin*, geometry, offset) = skin; // numUsedBones and numWeights appear in/after 34003 @@ -313,7 +313,7 @@ skinPreCB(MatPipeline*, Geometry *geo) // meshHeader->totalIndices is highest possible number of vertices again skin->init(skin->numBones, skin->numBones, geo->meshHeader->totalIndices); memcpy(skin->inverseMatrices, invMats, skin->numBones*64); - delete[] data; + rwFree(data); } void diff --git a/src/rwbase.h b/src/rwbase.h index ac934f3..e7b2888 100644 --- a/src/rwbase.h +++ b/src/rwbase.h @@ -401,8 +401,10 @@ enum VendorID VEND_CRITERIONTK = 1, VEND_CRITERIONINT = 4, VEND_CRITERIONWORLD = 5, - // Used for platform-specific stuff like rasters - VEND_PLATFORM = 10, + // Used for rasters (platform-specific) + VEND_RASTER = 10, + // Used for driver/device allocation tags + VEND_DRIVER = 11, }; // TODO: modules (VEND_CRITERIONINT) @@ -449,13 +451,16 @@ enum PluginID ID_VERTEXFMT = MAKEPLUGINID(VEND_CRITERIONWORLD, 0x11), // custom native raster - ID_RASTERGL = MAKEPLUGINID(VEND_PLATFORM, PLATFORM_GL), - ID_RASTERPS2 = MAKEPLUGINID(VEND_PLATFORM, PLATFORM_PS2), - ID_RASTERXBOX = MAKEPLUGINID(VEND_PLATFORM, PLATFORM_XBOX), - ID_RASTERD3D8 = MAKEPLUGINID(VEND_PLATFORM, PLATFORM_D3D8), - ID_RASTERD3D9 = MAKEPLUGINID(VEND_PLATFORM, PLATFORM_D3D9), - ID_RASTERWDGL = MAKEPLUGINID(VEND_PLATFORM, PLATFORM_WDGL), - ID_RASTERGL3 = MAKEPLUGINID(VEND_PLATFORM, PLATFORM_GL3), + ID_RASTERGL = MAKEPLUGINID(VEND_RASTER, PLATFORM_GL), + ID_RASTERPS2 = MAKEPLUGINID(VEND_RASTER, PLATFORM_PS2), + ID_RASTERXBOX = MAKEPLUGINID(VEND_RASTER, PLATFORM_XBOX), + ID_RASTERD3D8 = MAKEPLUGINID(VEND_RASTER, PLATFORM_D3D8), + ID_RASTERD3D9 = MAKEPLUGINID(VEND_RASTER, PLATFORM_D3D9), + ID_RASTERWDGL = MAKEPLUGINID(VEND_RASTER, PLATFORM_WDGL), + ID_RASTERGL3 = MAKEPLUGINID(VEND_RASTER, PLATFORM_GL3), + + // anything driver/device related (only as allocation tag) + ID_DRIVER = MAKEPLUGINID(VEND_DRIVER, 0), }; #define ECODE(c, s) c, diff --git a/src/rwengine.h b/src/rwengine.h index be75ff6..f52165f 100755 --- a/src/rwengine.h +++ b/src/rwengine.h @@ -109,9 +109,13 @@ enum MemHint struct MemoryFunctions { - void *(*malloc)(size_t sz, uint32 hint); - void *(*realloc)(void *p, size_t sz, uint32 hint); - void (*free)(void *p); + void *(*rwmalloc)(size_t sz, uint32 hint); + void *(*rwrealloc)(void *p, size_t sz, uint32 hint); + void (*rwfree)(void *p); + // These are temporary until we have better error handling + // TODO: Maybe don't put them here since they shouldn't really be switched out + void *(*rwmustmalloc)(size_t sz, uint32 hint); + void *(*rwmustrealloc)(void *p, size_t sz, uint32 hint); }; // This is for platform independent things @@ -158,9 +162,16 @@ inline void SetRenderState(int32 state, uint32 value){ inline uint32 GetRenderState(int32 state){ return engine->device.getRenderState(state); } -#define rwMalloc(s, h) rw::Engine::memfuncs.malloc(s,h) -#define rwRealloc(p, s, h) rw::Engine::memfuncs.realloc(p,s,h) -#define rwFree(p) rw::Engine::memfuncs.free(p) +// These must be macros because we might want to pass __FILE__ and __LINE__ later +#define rwMalloc(s, h) rw::Engine::memfuncs.rwmalloc(s,h) +#define rwMallocT(t, s, h) (t*)rw::Engine::memfuncs.rwmalloc((s)*sizeof(t),h) +#define rwRealloc(p, s, h) rw::Engine::memfuncs.rwrealloc(p,s,h) +#define rwReallocT(t, p, s, h) (t*)rw::Engine::memfuncs.rwrealloc(p,(s)*sizeof(t),h) +#define rwFree(p) rw::Engine::memfuncs.rwfree(p) +#define rwNew(s, h) rw::Engine::memfuncs.rwmustmalloc(s,h) +#define rwNewT(t, s, h) (t*)rw::Engine::memfuncs.rwmustmalloc((s)*sizeof(t),h) +#define rwResize(p, s, h) rw::Engine::memfuncs.rwmustrealloc(p,s,h) +#define rwResizeT(t, p, s, h) (t*)rw::Engine::memfuncs.rwmustrealloc(p,(s)*sizeof(t),h) namespace null { void beginUpdate(Camera*); diff --git a/src/rwobjects.h b/src/rwobjects.h index 275e4a6..993d6b5 100755 --- a/src/rwobjects.h +++ b/src/rwobjects.h @@ -362,16 +362,21 @@ struct MeshHeader }; uint32 flags; uint16 numMeshes; - // RW has uint16 serialNum here + uint16 serialNum; // not used yet uint32 totalIndices; - Mesh *mesh; // RW has a byte offset here + uint32 pad; // needed for alignment of Meshes + // after this the meshes - void allocateIndices(void); - ~MeshHeader(void); + Mesh *getMeshes(void) { return (Mesh*)(this+1); } + void setupIndices(void); + uint32 guessNumTriangles(void); }; +struct Geometry; + struct MorphTarget { + Geometry *parent; Sphere boundingSphere; V3d *vertices; V3d *normals; @@ -433,6 +438,7 @@ struct Geometry void calculateBoundingSphere(void); bool32 hasColoredMaterial(void); void allocateData(void); + MeshHeader *allocateMeshes(int32 numMeshes, uint32 numIndices, bool32 noIndices); void generateTriangles(int8 *adc = nil); void buildMeshes(void); void buildTristrips(void); @@ -463,6 +469,7 @@ struct Geometry // librw's pipelines are different so it's unused here. NATIVEINSTANCE = 0x02000000 }; + }; void registerMeshPlugin(void); diff --git a/src/skin.cpp b/src/skin.cpp index d6087de..3a83faf 100644 --- a/src/skin.cpp +++ b/src/skin.cpp @@ -38,11 +38,11 @@ destroySkin(void *object, int32 offset, int32) { Skin *skin = *PLUGINOFFSET(Skin*, object, offset); if(skin){ - delete[] skin->data; + rwFree(skin->data); rwFree(skin->remapIndices); // delete[] skin->platformData; } - delete skin; + rwFree(skin); return object; } @@ -55,7 +55,7 @@ copySkin(void *dst, void *src, int32 offset, int32) Geometry *geometry = (Geometry*)src; assert(geometry->instData == nil); assert(((Geometry*)src)->numVertices == ((Geometry*)dst)->numVertices); - Skin *dstskin = new Skin; + Skin *dstskin = rwNewT(Skin, 1, MEMDUR_EVENT | ID_SKIN); *PLUGINOFFSET(Skin*, dst, offset) = dstskin; dstskin->numBones = srcskin->numBones; dstskin->numUsedBones = srcskin->numUsedBones; @@ -134,7 +134,7 @@ readSkin(Stream *stream, int32 len, void *object, int32 offset, int32) stream->read(header, 4); // numBones, numUsedBones, // numWeights, unused - Skin *skin = new Skin; + Skin *skin = rwNewT(Skin, 1, MEMDUR_EVENT | ID_SKIN); *PLUGINOFFSET(Skin*, geometry, offset) = skin; // numUsedBones and numWeights appear in/after 34003 @@ -315,7 +315,7 @@ Skin::init(int32 numBones, int32 numUsedBones, int32 numVertices) uint32 size = this->numUsedBones + this->numBones*64 + numVertices*(16+4) + 0xF; - this->data = new uint8[size]; + this->data = rwNewT(uint8, size, MEMDUR_EVENT | ID_SKIN); uint8 *p = this->data; this->usedBones = nil; diff --git a/src/tga.cpp b/src/tga.cpp index dd547bf..9d66448 100644 --- a/src/tga.cpp +++ b/src/tga.cpp @@ -118,7 +118,7 @@ readTGA(const char *afilename) } file.close(); - delete[] data; + rwFree(data); return image; } diff --git a/src/tristrip.cpp b/src/tristrip.cpp index 195e1f7..a4c96d3 100644 --- a/src/tristrip.cpp +++ b/src/tristrip.cpp @@ -9,6 +9,7 @@ #include "rwplg.h" #include "rwpipeline.h" #include "rwobjects.h" +#include "rwengine.h" #define PLUGIN_ID 2 @@ -427,7 +428,7 @@ Geometry::buildTristrips(void) printf("%ld\n", sizeof(StripNode)); - smesh.nodes = new StripNode[this->numTriangles]; + smesh.nodes = rwNewT(StripNode, this->numTriangles, MEMDUR_FUNCTION | ID_GEOMETRY); for(int32 i = 0; i < this->matList.numMaterials; i++){ smesh.loneNodes.init(); smesh.endNodes.init(); @@ -444,7 +445,7 @@ printf("-------\n"); //printf("-------\n"); //printEnds(&smesh); } - delete[] smesh.nodes; + rwFree(smesh.nodes); exit(1); } diff --git a/src/uvanim.cpp b/src/uvanim.cpp index fcfd32f..d666c14 100644 --- a/src/uvanim.cpp +++ b/src/uvanim.cpp @@ -49,7 +49,7 @@ UVAnimDictionary::destroy(void) UVAnimDictEntry *de = UVAnimDictEntry::fromDict(lnk); UVAnimCustomData *cust = UVAnimCustomData::get(de->anim); cust->destroy(de->anim); - delete de; + rwFree(de); } rwFree(this); } @@ -57,7 +57,7 @@ UVAnimDictionary::destroy(void) void UVAnimDictionary::add(Animation *anim) { - UVAnimDictEntry *de = new UVAnimDictEntry; + UVAnimDictEntry *de = rwNewT(UVAnimDictEntry, 1, MEMDUR_EVENT | ID_UVANIMDICT); de->anim = anim; this->animations.append(&de->inDict); } @@ -172,7 +172,7 @@ static void registerUVAnimInterpolator(void) { // Linear - AnimInterpolatorInfo *info = new AnimInterpolatorInfo; + AnimInterpolatorInfo *info = rwNewT(AnimInterpolatorInfo, 1, MEMDUR_GLOBAL | ID_UVANIMATION); info->id = 0x1C0; info->interpKeyFrameSize = sizeof(UVAnimInterpFrame); info->animKeyFrameSize = sizeof(UVAnimKeyFrame); @@ -188,7 +188,7 @@ registerUVAnimInterpolator(void) AnimInterpolatorInfo::registerInterp(info); // Param - info = new AnimInterpolatorInfo; + info = rwNewT(AnimInterpolatorInfo, 1, MEMDUR_GLOBAL | ID_UVANIMATION); info->id = 0x1C1; info->interpKeyFrameSize = sizeof(UVAnimInterpFrame); info->animKeyFrameSize = sizeof(UVAnimKeyFrame); @@ -226,7 +226,7 @@ destroyUVAnim(void *object, int32 offset, int32) UVAnimCustomData *custom = UVAnimCustomData::get(ip->currentAnim); custom->destroy(ip->currentAnim); - delete ip; + rwFree(ip); } } return object; diff --git a/tools/ps2test/main.cpp b/tools/ps2test/main.cpp index 330400a..864ce9b 100755 --- a/tools/ps2test/main.cpp +++ b/tools/ps2test/main.cpp @@ -703,7 +703,7 @@ main() rw::findChunk(&in, rw::ID_CLUMP, NULL, NULL); rw::Clump *clump = rw::Clump::streamRead(&in); in.close(); - delete[] data; + rwFree(data); GsCtx gsCtx;