started moving to custom malloc/free

This commit is contained in:
aap 2017-08-24 15:10:34 +02:00
parent 6d38dea0d9
commit 040bb6cb51
22 changed files with 675 additions and 580 deletions

View File

@ -71,6 +71,7 @@ project "librw"
project "dumprwtree"
kind "ConsoleApp"
targetdir (Bindir)
removeplatforms { "*gl3", "*d3d9", "ps2" }
files { "tools/dumprwtree/*" }
includedirs { "." }
libdirs { Libdir }

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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;
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];
// TODO: morph targets (who cares anyway?)
}
}
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);
}
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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);
}
}

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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),

View File

@ -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*);

View File

@ -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);

468
src/texture.cpp Normal file
View File

@ -0,0 +1,468 @@
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cassert>
#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);
}
}

View File

@ -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));

View File

@ -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;

View File

@ -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

View File

@ -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;