diff --git a/premake5.lua b/premake5.lua index 1074856..2ba0da9 100755 --- a/premake5.lua +++ b/premake5.lua @@ -71,6 +71,7 @@ project "librw" project "dumprwtree" kind "ConsoleApp" targetdir (Bindir) + removeplatforms { "*gl3", "*d3d9", "ps2" } files { "tools/dumprwtree/*" } includedirs { "." } libdirs { Libdir } diff --git a/src/anim.cpp b/src/anim.cpp index af4cc82..b6fcb3c 100644 --- a/src/anim.cpp +++ b/src/anim.cpp @@ -8,10 +8,11 @@ #include "rwplg.h" #include "rwpipeline.h" #include "rwobjects.h" +#include "rwengine.h" #include "rwanim.h" #include "rwplugins.h" -#define PLUGIN_ID 0 +#define PLUGIN_ID ID_ANIMANIMATION namespace rw { @@ -55,7 +56,7 @@ Animation::create(AnimInterpolatorInfo *interpInfo, int32 numFrames, int32 sz = sizeof(Animation) + numFrames*interpInfo->animKeyFrameSize + interpInfo->customDataSize; - uint8 *data = (uint8*)malloc(sz); + uint8 *data = (uint8*)rwMalloc(sz, MEMDUR_EVENT | ID_ANIMANIMATION); if(data == nil){ RWERROR((ERR_ALLOC, sz)); return nil; @@ -75,7 +76,7 @@ Animation::create(AnimInterpolatorInfo *interpInfo, int32 numFrames, void Animation::destroy(void) { - free(this); + rwFree(this); } int32 @@ -179,7 +180,7 @@ AnimInterpolator::create(int32 numNodes, int32 maxFrameSize) if(sizeof(void*) > 4) realsz += 16; sz = sizeof(AnimInterpolator) + numNodes*realsz; - interp = (AnimInterpolator*)malloc(sz); + interp = (AnimInterpolator*)rwMalloc(sz, MEMDUR_EVENT | ID_ANIMANIMATION); if(interp == nil){ RWERROR((ERR_ALLOC, sz)); return nil; @@ -198,7 +199,7 @@ AnimInterpolator::create(int32 numNodes, int32 maxFrameSize) void AnimInterpolator::destroy(void) { - free(this); + rwFree(this); } bool32 diff --git a/src/base.cpp b/src/base.cpp index 9b62b11..838a780 100755 --- a/src/base.cpp +++ b/src/base.cpp @@ -143,12 +143,12 @@ V3d::transformVectors(V3d *out, V3d *in, int32 n, Matrix *m) // Matrix // -static Matrix::Tolerance matrixDefaultTolerance = { 0.01, 0.01, 0.01 }; +static Matrix::Tolerance matrixDefaultTolerance = { 0.01f, 0.01f, 0.01f }; Matrix* Matrix::create(void) { - Matrix *m = (Matrix*)malloc(sizeof(Matrix)); + Matrix *m = (Matrix*)rwMalloc(sizeof(Matrix), MEMDUR_EVENT | ID_MATRIX); m->setIdentity(); return m; } @@ -156,7 +156,7 @@ Matrix::create(void) void Matrix::destroy(void) { - free(this); + rwFree(this); } void @@ -770,13 +770,13 @@ StreamFile::close(void) uint32 StreamFile::write(const void *data, uint32 length) { - return fwrite(data, length, 1, this->file); + return (uint32)fwrite(data, length, 1, this->file); } uint32 StreamFile::read(void *data, uint32 length) { - return fread(data, length, 1, this->file); + return (uint32)fread(data, length, 1, this->file); } void diff --git a/src/camera.cpp b/src/camera.cpp index 363c35f..489fe5b 100755 --- a/src/camera.cpp +++ b/src/camera.cpp @@ -8,7 +8,7 @@ #include "rwobjects.h" #include "rwengine.h" -#define PLUGIN_ID 0 +#define PLUGIN_ID ID_CAMERA namespace rw { @@ -268,7 +268,7 @@ worldCameraSync(ObjectWithFrame *obj) Camera* Camera::create(void) { - Camera *cam = (Camera*)malloc(s_plglist.size); + Camera *cam = (Camera*)rwMalloc(s_plglist.size, MEMDUR_EVENT | ID_CAMERA); if(cam == nil){ RWERROR((ERR_ALLOC, s_plglist.size)); return nil; @@ -325,7 +325,7 @@ Camera::destroy(void) s_plglist.destruct(this); if(this->clump) this->inClump.remove(); - free(this); + rwFree(this); } void diff --git a/src/clump.cpp b/src/clump.cpp index 7f9fbb7..1d02d84 100644 --- a/src/clump.cpp +++ b/src/clump.cpp @@ -23,7 +23,7 @@ PluginList Atomic::s_plglist = { sizeof(Atomic), sizeof(Atomic), nil, nil }; Clump* Clump::create(void) { - Clump *clump = (Clump*)malloc(s_plglist.size); + Clump *clump = (Clump*)rwMalloc(s_plglist.size, MEMDUR_EVENT | ID_CLUMP); if(clump == nil){ RWERROR((ERR_ALLOC, s_plglist.size)); return nil; @@ -66,7 +66,7 @@ Clump::destroy(void) Camera::fromClump(lnk)->destroy(); if(f = this->getFrame(), f) f->destroyHierarchy(); - free(this); + rwFree(this); } Clump* @@ -120,7 +120,7 @@ Clump::streamRead(Stream *stream) numGeometries = stream->readI32(); if(numGeometries){ size_t sz = numGeometries*sizeof(Geometry*); - geometryList = (Geometry**)malloc(sz); + geometryList = (Geometry**)rwMalloc(sz, MEMDUR_FUNCTION | ID_CLUMP); if(geometryList == nil){ RWERROR((ERR_ALLOC, sz)); goto fail; @@ -193,8 +193,8 @@ Clump::streamRead(Stream *stream) for(int32 i = 0; i < numGeometries; i++) if(geometryList[i]) geometryList[i]->destroy(); - free(geometryList); - free(frmlst.frames); + rwFree(geometryList); + rwFree(frmlst.frames); if(s_plglist.streamRead(stream, clump)) return clump; @@ -202,9 +202,9 @@ failgeo: for(int32 i = 0; i < numGeometries; i++) if(geometryList[i]) geometryList[i]->destroy(); - free(geometryList); + rwFree(geometryList); fail: - free(frmlst.frames); + rwFree(frmlst.frames); clump->destroy(); return nil; } @@ -224,7 +224,7 @@ Clump::streamWrite(Stream *stream) FrameList_ frmlst; frmlst.numFrames = this->getFrame()->count(); - frmlst.frames = (Frame**)malloc(frmlst.numFrames*sizeof(Frame*)); + frmlst.frames = (Frame**)rwMalloc(frmlst.numFrames*sizeof(Frame*), MEMDUR_FUNCTION | ID_CLUMP); makeFrameList(this->getFrame(), frmlst.frames); frmlst.streamWrite(stream); @@ -262,7 +262,7 @@ Clump::streamWrite(Stream *stream) c->streamWrite(stream); } - free(frmlst.frames); + rwFree(frmlst.frames); s_plglist.streamWrite(stream, this); return true; @@ -336,7 +336,7 @@ worldAtomicSync(ObjectWithFrame *obj) Atomic* Atomic::create(void) { - Atomic *atomic = (Atomic*)malloc(s_plglist.size); + Atomic *atomic = (Atomic*)rwMalloc(s_plglist.size, MEMDUR_EVENT | ID_ATOMIC); if(atomic == nil){ RWERROR((ERR_ALLOC, s_plglist.size)); return nil; @@ -389,7 +389,7 @@ Atomic::destroy(void) if(this->clump) this->inClump.remove(); this->setFrame(nil); - free(this); + rwFree(this); } void diff --git a/src/engine.cpp b/src/engine.cpp index 0b7b53a..77fa22a 100755 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -23,6 +23,10 @@ namespace rw { Engine *engine; 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 *realloc_h(void *p, size_t sz, uint32 hint) { return realloc(p, sz); } // This function mainly registers engine plugins // RW initializes memory related things here too and @@ -36,6 +40,10 @@ Engine::init(void) return 0; } + memfuncs.malloc = malloc_h; + memfuncs.realloc = realloc_h; + memfuncs.free = free; + PluginList init = { sizeof(Driver), sizeof(Driver), nil, nil }; for(uint i = 0; i < NUM_PLATFORMS; i++) Driver::s_plglist[i] = init; @@ -64,7 +72,7 @@ Engine::open(void) } // Allocate engine - engine = (Engine*)malloc(sizeof(Engine)); + engine = (Engine*)rwMalloc(sizeof(Engine), MEMDUR_GLOBAL); engine->currentCamera = nil; engine->currentWorld = nil; engine->currentTexDictionary = nil; @@ -133,11 +141,14 @@ Engine::start(EngineStartParams *p) void Engine::term(void) { + // TODO } void Engine::close(void) { + // TODO + rwFree(engine); } void diff --git a/src/frame.cpp b/src/frame.cpp index ff635d2..357dc82 100644 --- a/src/frame.cpp +++ b/src/frame.cpp @@ -6,8 +6,9 @@ #include "rwplg.h" #include "rwpipeline.h" #include "rwobjects.h" +#include "rwengine.h" -#define PLUGIN_ID 0 +#define PLUGIN_ID ID_FRAMELIST namespace rw { @@ -17,7 +18,7 @@ PluginList Frame::s_plglist = { sizeof(Frame), sizeof(Frame), nil, nil }; Frame* Frame::create(void) { - Frame *f = (Frame*)malloc(s_plglist.size); + Frame *f = (Frame*)rwMalloc(s_plglist.size, MEMDUR_EVENT | ID_FRAMELIST); if(f == nil){ RWERROR((ERR_ALLOC, s_plglist.size)); return nil; @@ -51,7 +52,7 @@ Frame::destroy(void) this->inDirtyList.remove(); for(Frame *f = this->child; f; f = f->next) f->object.parent = nil; - free(this); + rwFree(this); } void @@ -65,7 +66,7 @@ Frame::destroyHierarchy(void) s_plglist.destruct(this); if(this->object.privateFlags & Frame::HIERARCHYSYNC) this->inDirtyList.remove(); - free(this); + rwFree(this); } Frame* @@ -343,7 +344,7 @@ FrameList_::streamRead(Stream *stream) return nil; } this->numFrames = stream->readI32(); - this->frames = (Frame**)malloc(this->numFrames*sizeof(Frame*)); + this->frames = (Frame**)rwMalloc(this->numFrames*sizeof(Frame*), MEMDUR_EVENT | ID_FRAMELIST); if(this->frames == nil){ RWERROR((ERR_ALLOC, this->numFrames*sizeof(Frame*))); return nil; @@ -354,7 +355,7 @@ FrameList_::streamRead(Stream *stream) this->frames[i] = f = Frame::create(); if(f == nil){ // TODO: clean up frames? - free(this->frames); + rwFree(this->frames); return nil; } f->matrix.right = buf.right; diff --git a/src/geometry.cpp b/src/geometry.cpp index 6ea0567..63f3d81 100644 --- a/src/geometry.cpp +++ b/src/geometry.cpp @@ -9,8 +9,9 @@ #include "rwplg.h" #include "rwpipeline.h" #include "rwobjects.h" +#include "rwengine.h" -#define PLUGIN_ID 2 +#define PLUGIN_ID ID_GEOMETRY namespace rw { @@ -23,7 +24,7 @@ SurfaceProperties defaultSurfaceProps = { 1.0f, 1.0f, 1.0f }; Geometry* Geometry::create(int32 numVerts, int32 numTris, uint32 flags) { - Geometry *geo = (Geometry*)malloc(s_plglist.size); + Geometry *geo = (Geometry*)rwMalloc(s_plglist.size, MEMDUR_EVENT | ID_GEOMETRY); if(geo == nil){ RWERROR((ERR_ALLOC, s_plglist.size)); return nil; @@ -90,7 +91,7 @@ Geometry::destroy(void) delete[] this->morphTargets; delete this->meshHeader; this->matList.deinit(); - free(this); + rwFree(this); } } @@ -269,7 +270,8 @@ Geometry::addMorphTargets(int32 n) { if(n == 0) return; - MorphTarget *morphTargets = new MorphTarget[this->numMorphTargets+n]; + n += this->numMorphTargets; + MorphTarget *morphTargets = new MorphTarget[n]; memcpy(morphTargets, this->morphTargets, this->numMorphTargets*sizeof(MorphTarget)); delete[] this->morphTargets; @@ -284,7 +286,7 @@ Geometry::addMorphTargets(int32 n) m->normals = new V3d[this->numVertices]; } } - this->numMorphTargets += n; + this->numMorphTargets = n; } void @@ -332,11 +334,12 @@ Geometry::allocateData(void) for(int32 i = 0; i < this->numTexCoordSets; i++) this->texCoords[i] = new TexCoords[this->numVertices]; - MorphTarget *m = this->morphTargets; - m->vertices = new V3d[this->numVertices]; - if(this->flags & NORMALS) - m->normals = new V3d[this->numVertices]; - // TODO: morph targets (who cares anyway?) + 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]; + } } static int @@ -553,7 +556,7 @@ Geometry::removeUnusedMaterials(void) } for(int32 i = 0; i < this->matList.numMaterials; i++) this->matList.materials[i]->destroy(); - free(this->matList.materials); + rwFree(this->matList.materials); this->matList.materials = materials; this->matList.space = this->matList.numMaterials; this->matList.numMaterials = numMaterials; @@ -596,6 +599,8 @@ Geometry::removeUnusedMaterials(void) // // MaterialList // +#undef PLUGIN_ID +#define PLUGIN_ID ID_MATERIAL void MaterialList::init(void) @@ -611,7 +616,7 @@ MaterialList::deinit(void) if(this->materials){ for(int32 i = 0; i < this->numMaterials; i++) this->materials[i]->destroy(); - free(this->materials); + rwFree(this->materials); } } @@ -623,10 +628,12 @@ MaterialList::appendMaterial(Material *mat) if(this->numMaterials >= this->space){ space = this->space + 20; if(this->materials) - ml = (Material**)realloc(this->materials, - space*sizeof(Material*)); + ml = (Material**)rwRealloc(this->materials, + space*sizeof(Material*), + MEMDUR_EVENT | ID_MATERIAL); else - ml = (Material**)malloc(space*sizeof(Material*)); + ml = (Material**)rwMalloc(space*sizeof(Material*), + MEMDUR_EVENT | ID_MATERIAL); if(ml == nil) return -1; this->space = space; @@ -659,12 +666,12 @@ MaterialList::streamRead(Stream *stream, MaterialList *matlist) numMat = stream->readI32(); if(numMat == 0) return matlist; - matlist->materials = (Material**)malloc(numMat*sizeof(Material*)); + matlist->materials = (Material**)rwMalloc(numMat*sizeof(Material*), MEMDUR_EVENT | ID_MATERIAL); if(matlist->materials == nil) goto fail; matlist->space = numMat; - indices = (int32*)malloc(numMat*4); + indices = (int32*)rwMalloc(numMat*4, MEMDUR_FUNCTION | ID_MATERIAL); stream->read(indices, numMat*4); Material *m; @@ -684,10 +691,10 @@ MaterialList::streamRead(Stream *stream, MaterialList *matlist) matlist->appendMaterial(m); m->destroy(); } - free(indices); + rwFree(indices); return matlist; fail: - free(indices); + rwFree(indices); matlist->deinit(); return nil; } @@ -741,7 +748,7 @@ MaterialList::streamGetSize(void) Material* Material::create(void) { - Material *mat = (Material*)malloc(s_plglist.size); + Material *mat = (Material*)rwMalloc(s_plglist.size, MEMDUR_EVENT | ID_MATERIAL); if(mat == nil){ RWERROR((ERR_ALLOC, s_plglist.size)); return nil; @@ -780,7 +787,7 @@ Material::destroy(void) s_plglist.destruct(this); if(this->texture) this->texture->destroy(); - free(this); + rwFree(this); } } diff --git a/src/gl/gl3shader.cpp b/src/gl/gl3shader.cpp index fa16bb8..445bc98 100644 --- a/src/gl/gl3shader.cpp +++ b/src/gl/gl3shader.cpp @@ -74,7 +74,7 @@ loadfile(const char *path) } fseek(f, 0, SEEK_END); len = ftell(f); - buf = (char*)malloc(len+1); + buf = (char*)rwMalloc(len+1, MEMDUR_EVENT); rewind(f); fread(buf, 1, len, f); buf[len] = '\0'; @@ -97,10 +97,10 @@ compileshader(GLenum type, const char *src, GLuint *shader) fprintf(stderr, "Error in %s shader\n", type == GL_VERTEX_SHADER ? "vertex" : "fragment"); glGetShaderiv(shdr, GL_INFO_LOG_LENGTH, &len); - log = (char*)malloc(len); + log = (char*)rwMalloc(len, MEMDUR_FUNCTION); glGetShaderInfoLog(shdr, len, nil, log); fprintf(stderr, "%s\n", log); - free(log); + rwFree(log); return 1; } *shader = shdr; @@ -123,10 +123,10 @@ linkprogram(GLint vs, GLint fs, GLuint *program) if(!success){ fprintf(stderr, "Error in program\n"); glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &len); - log = (char*)malloc(len); + log = (char*)rwMalloc(len, MEMDUR_FUNCTION); glGetProgramInfoLog(prog, len, nil, log); fprintf(stderr, "%s\n", log); - free(log); + rwFree(log); return 1; } *program = prog; @@ -181,8 +181,8 @@ Shader::fromFiles(const char *vspath, const char *fspath) vsrc = loadfile(vspath); fsrc = loadfile(fspath); Shader *s = fromStrings(vsrc, fsrc); - free(vsrc); - free(fsrc); + rwFree(vsrc); + rwFree(fsrc); return s; } diff --git a/src/hanim.cpp b/src/hanim.cpp index d2daf6e..1cfd219 100644 --- a/src/hanim.cpp +++ b/src/hanim.cpp @@ -30,7 +30,11 @@ HAnimHierarchy* HAnimHierarchy::create(int32 numNodes, int32 *nodeFlags, int32 *nodeIDs, int32 flags, int32 maxKeySize) { - HAnimHierarchy *hier = (HAnimHierarchy*)malloc(sizeof(*hier)); + HAnimHierarchy *hier = (HAnimHierarchy*)rwMalloc(sizeof(*hier), MEMDUR_EVENT | ID_HANIM); + if(hier == nil){ + RWERROR((ERR_ALLOC, sizeof(*hier))); + return nil; + } hier->currentAnim = AnimInterpolator::create(numNodes, maxKeySize); hier->numNodes = numNodes; @@ -61,7 +65,7 @@ HAnimHierarchy::destroy(void) { delete[] (uint8*)this->matricesUnaligned; delete[] this->nodeInfo; - free(this); + rwFree(this); } static Frame* @@ -313,10 +317,10 @@ assert(t >= in1->time && t <= in2->time); void registerHAnimPlugin(void) { - hAnimOffset = Frame::registerPlugin(sizeof(HAnimData), ID_HANIMPLUGIN, + hAnimOffset = Frame::registerPlugin(sizeof(HAnimData), ID_HANIM, createHAnim, destroyHAnim, copyHAnim); - Frame::registerPluginStream(ID_HANIMPLUGIN, + Frame::registerPluginStream(ID_HANIM, readHAnim, writeHAnim, getSizeHAnim); diff --git a/src/image.cpp b/src/image.cpp index b05bc88..d5a5850 100644 --- a/src/image.cpp +++ b/src/image.cpp @@ -15,387 +15,16 @@ #include "d3d/rwd3d8.h" #include "d3d/rwd3d9.h" -#ifdef _WIN32 -/* srsly? */ -#define strdup _strdup -#endif - -#define PLUGIN_ID 0 +#define PLUGIN_ID ID_IMAGE namespace rw { -PluginList TexDictionary::s_plglist = { sizeof(TexDictionary), sizeof(TexDictionary), nil, nil }; -PluginList Texture::s_plglist = { sizeof(Texture), sizeof(Texture), nil, nil }; -PluginList Raster::s_plglist = { sizeof(Raster), sizeof(Raster), nil, nil }; - -// -// TexDictionary -// - -TexDictionary* -TexDictionary::create(void) -{ - TexDictionary *dict = (TexDictionary*)malloc(s_plglist.size); - if(dict == nil){ - RWERROR((ERR_ALLOC, s_plglist.size)); - return nil; - } - dict->object.init(TexDictionary::ID, 0); - dict->textures.init(); - s_plglist.construct(dict); - return dict; -} - -void -TexDictionary::destroy(void) -{ - if(engine->currentTexDictionary == this) - engine->currentTexDictionary = nil; - FORLIST(lnk, this->textures) - Texture::fromDict(lnk)->destroy(); - s_plglist.destruct(this); - free(this); -} - -void -TexDictionary::add(Texture *t) -{ - if(t->dict) - t->inDict.remove(); - t->dict = this; - this->textures.append(&t->inDict); -} - -Texture* -TexDictionary::find(const char *name) -{ - FORLIST(lnk, this->textures){ - Texture *tex = Texture::fromDict(lnk); - if(strncmp_ci(tex->name, name, 32) == 0) - return tex; - } - return nil; -} - -TexDictionary* -TexDictionary::streamRead(Stream *stream) -{ - if(!findChunk(stream, ID_STRUCT, nil, nil)){ - RWERROR((ERR_CHUNK, "STRUCT")); - return nil; - } - int32 numTex = stream->readI16(); - stream->readI16(); // device id (0 = unknown, 1 = d3d8, 2 = d3d9, - // 3 = gcn, 4 = null, 5 = opengl, - // 6 = ps2, 7 = softras, 8 = xbox, 9 = psp) - TexDictionary *txd = TexDictionary::create(); - if(txd == nil) - return nil; - Texture *tex; - for(int32 i = 0; i < numTex; i++){ - if(!findChunk(stream, ID_TEXTURENATIVE, nil, nil)){ - RWERROR((ERR_CHUNK, "TEXTURENATIVE")); - goto fail; - } - tex = Texture::streamReadNative(stream); - if(tex == nil) - goto fail; - Texture::s_plglist.streamRead(stream, tex); - txd->add(tex); - } - if(s_plglist.streamRead(stream, txd)) - return txd; -fail: - txd->destroy(); - return nil; -} - -void -TexDictionary::streamWrite(Stream *stream) -{ - writeChunkHeader(stream, ID_TEXDICTIONARY, this->streamGetSize()); - writeChunkHeader(stream, ID_STRUCT, 4); - int32 numTex = this->count(); - stream->writeI16(numTex); - stream->writeI16(0); - FORLIST(lnk, this->textures){ - Texture *tex = Texture::fromDict(lnk); - uint32 sz = tex->streamGetSizeNative(); - sz += 12 + Texture::s_plglist.streamGetSize(tex); - writeChunkHeader(stream, ID_TEXTURENATIVE, sz); - tex->streamWriteNative(stream); - Texture::s_plglist.streamWrite(stream, tex); - } - s_plglist.streamWrite(stream, this); -} - -uint32 -TexDictionary::streamGetSize(void) -{ - uint32 size = 12 + 4; - FORLIST(lnk, this->textures){ - Texture *tex = Texture::fromDict(lnk); - size += 12 + tex->streamGetSizeNative(); - size += 12 + Texture::s_plglist.streamGetSize(tex); - } - size += 12 + s_plglist.streamGetSize(this); - return size; -} - -void -TexDictionary::setCurrent(TexDictionary *txd) -{ - engine->currentTexDictionary = txd; -} - -TexDictionary* -TexDictionary::getCurrent(void) -{ - return engine->currentTexDictionary; -} - -// -// Texture -// - -static Texture *defaultFindCB(const char *name); -static Texture *defaultReadCB(const char *name, const char *mask); - -Texture *(*Texture::findCB)(const char *name) = defaultFindCB; -Texture *(*Texture::readCB)(const char *name, const char *mask) = defaultReadCB; - -Texture* -Texture::create(Raster *raster) -{ - Texture *tex = (Texture*)malloc(s_plglist.size); - if(tex == nil){ - RWERROR((ERR_ALLOC, s_plglist.size)); - return nil; - } - tex->dict = nil; - tex->inDict.init(); - memset(tex->name, 0, 32); - memset(tex->mask, 0, 32); - tex->filterAddressing = (WRAP << 12) | (WRAP << 8) | NEAREST; - tex->raster = raster; - tex->refCount = 1; - s_plglist.construct(tex); - return tex; -} - -void -Texture::destroy(void) -{ - this->refCount--; - if(this->refCount <= 0){ - s_plglist.destruct(this); - if(this->dict) - this->inDict.remove(); - if(this->raster) - this->raster->destroy(); - free(this); - } -} - -static Texture* -defaultFindCB(const char *name) -{ - if(engine->currentTexDictionary) - return engine->currentTexDictionary->find(name); - // TODO: RW searches *all* TXDs otherwise - return nil; -} - -static Texture* -defaultReadCB(const char *name, const char *mask) -{ - Texture *tex; - Image *img; - char *n = (char*)malloc(strlen(name) + 5); - strcpy(n, name); - strcat(n, ".tga"); - img = readTGA(n); - free(n); - if(img){ - tex = Texture::create(Raster::createFromImage(img)); - strncpy(tex->name, name, 32); - if(mask) - strncpy(tex->mask, mask, 32); - img->destroy(); - return tex; - }else - return nil; -} - -Texture* -Texture::read(const char *name, const char *mask) -{ - (void)mask; - Raster *raster = nil; - Texture *tex; - - if(tex = Texture::findCB(name), tex){ - tex->refCount++; - return tex; - } - if(engine->loadTextures){ - tex = Texture::readCB(name, mask); - if(tex == nil) - goto dummytex; - }else dummytex: if(engine->makeDummies){ - tex = Texture::create(nil); - if(tex == nil) - return nil; - strncpy(tex->name, name, 32); - if(mask) - strncpy(tex->mask, mask, 32); - raster = Raster::create(0, 0, 0, Raster::DONTALLOCATE); - tex->raster = raster; - } - if(tex && engine->currentTexDictionary){ - if(tex->dict) - tex->inDict.remove(); - engine->currentTexDictionary->add(tex); - } - return tex; -} - -Texture* -Texture::streamRead(Stream *stream) -{ - uint32 length; - char name[128], mask[128]; - if(!findChunk(stream, ID_STRUCT, nil, nil)){ - RWERROR((ERR_CHUNK, "STRUCT")); - return nil; - } - uint32 filterAddressing = stream->readU32(); - // TODO: if V addressing is 0, copy U - // if using mipmap filter mode, set automipmapping, - // if 0x10000 is set, set mipmapping - - if(!findChunk(stream, ID_STRING, &length, nil)){ - RWERROR((ERR_CHUNK, "STRING")); - return nil; - } - stream->read(name, length); - - if(!findChunk(stream, ID_STRING, &length, nil)){ - RWERROR((ERR_CHUNK, "STRING")); - return nil; - } - stream->read(mask, length); - - Texture *tex = Texture::read(name, mask); - if(tex == nil) - return nil; - if(tex->refCount == 1) - tex->filterAddressing = filterAddressing; - - if(s_plglist.streamRead(stream, tex)) - return tex; - - tex->destroy(); - return nil; -} - -bool -Texture::streamWrite(Stream *stream) -{ - int size; - char buf[36]; - writeChunkHeader(stream, ID_TEXTURE, this->streamGetSize()); - writeChunkHeader(stream, ID_STRUCT, 4); - stream->writeU32(this->filterAddressing); - - memset(buf, 0, 36); - strncpy(buf, this->name, 32); - size = strlen(buf)+4 & ~3; - writeChunkHeader(stream, ID_STRING, size); - stream->write(buf, size); - - memset(buf, 0, 36); - strncpy(buf, this->mask, 32); - size = strlen(buf)+4 & ~3; - writeChunkHeader(stream, ID_STRING, size); - stream->write(buf, size); - - s_plglist.streamWrite(stream, this); - return true; -} - -uint32 -Texture::streamGetSize(void) -{ - uint32 size = 0; - size += 12 + 4; - size += 12 + 12; - size += strlen(this->name)+4 & ~3; - size += strlen(this->mask)+4 & ~3; - size += 12 + s_plglist.streamGetSize(this); - return size; -} - -Texture* -Texture::streamReadNative(Stream *stream) -{ - if(!findChunk(stream, ID_STRUCT, nil, nil)){ - RWERROR((ERR_CHUNK, "STRUCT")); - return nil; - } - uint32 platform = stream->readU32(); - stream->seek(-16); - if(platform == FOURCC_PS2) - return ps2::readNativeTexture(stream); - if(platform == PLATFORM_D3D8) - return d3d8::readNativeTexture(stream); - if(platform == PLATFORM_D3D9) - return d3d9::readNativeTexture(stream); - if(platform == PLATFORM_XBOX) - return xbox::readNativeTexture(stream); - assert(0 && "unsupported platform"); - return nil; -} - -void -Texture::streamWriteNative(Stream *stream) -{ - if(this->raster->platform == PLATFORM_PS2) - ps2::writeNativeTexture(this, stream); - else if(this->raster->platform == PLATFORM_D3D8) - d3d8::writeNativeTexture(this, stream); - else if(this->raster->platform == PLATFORM_D3D9) - d3d9::writeNativeTexture(this, stream); - else if(this->raster->platform == PLATFORM_XBOX) - xbox::writeNativeTexture(this, stream); - else - assert(0 && "unsupported platform"); -} - -uint32 -Texture::streamGetSizeNative(void) -{ - if(this->raster->platform == PLATFORM_PS2) - return ps2::getSizeNativeTexture(this); - if(this->raster->platform == PLATFORM_D3D8) - return d3d8::getSizeNativeTexture(this); - if(this->raster->platform == PLATFORM_D3D9) - return d3d9::getSizeNativeTexture(this); - if(this->raster->platform == PLATFORM_XBOX) - return xbox::getSizeNativeTexture(this); - assert(0 && "unsupported platform"); - return 0; -} - -// -// Image -// // TODO: full 16 bit support Image* Image::create(int32 width, int32 height, int32 depth) { - Image *img = (Image*)malloc(sizeof(Image)); + Image *img = (Image*)rwMalloc(sizeof(Image), MEMDUR_EVENT | ID_IMAGE); if(img == nil){ RWERROR((ERR_ALLOC, sizeof(Image))); return nil; @@ -414,7 +43,7 @@ void Image::destroy(void) { this->free(); - ::free(this); + rwFree(this); } void @@ -836,14 +465,25 @@ Image::extractMask(void) static char *searchPaths = nil; int numSearchPaths = 0; +static char* +rwstrdup(const char *s) +{ + char *t; + int32 len = strlen(s)+1; + t = (char*)rwMalloc(len, MEMDUR_EVENT); + if(t) + memcpy(t, s, len); + return t; +} + void Image::setSearchPath(const char *path) { char *p, *end; - ::free(searchPaths); + rwFree(searchPaths); numSearchPaths = 0; if(path) - searchPaths = p = strdup(path); + searchPaths = p = rwstrdup(path); else{ searchPaths = nil; return; @@ -878,12 +518,12 @@ Image::getFilename(const char *name) if(f){ fclose(f); printf("found %s\n", name); - return strdup(name); + return rwstrdup(name); } return nil; }else for(int i = 0; i < numSearchPaths; i++){ - s = (char*)malloc(strlen(p)+len); + s = (char*)rwMalloc(strlen(p)+len, MEMDUR_EVENT | ID_IMAGE); if(s == nil){ RWERROR((ERR_ALLOC, strlen(p)+len)); return nil; @@ -896,88 +536,10 @@ Image::getFilename(const char *name) printf("found %s\n", name); return s; } - ::free(s); + rwFree(s); p += strlen(p) + 1; } return nil; } -// -// Raster -// - -Raster* -Raster::create(int32 width, int32 height, int32 depth, int32 format, int32 platform) -{ - // TODO: pass arguments through to the driver and create the raster there - Raster *raster = (Raster*)malloc(s_plglist.size); - assert(raster != nil); - raster->platform = platform ? platform : rw::platform; - raster->type = format & 0x7; - raster->flags = format & 0xF8; - raster->format = format & 0xFF00; - raster->width = width; - raster->height = height; - raster->depth = depth; - raster->pixels = raster->palette = nil; - s_plglist.construct(raster); - -// printf("%d %d %d %d\n", raster->type, raster->width, raster->height, raster->depth); - engine->driver[raster->platform]->rasterCreate(raster); - return raster; -} - -void -Raster::destroy(void) -{ - s_plglist.destruct(this); -// delete[] this->texels; -// delete[] this->palette; - free(this); -} - -uint8* -Raster::lock(int32 level) -{ - return engine->driver[this->platform]->rasterLock(this, level); -} - -void -Raster::unlock(int32 level) -{ - engine->driver[this->platform]->rasterUnlock(this, level); -} - -int32 -Raster::getNumLevels(void) -{ - return engine->driver[this->platform]->rasterNumLevels(this); -} - -int32 -Raster::calculateNumLevels(int32 width, int32 height) -{ - int32 size = width >= height ? width : height; - int32 n; - for(n = 0; size != 0; n++) - size /= 2; - return n; -} - -Raster* -Raster::createFromImage(Image *image, int32 platform) -{ - Raster *raster = Raster::create(image->width, image->height, - image->depth, TEXTURE | DONTALLOCATE, - platform); - engine->driver[raster->platform]->rasterFromImage(raster, image); - return raster; -} - -Image* -Raster::toImage(void) -{ - return engine->driver[this->platform]->rasterToImage(this); -} - } diff --git a/src/light.cpp b/src/light.cpp index 21ced14..7220256 100644 --- a/src/light.cpp +++ b/src/light.cpp @@ -6,8 +6,9 @@ #include "rwplg.h" #include "rwpipeline.h" #include "rwobjects.h" +#include "rwengine.h" -#define PLUGIN_ID 2 +#define PLUGIN_ID ID_LIGHT namespace rw { @@ -28,7 +29,7 @@ worldLightSync(ObjectWithFrame *obj) Light* Light::create(int32 type) { - Light *light = (Light*)malloc(s_plglist.size); + Light *light = (Light*)rwMalloc(s_plglist.size, MEMDUR_EVENT | ID_LIGHT); if(light == nil){ RWERROR((ERR_ALLOC, s_plglist.size)); return nil; @@ -65,7 +66,7 @@ Light::destroy(void) if(this->clump) this->inClump.remove(); // we do not remove from world, be careful - free(this); + rwFree(this); } void diff --git a/src/plg.cpp b/src/plg.cpp index 2b94ecb..610d00a 100644 --- a/src/plg.cpp +++ b/src/plg.cpp @@ -8,6 +8,9 @@ #include "rwbase.h" #include "rwerror.h" #include "rwplg.h" +#include "rwpipeline.h" +#include "rwobjects.h" +#include "rwengine.h" namespace rw { @@ -103,7 +106,7 @@ int32 PluginList::registerPlugin(int32 size, uint32 id, Constructor ctor, Destructor dtor, CopyConstructor copy) { - Plugin *p = (Plugin*)malloc(sizeof(Plugin)); + Plugin *p = (Plugin*)rwMalloc(sizeof(Plugin), MEMDUR_GLOBAL); p->offset = this->size; this->size += size; int32 round = sizeof(void*)-1; diff --git a/src/ps2/ps2raster.cpp b/src/ps2/ps2raster.cpp index 292e7a8..11b2275 100644 --- a/src/ps2/ps2raster.cpp +++ b/src/ps2/ps2raster.cpp @@ -86,7 +86,7 @@ mallocalign(size_t size, int32 alignment) { void *p; void **pp; - p = malloc(size + alignment + sizeof(void*)); + p = rwMalloc(size + alignment + sizeof(void*), MEMDUR_EVENT | ID_RASTERPS2); if(p == nil) return nil; pp = (void**)(((uintptr)p + sizeof(void*) + alignment)&~(alignment-1)); pp[-1] = p; @@ -99,7 +99,7 @@ freealign(void *p) void *pp; if(p == nil) return; pp = ((void**)p)[-1]; - free(pp); + rwFree(pp); } // TODO: these depend on video mode, set in deviceSystem! @@ -391,13 +391,13 @@ static uint8 blockmaprev_PSMCT16[32] = { static void calcOffsets(int32 width_Px, int32 height_Px, int32 psm, uint64 *bufferBase_B, uint64 *bufferWidth_W, uint32 *trxpos, uint32 *totalSize, uint32 *paletteBase) { - int32 pageWidth_Px, pageHeight_Px; - int32 blockWidth_Px, blockHeight_Px; - int32 mindim_Px; + uint32 pageWidth_Px, pageHeight_Px; + uint32 blockWidth_Px, blockHeight_Px; + uint32 mindim_Px; int32 nlevels; int32 n; - int32 mipw_Px, miph_Px; - int32 lastmipw_Px, lastmiph_Px; + uint32 mipw_Px, miph_Px; + uint32 lastmipw_Px, lastmiph_Px; uint32 bufferHeight_P[8]; uint32 bufferPage_B[8]; // address of page in which the level is allocated uint32 xoff_Px, yoff_Px; // x/y offset the last level starts at @@ -408,7 +408,7 @@ calcOffsets(int32 width_Px, int32 height_Px, int32 psm, uint64 *bufferBase_B, ui uint32 widthstack_Px[8]; uint32 heightstack_Px[8]; uint32 basestack_B[8]; - int32 flag; + uint32 flag; switch(psm){ case PSMCT32: @@ -652,7 +652,7 @@ calcOffsets(int32 width_Px, int32 height_Px, int32 psm, uint64 *bufferBase_B, ui // the R bits are the block's row in a row of pages // We want to swap P and R: PPRRRCC bufferBase_B[n] = - (bufferBase_B[n] & ~(bufpagestride_B - PAGEWIDTH_B)) // mask out R and P + (bufferBase_B[n] & ~((uint64)bufpagestride_B - PAGEWIDTH_B)) // mask out R and P | ((bufferBase_B[n] & (bufwidth_B - PAGEWIDTH_B)) * (bufpagestride_B/bufwidth_B)) // extract P and shift left | ((bufferBase_B[n] & (bufpagestride_B - bufwidth_B)) / (bufwidth_B/PAGEWIDTH_B)); // extract R and shift right } @@ -968,8 +968,8 @@ createTexRaster(Raster *raster) ras->pixelSize = ALIGN16(raster->stride*raster->height); ras->paletteSize = paletteWidth*paletteHeight*paletteDepth; - ras->miptbp1 = 1<<54 | 1<<34 | 1<<14; - ras->miptbp2 = 1<<54 | 1<<34 | 1<<14; + ras->miptbp1 = 1ULL<<54 | 1ULL<<34 | 1ULL<<14; + ras->miptbp2 = 1ULL<<54 | 1ULL<<34 | 1ULL<<14; ras->tex1low = 0; // one mipmap level // find out number of pages needed @@ -1010,8 +1010,8 @@ createTexRaster(Raster *raster) th << 30 | tcc << 34 | cpsm << 51 | - 0 << 55 | // csm0 - 0 << 56 | // entry offset + 0ULL << 55 | // csm0 + 0ULL << 56 | // entry offset cld << 61; diff --git a/src/rwbase.h b/src/rwbase.h index eac18d1..ac934f3 100644 --- a/src/rwbase.h +++ b/src/rwbase.h @@ -381,11 +381,12 @@ enum Platform // SOFTRAS PLATFORM_D3D8 = 8, PLATFORM_D3D9 = 9, + // PSP // non-stock-RW platforms - PLATFORM_WDGL = 10, // WarDrum OpenGL - PLATFORM_GL3 = 11, // my GL3 implementation + PLATFORM_WDGL = 11, // WarDrum OpenGL + PLATFORM_GL3 = 12, // my GL3 implementation NUM_PLATFORMS, @@ -404,6 +405,8 @@ enum VendorID VEND_PLATFORM = 10, }; +// TODO: modules (VEND_CRITERIONINT) + enum PluginID { // Core @@ -415,6 +418,8 @@ enum PluginID ID_TEXTURE = MAKEPLUGINID(VEND_CORE, 0x06), ID_MATERIAL = MAKEPLUGINID(VEND_CORE, 0x07), ID_MATLIST = MAKEPLUGINID(VEND_CORE, 0x08), + ID_WORLD = MAKEPLUGINID(VEND_CORE, 0x0B), + ID_MATRIX = MAKEPLUGINID(VEND_CORE, 0x0D), ID_FRAMELIST = MAKEPLUGINID(VEND_CORE, 0x0E), ID_GEOMETRY = MAKEPLUGINID(VEND_CORE, 0x0F), ID_CLUMP = MAKEPLUGINID(VEND_CORE, 0x10), @@ -422,6 +427,7 @@ enum PluginID ID_ATOMIC = MAKEPLUGINID(VEND_CORE, 0x14), ID_TEXTURENATIVE = MAKEPLUGINID(VEND_CORE, 0x15), ID_TEXDICTIONARY = MAKEPLUGINID(VEND_CORE, 0x16), + ID_IMAGE = MAKEPLUGINID(VEND_CORE, 0x18), ID_GEOMETRYLIST = MAKEPLUGINID(VEND_CORE, 0x1A), ID_ANIMANIMATION = MAKEPLUGINID(VEND_CORE, 0x1B), ID_RIGHTTORENDER = MAKEPLUGINID(VEND_CORE, 0x1F), @@ -430,7 +436,7 @@ enum PluginID // Toolkit ID_SKYMIPMAP = MAKEPLUGINID(VEND_CRITERIONTK, 0x10), ID_SKIN = MAKEPLUGINID(VEND_CRITERIONTK, 0x16), - ID_HANIMPLUGIN = MAKEPLUGINID(VEND_CRITERIONTK, 0x1E), + ID_HANIM = MAKEPLUGINID(VEND_CRITERIONTK, 0x1E), ID_USERDATA = MAKEPLUGINID(VEND_CRITERIONTK, 0x1F), ID_MATFX = MAKEPLUGINID(VEND_CRITERIONTK, 0x20), ID_PDS = MAKEPLUGINID(VEND_CRITERIONTK, 0x31), diff --git a/src/rwengine.h b/src/rwengine.h index dd8352d..be75ff6 100755 --- a/src/rwengine.h +++ b/src/rwengine.h @@ -94,6 +94,26 @@ struct Driver struct EngineStartParams; +enum MemHint +{ + MEMDUR_NA = 0, + // used inside function + MEMDUR_FUNCTION = 0x10000, + // used for one frame + MEMDUR_FRAME = 0x20000, + // used for longer time + MEMDUR_EVENT = 0x30000, + // used while the engine is running + MEMDUR_GLOBAL = 0x40000 +}; + +struct MemoryFunctions +{ + void *(*malloc)(size_t sz, uint32 hint); + void *(*realloc)(void *p, size_t sz, uint32 hint); + void (*free)(void *p); +}; + // This is for platform independent things // TODO: move more stuff into this // TODO: make this have plugins and allocate in Engine::open @@ -118,6 +138,8 @@ struct Engine Driver *driver[NUM_PLATFORMS]; Device device; + // These must always be available + static MemoryFunctions memfuncs; static State state; static bool32 init(void); @@ -136,6 +158,10 @@ 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) + namespace null { void beginUpdate(Camera*); void endUpdate(Camera*); diff --git a/src/skin.cpp b/src/skin.cpp index b99097f..d6087de 100644 --- a/src/skin.cpp +++ b/src/skin.cpp @@ -39,7 +39,7 @@ destroySkin(void *object, int32 offset, int32) Skin *skin = *PLUGINOFFSET(Skin*, object, offset); if(skin){ delete[] skin->data; - free(skin->remapIndices); + rwFree(skin->remapIndices); // delete[] skin->platformData; } delete skin; @@ -83,7 +83,7 @@ readSkinSplitData(Stream *stream, Skin *skin) skin->rleSize = stream->readI32(); if(skin->numMeshes){ sz = skin->numBones + 2*(skin->numMeshes+skin->rleSize); - data = (int8*)malloc(sz); + data = (int8*)rwMalloc(sz, MEMDUR_EVENT | ID_SKIN); stream->read(data, sz); skin->remapIndices = data; skin->rleCount = (Skin::RLEcount*)(data + skin->numBones); diff --git a/src/texture.cpp b/src/texture.cpp new file mode 100644 index 0000000..e2d7cd0 --- /dev/null +++ b/src/texture.cpp @@ -0,0 +1,468 @@ +#include +#include +#include +#include + +#include "rwbase.h" +#include "rwerror.h" +#include "rwplg.h" +#include "rwpipeline.h" +#include "rwobjects.h" +#include "rwengine.h" +#include "ps2/rwps2.h" +#include "d3d/rwd3d.h" +#include "d3d/rwxbox.h" +#include "d3d/rwd3d8.h" +#include "d3d/rwd3d9.h" + +#ifdef _WIN32 +/* srsly? */ +#define strdup _strdup +#endif + +#define PLUGIN_ID 0 + +namespace rw { + +PluginList TexDictionary::s_plglist = { sizeof(TexDictionary), sizeof(TexDictionary), nil, nil }; +PluginList Texture::s_plglist = { sizeof(Texture), sizeof(Texture), nil, nil }; +PluginList Raster::s_plglist = { sizeof(Raster), sizeof(Raster), nil, nil }; + +// +// TexDictionary +// + +TexDictionary* +TexDictionary::create(void) +{ + TexDictionary *dict = (TexDictionary*)rwMalloc(s_plglist.size, MEMDUR_EVENT | ID_TEXDICTIONARY); + if(dict == nil){ + RWERROR((ERR_ALLOC, s_plglist.size)); + return nil; + } + dict->object.init(TexDictionary::ID, 0); + dict->textures.init(); + s_plglist.construct(dict); + return dict; +} + +void +TexDictionary::destroy(void) +{ + if(engine->currentTexDictionary == this) + engine->currentTexDictionary = nil; + FORLIST(lnk, this->textures) + Texture::fromDict(lnk)->destroy(); + s_plglist.destruct(this); + rwFree(this); +} + +void +TexDictionary::add(Texture *t) +{ + if(t->dict) + t->inDict.remove(); + t->dict = this; + this->textures.append(&t->inDict); +} + +Texture* +TexDictionary::find(const char *name) +{ + FORLIST(lnk, this->textures){ + Texture *tex = Texture::fromDict(lnk); + if(strncmp_ci(tex->name, name, 32) == 0) + return tex; + } + return nil; +} + +TexDictionary* +TexDictionary::streamRead(Stream *stream) +{ + if(!findChunk(stream, ID_STRUCT, nil, nil)){ + RWERROR((ERR_CHUNK, "STRUCT")); + return nil; + } + int32 numTex = stream->readI16(); + stream->readI16(); // device id (0 = unknown, 1 = d3d8, 2 = d3d9, + // 3 = gcn, 4 = null, 5 = opengl, + // 6 = ps2, 7 = softras, 8 = xbox, 9 = psp) + TexDictionary *txd = TexDictionary::create(); + if(txd == nil) + return nil; + Texture *tex; + for(int32 i = 0; i < numTex; i++){ + if(!findChunk(stream, ID_TEXTURENATIVE, nil, nil)){ + RWERROR((ERR_CHUNK, "TEXTURENATIVE")); + goto fail; + } + tex = Texture::streamReadNative(stream); + if(tex == nil) + goto fail; + Texture::s_plglist.streamRead(stream, tex); + txd->add(tex); + } + if(s_plglist.streamRead(stream, txd)) + return txd; +fail: + txd->destroy(); + return nil; +} + +void +TexDictionary::streamWrite(Stream *stream) +{ + writeChunkHeader(stream, ID_TEXDICTIONARY, this->streamGetSize()); + writeChunkHeader(stream, ID_STRUCT, 4); + int32 numTex = this->count(); + stream->writeI16(numTex); + stream->writeI16(0); + FORLIST(lnk, this->textures){ + Texture *tex = Texture::fromDict(lnk); + uint32 sz = tex->streamGetSizeNative(); + sz += 12 + Texture::s_plglist.streamGetSize(tex); + writeChunkHeader(stream, ID_TEXTURENATIVE, sz); + tex->streamWriteNative(stream); + Texture::s_plglist.streamWrite(stream, tex); + } + s_plglist.streamWrite(stream, this); +} + +uint32 +TexDictionary::streamGetSize(void) +{ + uint32 size = 12 + 4; + FORLIST(lnk, this->textures){ + Texture *tex = Texture::fromDict(lnk); + size += 12 + tex->streamGetSizeNative(); + size += 12 + Texture::s_plglist.streamGetSize(tex); + } + size += 12 + s_plglist.streamGetSize(this); + return size; +} + +void +TexDictionary::setCurrent(TexDictionary *txd) +{ + engine->currentTexDictionary = txd; +} + +TexDictionary* +TexDictionary::getCurrent(void) +{ + return engine->currentTexDictionary; +} + +// +// Texture +// + +static Texture *defaultFindCB(const char *name); +static Texture *defaultReadCB(const char *name, const char *mask); + +Texture *(*Texture::findCB)(const char *name) = defaultFindCB; +Texture *(*Texture::readCB)(const char *name, const char *mask) = defaultReadCB; + +Texture* +Texture::create(Raster *raster) +{ + Texture *tex = (Texture*)rwMalloc(s_plglist.size, MEMDUR_EVENT | ID_TEXTURE); + if(tex == nil){ + RWERROR((ERR_ALLOC, s_plglist.size)); + return nil; + } + tex->dict = nil; + tex->inDict.init(); + memset(tex->name, 0, 32); + memset(tex->mask, 0, 32); + tex->filterAddressing = (WRAP << 12) | (WRAP << 8) | NEAREST; + tex->raster = raster; + tex->refCount = 1; + s_plglist.construct(tex); + return tex; +} + +void +Texture::destroy(void) +{ + this->refCount--; + if(this->refCount <= 0){ + s_plglist.destruct(this); + if(this->dict) + this->inDict.remove(); + if(this->raster) + this->raster->destroy(); + rwFree(this); + } +} + +static Texture* +defaultFindCB(const char *name) +{ + if(engine->currentTexDictionary) + return engine->currentTexDictionary->find(name); + // TODO: RW searches *all* TXDs otherwise + return nil; +} + +static Texture* +defaultReadCB(const char *name, const char *mask) +{ + Texture *tex; + Image *img; + char *n = (char*)rwMalloc(strlen(name) + 5, MEMDUR_FUNCTION | ID_TEXTURE); + strcpy(n, name); + strcat(n, ".tga"); + img = readTGA(n); + rwFree(n); + if(img){ + tex = Texture::create(Raster::createFromImage(img)); + strncpy(tex->name, name, 32); + if(mask) + strncpy(tex->mask, mask, 32); + img->destroy(); + return tex; + }else + return nil; +} + +Texture* +Texture::read(const char *name, const char *mask) +{ + (void)mask; + Raster *raster = nil; + Texture *tex; + + if(tex = Texture::findCB(name), tex){ + tex->refCount++; + return tex; + } + if(engine->loadTextures){ + tex = Texture::readCB(name, mask); + if(tex == nil) + goto dummytex; + }else dummytex: if(engine->makeDummies){ + tex = Texture::create(nil); + if(tex == nil) + return nil; + strncpy(tex->name, name, 32); + if(mask) + strncpy(tex->mask, mask, 32); + raster = Raster::create(0, 0, 0, Raster::DONTALLOCATE); + tex->raster = raster; + } + if(tex && engine->currentTexDictionary){ + if(tex->dict) + tex->inDict.remove(); + engine->currentTexDictionary->add(tex); + } + return tex; +} + +Texture* +Texture::streamRead(Stream *stream) +{ + uint32 length; + char name[128], mask[128]; + if(!findChunk(stream, ID_STRUCT, nil, nil)){ + RWERROR((ERR_CHUNK, "STRUCT")); + return nil; + } + uint32 filterAddressing = stream->readU32(); + // TODO: if V addressing is 0, copy U + // if using mipmap filter mode, set automipmapping, + // if 0x10000 is set, set mipmapping + + if(!findChunk(stream, ID_STRING, &length, nil)){ + RWERROR((ERR_CHUNK, "STRING")); + return nil; + } + stream->read(name, length); + + if(!findChunk(stream, ID_STRING, &length, nil)){ + RWERROR((ERR_CHUNK, "STRING")); + return nil; + } + stream->read(mask, length); + + Texture *tex = Texture::read(name, mask); + if(tex == nil) + return nil; + if(tex->refCount == 1) + tex->filterAddressing = filterAddressing; + + if(s_plglist.streamRead(stream, tex)) + return tex; + + tex->destroy(); + return nil; +} + +bool +Texture::streamWrite(Stream *stream) +{ + int size; + char buf[36]; + writeChunkHeader(stream, ID_TEXTURE, this->streamGetSize()); + writeChunkHeader(stream, ID_STRUCT, 4); + stream->writeU32(this->filterAddressing); + + memset(buf, 0, 36); + strncpy(buf, this->name, 32); + size = strlen(buf)+4 & ~3; + writeChunkHeader(stream, ID_STRING, size); + stream->write(buf, size); + + memset(buf, 0, 36); + strncpy(buf, this->mask, 32); + size = strlen(buf)+4 & ~3; + writeChunkHeader(stream, ID_STRING, size); + stream->write(buf, size); + + s_plglist.streamWrite(stream, this); + return true; +} + +uint32 +Texture::streamGetSize(void) +{ + uint32 size = 0; + size += 12 + 4; + size += 12 + 12; + size += strlen(this->name)+4 & ~3; + size += strlen(this->mask)+4 & ~3; + size += 12 + s_plglist.streamGetSize(this); + return size; +} + +Texture* +Texture::streamReadNative(Stream *stream) +{ + if(!findChunk(stream, ID_STRUCT, nil, nil)){ + RWERROR((ERR_CHUNK, "STRUCT")); + return nil; + } + uint32 platform = stream->readU32(); + stream->seek(-16); + if(platform == FOURCC_PS2) + return ps2::readNativeTexture(stream); + if(platform == PLATFORM_D3D8) + return d3d8::readNativeTexture(stream); + if(platform == PLATFORM_D3D9) + return d3d9::readNativeTexture(stream); + if(platform == PLATFORM_XBOX) + return xbox::readNativeTexture(stream); + assert(0 && "unsupported platform"); + return nil; +} + +void +Texture::streamWriteNative(Stream *stream) +{ + if(this->raster->platform == PLATFORM_PS2) + ps2::writeNativeTexture(this, stream); + else if(this->raster->platform == PLATFORM_D3D8) + d3d8::writeNativeTexture(this, stream); + else if(this->raster->platform == PLATFORM_D3D9) + d3d9::writeNativeTexture(this, stream); + else if(this->raster->platform == PLATFORM_XBOX) + xbox::writeNativeTexture(this, stream); + else + assert(0 && "unsupported platform"); +} + +uint32 +Texture::streamGetSizeNative(void) +{ + if(this->raster->platform == PLATFORM_PS2) + return ps2::getSizeNativeTexture(this); + if(this->raster->platform == PLATFORM_D3D8) + return d3d8::getSizeNativeTexture(this); + if(this->raster->platform == PLATFORM_D3D9) + return d3d9::getSizeNativeTexture(this); + if(this->raster->platform == PLATFORM_XBOX) + return xbox::getSizeNativeTexture(this); + assert(0 && "unsupported platform"); + return 0; +} + +// +// Raster +// + +Raster* +Raster::create(int32 width, int32 height, int32 depth, int32 format, int32 platform) +{ + // TODO: pass arguments through to the driver and create the raster there + Raster *raster = (Raster*)rwMalloc(s_plglist.size, MEMDUR_EVENT); // TODO + assert(raster != nil); + raster->platform = platform ? platform : rw::platform; + raster->type = format & 0x7; + raster->flags = format & 0xF8; + raster->format = format & 0xFF00; + raster->width = width; + raster->height = height; + raster->depth = depth; + raster->pixels = raster->palette = nil; + s_plglist.construct(raster); + +// printf("%d %d %d %d\n", raster->type, raster->width, raster->height, raster->depth); + engine->driver[raster->platform]->rasterCreate(raster); + return raster; +} + +void +Raster::destroy(void) +{ + s_plglist.destruct(this); +// delete[] this->texels; +// delete[] this->palette; + rwFree(this); +} + +uint8* +Raster::lock(int32 level) +{ + return engine->driver[this->platform]->rasterLock(this, level); +} + +void +Raster::unlock(int32 level) +{ + engine->driver[this->platform]->rasterUnlock(this, level); +} + +int32 +Raster::getNumLevels(void) +{ + return engine->driver[this->platform]->rasterNumLevels(this); +} + +int32 +Raster::calculateNumLevels(int32 width, int32 height) +{ + int32 size = width >= height ? width : height; + int32 n; + for(n = 0; size != 0; n++) + size /= 2; + return n; +} + +Raster* +Raster::createFromImage(Image *image, int32 platform) +{ + Raster *raster = Raster::create(image->width, image->height, + image->depth, TEXTURE | DONTALLOCATE, + platform); + engine->driver[raster->platform]->rasterFromImage(raster, image); + return raster; +} + +Image* +Raster::toImage(void) +{ + return engine->driver[this->platform]->rasterToImage(this); +} + +} diff --git a/src/tga.cpp b/src/tga.cpp index 5b79ad6..dd547bf 100644 --- a/src/tga.cpp +++ b/src/tga.cpp @@ -57,7 +57,7 @@ readTGA(const char *afilename) uint32 length; uint8 *data = getFileContents(filename, &length); assert(data != nil); - free(filename); + rwFree(filename); StreamMemory file; file.open(data, length); file.read(&header, sizeof(header)); diff --git a/src/userdata.cpp b/src/userdata.cpp index 61b3cf8..0a5f8a1 100644 --- a/src/userdata.cpp +++ b/src/userdata.cpp @@ -17,14 +17,16 @@ namespace rw { UserDataGlobals userDataGlobals; +#define udMalloc(sz) rwMalloc(sz, MEMDUR_EVENT | ID_USERDATA) + void UserDataArray::setString(int32 n, const char *s) { int32 len; char **sp = &((char**)this->data)[n]; - free(*sp); - len = strlen(s)+1; - *sp = (char*)malloc(len); + rwFree(*sp); + len = (int32)strlen(s)+1; + *sp = (char*)udMalloc(len); if(*sp) strncpy(*sp, s, len); } @@ -47,21 +49,21 @@ destroyUserData(void *object, int32 offset, int32) UserDataExtension *ext = PLUGINOFFSET(UserDataExtension, object, offset); a = ext->arrays; for(i = 0; i < ext->numArrays; i++){ - free(a->name); + rwFree(a->name); switch(a->datatype){ case USERDATASTRING: strar = (char**)a->data; for(j = 0; j < a->numElements; j++) - free(strar[j]); + rwFree(strar[j]); /* fallthrough */ case USERDATAINT: case USERDATAFLOAT: - free(a->data); + rwFree(a->data); break; } a++; } - free(ext->arrays); + rwFree(ext->arrays); ext->numArrays = 0; ext->arrays = nil; return object; @@ -76,30 +78,31 @@ copyUserData(void *dst, void *src, int32 offset, int32) UserDataExtension *srcext = PLUGINOFFSET(UserDataExtension, src, offset); UserDataExtension *dstext = PLUGINOFFSET(UserDataExtension, dst, offset); dstext->numArrays = srcext->numArrays; - dstext->arrays = (UserDataArray*)malloc(dstext->numArrays*sizeof(UserDataArray)); + dstext->arrays = (UserDataArray*)udMalloc(dstext->numArrays*sizeof(UserDataArray)); srca = srcext->arrays; dsta = srcext->arrays; for(i = 0; i < srcext->numArrays; i++){ - int32 len = strlen(srca->name)+1; - dsta->name = (char*)malloc(len); + int32 len = (int32)strlen(srca->name)+1; + dsta->name = (char*)udMalloc(len); strncpy(dsta->name, srca->name, len); dsta->datatype = srca->datatype; dsta->numElements = srca->numElements; switch(srca->datatype){ case USERDATAINT: - dsta->data = (int32*)malloc(sizeof(int32)*dsta->numElements); + dsta->data = (int32*)udMalloc(sizeof(int32)*dsta->numElements); memcpy(dsta->data, srca->data, sizeof(int32)*dsta->numElements); break; case USERDATAFLOAT: - dsta->data = (float32*)malloc(sizeof(float32)*dsta->numElements); + dsta->data = (float32*)udMalloc(sizeof(float32)*dsta->numElements); memcpy(dsta->data, srca->data, sizeof(float32)*dsta->numElements); break; case USERDATASTRING: - dststrar = (char**)malloc(sizeof(char*)*dsta->numElements); + dststrar = (char**)udMalloc(sizeof(char*)*dsta->numElements); dsta->data = dststrar; + srcstrar = (char**)srca->data; for(j = 0; j < dsta->numElements; j++){ - len = strlen(srcstrar[j])+1; - dststrar[j] = (char*)malloc(len); + len = (int32)strlen(srcstrar[j])+1; + dststrar[j] = (char*)udMalloc(len); strncpy(dststrar[j], srcstrar[j], len); } break; @@ -118,29 +121,29 @@ readUserData(Stream *stream, int32, void *object, int32 offset, int32) UserDataArray *a; UserDataExtension *ext = PLUGINOFFSET(UserDataExtension, object, offset); ext->numArrays = stream->readI32(); - ext->arrays = (UserDataArray*)malloc(ext->numArrays*sizeof(UserDataArray)); + ext->arrays = (UserDataArray*)udMalloc(ext->numArrays*sizeof(UserDataArray)); a = ext->arrays; for(i = 0; i < ext->numArrays; i++){ int32 len = stream->readI32(); - a->name = (char*)malloc(len); + a->name = (char*)udMalloc(len); stream->read(a->name, len); a->datatype = stream->readU32(); a->numElements = stream->readI32(); switch(a->datatype){ case USERDATAINT: - a->data = (int32*)malloc(sizeof(int32)*a->numElements); + a->data = (int32*)udMalloc(sizeof(int32)*a->numElements); stream->read(a->data, sizeof(int32)*a->numElements); break; case USERDATAFLOAT: - a->data = (float32*)malloc(sizeof(float32)*a->numElements); + a->data = (float32*)udMalloc(sizeof(float32)*a->numElements); stream->read(a->data, sizeof(float32)*a->numElements); break; case USERDATASTRING: - strar = (char**)malloc(sizeof(char*)*a->numElements); + strar = (char**)udMalloc(sizeof(char*)*a->numElements); a->data = strar; for(j = 0; j < a->numElements; j++){ len = stream->readI32(); - strar[j] = (char*)malloc(len); + strar[j] = (char*)udMalloc(len); stream->read(strar[j], len); } break; @@ -161,7 +164,7 @@ writeUserData(Stream *stream, int32, void *object, int32 offset, int32) stream->writeI32(ext->numArrays); a = ext->arrays; for(i = 0; i < ext->numArrays; i++){ - len = strlen(a->name)+1; + len = (int32)strlen(a->name)+1; stream->writeI32(len); stream->write(a->name, len); stream->writeU32(a->datatype); @@ -176,7 +179,7 @@ writeUserData(Stream *stream, int32, void *object, int32 offset, int32) case USERDATASTRING: strar = (char**)a->data; for(j = 0; j < a->numElements; j++){ - len = strlen(strar[j])+1; + len = (int32)strlen(strar[j])+1; stream->writeI32(len); stream->write(strar[j], len); } @@ -201,7 +204,7 @@ getSizeUserData(void *object, int32 offset, int32) size = 4; // numArrays a = ext->arrays; for(i = 0; i < ext->numArrays; i++){ - len = strlen(a->name)+1; + len = (int32)strlen(a->name)+1; size += 4 + len + 4 + 4; // name len, name, type, numElements switch(a->datatype){ case USERDATAINT: @@ -213,7 +216,7 @@ getSizeUserData(void *object, int32 offset, int32) case USERDATASTRING: strar = (char**)a->data; for(j = 0; j < a->numElements; j++){ - len = strlen(strar[j])+1; + len = (int32)strlen(strar[j])+1; size += 4 + len; // len and string } break; @@ -235,17 +238,17 @@ add(UserDataExtension *ext, const char *name, int32 datatype, int32 numElements) if(ext->arrays[i].datatype == USERDATANA) goto alloc; // have to realloc - a = (UserDataArray*)malloc((ext->numArrays+1)*sizeof(UserDataArray)); + a = (UserDataArray*)udMalloc((ext->numArrays+1)*sizeof(UserDataArray)); if(a == nil) return -1; memcpy(a, ext->arrays, ext->numArrays*sizeof(UserDataArray)); - free(ext->arrays); + rwFree(ext->arrays); ext->arrays = a; i = ext->numArrays++; alloc: a = &ext->arrays[i]; - len = strlen(name)+1; - a->name = (char*)malloc(len+1); + len = (int32)strlen(name)+1; + a->name = (char*)udMalloc(len+1); assert(a->name); strncpy(a->name, name, len); a->datatype = datatype; @@ -253,7 +256,7 @@ alloc: typesz = datatype == USERDATAINT ? sizeof(int32) : datatype == USERDATAFLOAT ? sizeof(float32) : datatype == USERDATASTRING ? sizeof(char*) : 0; - a->data = malloc(typesz*numElements); + a->data = udMalloc(typesz*numElements); assert(a->data); memset(a->data, 0, typesz*numElements); return i; @@ -265,14 +268,14 @@ remove(UserDataExtension *ext, int32 n) int32 i; UserDataArray *a = &ext->arrays[n]; if(a->name){ - free(a->name); + rwFree(a->name); a->name = nil; } if(a->datatype == USERDATASTRING) for(i = 0; i < a->numElements; i++) - free(((char**)a->data)[i]); + rwFree(((char**)a->data)[i]); if(a->data){ - free(a->data); + rwFree(a->data); a->data = nil; } a->datatype = USERDATANA; diff --git a/src/uvanim.cpp b/src/uvanim.cpp index 2e5460b..fcfd32f 100644 --- a/src/uvanim.cpp +++ b/src/uvanim.cpp @@ -8,6 +8,7 @@ #include "rwplg.h" #include "rwpipeline.h" #include "rwobjects.h" +#include "rwengine.h" #include "rwanim.h" #include "rwplugins.h" @@ -32,7 +33,7 @@ UVAnimDictionary *currentUVAnimDictionary; UVAnimDictionary* UVAnimDictionary::create(void) { - UVAnimDictionary *dict = (UVAnimDictionary*)malloc(sizeof(UVAnimDictionary)); + UVAnimDictionary *dict = (UVAnimDictionary*)rwMalloc(sizeof(UVAnimDictionary), MEMDUR_EVENT | ID_UVANIMATION); if(dict == nil){ RWERROR((ERR_ALLOC, sizeof(UVAnimDictionary))); return nil; @@ -50,7 +51,7 @@ UVAnimDictionary::destroy(void) cust->destroy(de->anim); delete de; } - free(this); + rwFree(this); } void diff --git a/src/world.cpp b/src/world.cpp index d17def9..51545b8 100755 --- a/src/world.cpp +++ b/src/world.cpp @@ -9,7 +9,7 @@ #include "rwobjects.h" #include "rwengine.h" -#define PLUGIN_ID 2 +#define PLUGIN_ID ID_WORLD namespace rw { @@ -18,7 +18,7 @@ PluginList World::s_plglist = { sizeof(World), sizeof(World), nil, nil }; World* World::create(void) { - World *world = (World*)malloc(s_plglist.size); + World *world = (World*)rwMalloc(s_plglist.size, MEMDUR_EVENT | ID_WORLD); if(world == nil){ RWERROR((ERR_ALLOC, s_plglist.size)); return nil;