diff --git a/rw.h b/rw.h index 19e0eb5..da06c26 100644 --- a/rw.h +++ b/rw.h @@ -2,6 +2,7 @@ #include #include "src/rwbase.h" +#include "src/rwerror.h" #include "src/rwplg.h" #include "src/rwpipeline.h" #include "src/rwobjects.h" diff --git a/src/base.err b/src/base.err new file mode 100644 index 0000000..8d9d064 --- /dev/null +++ b/src/base.err @@ -0,0 +1,8 @@ +ECODE(ERR_GENERAL, + "General Error") +ECODE(ERR_ALLOC, + "Couldn't allocate 0x%X bytes") +ECODE(ERR_FILE, + "Couldn't open file %s") +ECODE(ERR_CHUNK, + "Couldn't find chunk %s") diff --git a/src/camera.cpp b/src/camera.cpp new file mode 100644 index 0000000..e6e334e --- /dev/null +++ b/src/camera.cpp @@ -0,0 +1,167 @@ +#include +#include + +#include "rwbase.h" +#include "rwerror.h" +#include "rwplg.h" +#include "rwpipeline.h" +#include "rwobjects.h" + +#define PLUGIN_ID 0 + +namespace rw { + +Camera* +Camera::create(void) +{ + Camera *cam = (Camera*)malloc(PluginBase::s_size); + if(cam == NULL){ + RWERROR((ERR_ALLOC, PluginBase::s_size)); + return NULL; + } + cam->object.object.init(Camera::ID, 0); + cam->viewWindow.set(1.0f, 1.0f); + cam->viewOffset.set(0.0f, 0.0f); + cam->nearPlane = 0.05f; + cam->farPlane = 10.0f; + cam->fogPlane = 5.0f; + cam->projection = Camera::PERSPECTIVE; + cam->clump = NULL; + cam->inClump.init(); + cam->constructPlugins(); + return cam; +} + +Camera* +Camera::clone(void) +{ + Camera *cam = Camera::create(); + if(cam == NULL) + return NULL; + cam->object.object.copy(&this->object.object); + cam->setFrame(this->getFrame()); + cam->viewWindow = this->viewWindow; + cam->viewOffset = this->viewOffset; + cam->nearPlane = this->nearPlane; + cam->farPlane = this->farPlane; + cam->fogPlane = this->fogPlane; + cam->projection = this->projection; + cam->copyPlugins(this); + return cam; +} + +void +Camera::destroy(void) +{ + this->destructPlugins(); + if(this->clump) + this->inClump.remove(); + free(this); +} + +struct CameraChunkData +{ + V2d viewWindow; + V2d viewOffset; + float32 nearPlane, farPlane; + float32 fogPlane; + int32 projection; +}; + +Camera* +Camera::streamRead(Stream *stream) +{ + CameraChunkData buf; + if(!findChunk(stream, ID_STRUCT, NULL, NULL)){ + RWERROR((ERR_CHUNK, "STRUCT")); + return NULL; + } + stream->read(&buf, sizeof(CameraChunkData)); + Camera *cam = Camera::create(); + cam->viewWindow = buf.viewWindow; + cam->viewOffset = buf.viewOffset; + cam->nearPlane = buf.nearPlane; + cam->farPlane = buf.farPlane; + cam->fogPlane = buf.fogPlane; + cam->projection = buf.projection; + cam->streamReadPlugins(stream); + return cam; + +} + +bool +Camera::streamWrite(Stream *stream) +{ + CameraChunkData buf; + writeChunkHeader(stream, ID_CAMERA, this->streamGetSize()); + writeChunkHeader(stream, ID_STRUCT, sizeof(CameraChunkData)); + buf.viewWindow = this->viewWindow; + buf.viewOffset = this->viewOffset; + buf.nearPlane = this->nearPlane; + buf.farPlane = this->farPlane; + buf.fogPlane = this->fogPlane; + buf.projection = this->projection; + stream->write(&buf, sizeof(CameraChunkData)); + this->streamWritePlugins(stream); + return true; +} + +uint32 +Camera::streamGetSize(void) +{ + return 12 + sizeof(CameraChunkData) + 12 + this->streamGetPluginSize(); +} + +void +Camera::updateProjectionMatrix(void) +{ + float32 invwx = 1.0f/this->viewWindow.x; + float32 invwy = 1.0f/this->viewWindow.y; + float32 invz = 1.0f/(this->farPlane-this->nearPlane); + if(rw::platform == PLATFORM_D3D8 || rw::platform == PLATFORM_D3D9 || + rw::platform == PLATFORM_XBOX){ + // is this all really correct? + this->projMat[0] = invwx; + this->projMat[1] = 0.0f; + this->projMat[2] = 0.0f; + this->projMat[3] = 0.0f; + + this->projMat[4] = 0.0f; + this->projMat[5] = invwy; + this->projMat[6] = 0.0f; + this->projMat[7] = 0.0f; + + if(this->projection == PERSPECTIVE){ + this->projMat[8] = this->viewOffset.x*invwx; + this->projMat[9] = this->viewOffset.y*invwy; + this->projMat[10] = this->farPlane*invz; + this->projMat[11] = 1.0f; + + this->projMat[12] = 0.0f; + this->projMat[13] = 0.0f; + this->projMat[14] = -this->nearPlane*this->projMat[10]; + this->projMat[15] = 0.0f; + }else{ + this->projMat[8] = 0.0f; + this->projMat[9] = 0.0f; + this->projMat[10] = invz; + this->projMat[11] = 0.0f; + + this->projMat[12] = this->viewOffset.x*invwx; + this->projMat[13] = this->viewOffset.y*invwy; + this->projMat[14] = -this->nearPlane*this->projMat[10]; + this->projMat[15] = 1.0f; + } + } +} + +void +Camera::setFOV(float32 fov, float32 ratio) +{ + float32 a = tan(fov*3.14159f/360.0f); + this->viewWindow.x = a; + this->viewWindow.y = a/ratio; + this->viewOffset.set(0.0f, 0.0f); +} + +} diff --git a/src/clump.cpp b/src/clump.cpp index 28cb1f2..69eb51c 100644 --- a/src/clump.cpp +++ b/src/clump.cpp @@ -1,267 +1,19 @@ #include #include -#include -#include -#include #include "rwbase.h" +#include "rwerror.h" #include "rwplg.h" #include "rwpipeline.h" #include "rwobjects.h" #include "rwengine.h" -#include "rwps2.h" -#include "rwxbox.h" -#include "rwd3d8.h" -#include "rwd3d9.h" -#include "rwwdgl.h" using namespace std; +#define PLUGIN_ID 2 + namespace rw { -LinkList Frame::dirtyList; - -Frame* -Frame::create(void) -{ - Frame *f = (Frame*)malloc(PluginBase::s_size); - assert(f != NULL); - f->object.init(Frame::ID, 0); - f->objectList.init(); - f->child = NULL; - f->next = NULL; - f->root = f; - f->matrix.setIdentity(); - f->ltm.setIdentity(); - f->constructPlugins(); - return f; -} - -Frame* -Frame::cloneHierarchy(void) -{ - Frame *frame = this->cloneAndLink(NULL); - frame->purgeClone(); - return frame; -} - -void -Frame::destroy(void) -{ - this->destructPlugins(); - Frame *parent = this->getParent(); - Frame *child; - if(parent){ - // remove from child list - child = parent->child; - if(child == this) - parent->child = this->next; - else{ - for(child = child->next; child != this; child = child->next) - ; - child->next = this->next; - } - this->object.parent = NULL; - // Doesn't seem to make much sense, blame criterion. - this->setHierarchyRoot(this); - } - for(Frame *f = this->child; f; f = f->next) - f->object.parent = NULL; - free(this); -} - -void -Frame::destroyHierarchy(void) -{ - Frame *next; - for(Frame *child = this->child; child; child = next){ - next = child->next; - child->destroyHierarchy(); - } - this->destructPlugins(); - free(this); -} - -Frame* -Frame::addChild(Frame *child, bool32 append) -{ - Frame *c; - if(child->getParent()) - child->removeChild(); - if(append){ - if(this->child == NULL) - this->child = child; - else{ - for(c = this->child; c->next; c = c->next); - c->next = child; - } - child->next = NULL; - }else{ - child->next = this->child; - this->child = child; - } - child->object.parent = this; - child->root = this->root; - for(c = child->child; c; c = c->next) - c->setHierarchyRoot(this); - if(child->object.privateFlags & Frame::HIERARCHYSYNC){ - child->inDirtyList.remove(); - child->object.privateFlags &= ~Frame::HIERARCHYSYNC; - } - this->updateObjects(); - return this; -} - -Frame* -Frame::removeChild(void) -{ - Frame *parent = this->getParent(); - Frame *child = parent->child; - if(child == this) - parent->child = this->next; - else{ - while(child->next != this) - child = child->next; - child->next = this->next; - } - this->object.parent = this->next = NULL; - this->root = this; - for(child = this->child; child; child = child->next) - child->setHierarchyRoot(this); - this->updateObjects(); - return this; -} - -Frame* -Frame::forAllChildren(Callback cb, void *data) -{ - for(Frame *f = this->child; f; f = f->next) - cb(f, data); - return this; -} - -static Frame* -countCB(Frame *f, void *count) -{ - (*(int32*)count)++; - f->forAllChildren(countCB, count); - return f; -} - -int32 -Frame::count(void) -{ - int32 count = 1; - this->forAllChildren(countCB, (void*)&count); - return count; -} - -static void -syncRecurse(Frame *frame, uint8 flags) -{ - uint8 flg; - for(; frame; frame = frame->next){ - flg = flags | frame->object.privateFlags; - if(flg & Frame::SUBTREESYNCLTM){ - Matrix::mult(&frame->ltm, &frame->getParent()->ltm, &frame->matrix); - frame->object.privateFlags &= ~Frame::SUBTREESYNCLTM; - } - syncRecurse(frame->child, flg); - } -} - -void -Frame::syncHierarchyLTM(void) -{ - Frame *child; - uint8 flg; - if(this->object.privateFlags & Frame::SUBTREESYNCLTM) - this->ltm = this->matrix; - for(child = this->child; child; child = child->next){ - flg = this->object.privateFlags | child->object.privateFlags; - if(flg & Frame::SUBTREESYNCLTM){ - Matrix::mult(&child->ltm, &this->ltm, &child->matrix); - child->object.privateFlags &= ~Frame::SUBTREESYNCLTM; - } - syncRecurse(child, flg); - } - this->object.privateFlags &= ~Frame::SYNCLTM; -} - -Matrix* -Frame::getLTM(void) -{ - if(this->root->object.privateFlags & Frame::HIERARCHYSYNCLTM) - this->root->syncHierarchyLTM(); - return &this->ltm; -} - -void -Frame::updateObjects(void) -{ - if((this->root->object.privateFlags & HIERARCHYSYNC) == 0) - Frame::dirtyList.add(&this->inDirtyList); - this->root->object.privateFlags |= HIERARCHYSYNC; - this->object.privateFlags |= SUBTREESYNC; -} - -void -Frame::setHierarchyRoot(Frame *root) -{ - this->root = root; - for(Frame *child = this->child; child; child = child->next) - child->setHierarchyRoot(root); -} - -// Clone a frame hierarchy. Link cloned frames into Frame::root of the originals. -Frame* -Frame::cloneAndLink(Frame *clonedroot) -{ - Frame *frame = Frame::create(); - if(clonedroot == NULL) - clonedroot = frame; - frame->object.copy(&this->object); - frame->matrix = this->matrix; - //memcpy(frame->matrix, this->matrix, sizeof(this->matrix)); - frame->root = clonedroot; - this->root = frame; // Remember cloned frame - for(Frame *child = this->child; child; child = child->next){ - Frame *clonedchild = child->cloneAndLink(clonedroot); - clonedchild->next = frame->child; - frame->child = clonedchild; - clonedchild->object.parent = frame; - } - frame->copyPlugins(this); - return frame; -} - -// Remove links to cloned frames from hierarchy. -void -Frame::purgeClone(void) -{ - Frame *parent = this->getParent(); - this->setHierarchyRoot(parent ? parent->root : this); -} - -static Frame* -sizeCB(Frame *f, void *size) -{ - *(int32*)size += f->streamGetPluginSize(); - f->forAllChildren(sizeCB, size); - return f; -} - -Frame** -makeFrameList(Frame *frame, Frame **flist) -{ - *flist++ = frame; - if(frame->next) - flist = makeFrameList(frame->next, flist); - if(frame->child) - flist = makeFrameList(frame->child, flist); - return flist; -} - // // Clump // @@ -270,7 +22,10 @@ Clump* Clump::create(void) { Clump *clump = (Clump*)malloc(PluginBase::s_size); - assert(clump != NULL); + if(clump == nil){ + RWERROR((ERR_ALLOC, PluginBase::s_size)); + return nil; + } clump->object.init(Clump::ID, 0); clump->atomics.init(); clump->lights.init(); @@ -318,8 +73,14 @@ Clump::streamRead(Stream *stream) uint32 length, version; int32 buf[3]; Clump *clump; - assert(findChunk(stream, ID_STRUCT, &length, &version)); + + if(!findChunk(stream, ID_STRUCT, &length, &version)){ + RWERROR((ERR_CHUNK, "STRUCT")); + return nil; + } clump = Clump::create(); + if(clump == nil) + return nil; stream->read(buf, length); int32 numAtomics = buf[0]; int32 numLights = 0; @@ -339,31 +100,68 @@ Clump::streamRead(Stream *stream) if(version >= 0x30400){ // Geometry list int32 numGeometries = 0; - assert(findChunk(stream, ID_GEOMETRYLIST, NULL, NULL)); - assert(findChunk(stream, ID_STRUCT, NULL, NULL)); + if(!findChunk(stream, ID_GEOMETRYLIST, nil, nil)){ + RWERROR((ERR_CHUNK, "GEOMETRYLIST")); + // TODO: free + return nil; + } + if(!findChunk(stream, ID_STRUCT, nil, nil)){ + RWERROR((ERR_CHUNK, "STRUCT")); + // TODO: free + return nil; + } numGeometries = stream->readI32(); if(numGeometries) geometryList = new Geometry*[numGeometries]; for(int32 i = 0; i < numGeometries; i++){ - assert(findChunk(stream, ID_GEOMETRY, NULL, NULL)); + if(!findChunk(stream, ID_GEOMETRY, nil, nil)){ + RWERROR((ERR_CHUNK, "GEOMETRY")); + // TODO: free + return nil; + } geometryList[i] = Geometry::streamRead(stream); + if(geometryList[i] == nil){ + // TODO: free + return nil; + } } } // Atomics + Atomic *a; for(int32 i = 0; i < numAtomics; i++){ - assert(findChunk(stream, ID_ATOMIC, NULL, NULL)); - Atomic *a = Atomic::streamReadClump(stream, frameList, geometryList); + if(!findChunk(stream, ID_ATOMIC, nil, nil)){ + RWERROR((ERR_CHUNK, "ATOMIC")); + // TODO: free + return nil; + } + a = Atomic::streamReadClump(stream, frameList, geometryList); + if(a == nil){ + // TODO: free + return nil; + } clump->addAtomic(a); } // Lights for(int32 i = 0; i < numLights; i++){ int32 frm; - assert(findChunk(stream, ID_STRUCT, NULL, NULL)); + if(!findChunk(stream, ID_STRUCT, nil, nil)){ + RWERROR((ERR_CHUNK, "STRUCT")); + // TODO: free + return nil; + } frm = stream->readI32(); - assert(findChunk(stream, ID_LIGHT, NULL, NULL)); + if(!findChunk(stream, ID_LIGHT, nil, nil)){ + RWERROR((ERR_CHUNK, "LIGHT")); + // TODO: free + return nil; + } Light *l = Light::streamRead(stream); + if(l == nil){ + // TODO: free + return nil; + } l->setFrame(frameList[frm]); clump->addLight(l); } @@ -371,10 +169,22 @@ Clump::streamRead(Stream *stream) // Cameras for(int32 i = 0; i < numCameras; i++){ int32 frm; - assert(findChunk(stream, ID_STRUCT, NULL, NULL)); + if(!findChunk(stream, ID_STRUCT, nil, nil)){ + RWERROR((ERR_CHUNK, "STRUCT")); + // TODO: free + return nil; + } frm = stream->readI32(); - assert(findChunk(stream, ID_CAMERA, NULL, NULL)); + if(!findChunk(stream, ID_CAMERA, nil, nil)){ + RWERROR((ERR_CHUNK, "CAMERA")); + // TODO: free + return nil; + } Camera *cam = Camera::streamRead(stream); + if(cam == nil){ + // TODO: free + return nil; + } cam->setFrame(frameList[frm]); clump->addCamera(cam); } @@ -450,6 +260,14 @@ struct FrameStreamData int32 matflag; }; +static Frame* +sizeCB(Frame *f, void *size) +{ + *(int32*)size += f->streamGetPluginSize(); + f->forAllChildren(sizeCB, size); + return f; +} + uint32 Clump::streamGetSize(void) { @@ -498,13 +316,19 @@ Clump::render(void) } } -void +bool Clump::frameListStreamRead(Stream *stream, Frame ***flp, int32 *nf) { FrameStreamData buf; int32 numFrames = 0; - assert(findChunk(stream, ID_FRAMELIST, NULL, NULL)); - assert(findChunk(stream, ID_STRUCT, NULL, NULL)); + if(!findChunk(stream, ID_FRAMELIST, nil, nil)){ + RWERROR((ERR_CHUNK, "FRAMELIST")); + return 0; + } + if(!findChunk(stream, ID_STRUCT, nil, nil)){ + RWERROR((ERR_CHUNK, "STRUCT")); + return 0; + } numFrames = stream->readI32(); Frame **frameList = new Frame*[numFrames]; for(int32 i = 0; i < numFrames; i++){ @@ -527,6 +351,7 @@ Clump::frameListStreamRead(Stream *stream, Frame ***flp, int32 *nf) frameList[i]->streamReadPlugins(stream); *nf = numFrames; *flp = frameList; + return 1; } void @@ -566,14 +391,17 @@ Atomic* Atomic::create(void) { Atomic *atomic = (Atomic*)malloc(PluginBase::s_size); - assert(atomic != NULL); + if(atomic == nil){ + RWERROR((ERR_ALLOC, PluginBase::s_size)); + return nil; + } atomic->object.object.init(Atomic::ID, 0); - atomic->geometry = NULL; + atomic->geometry = nil; atomic->worldBoundingSphere.center.set(0.0f, 0.0f, 0.0f); atomic->worldBoundingSphere.radius = 0.0f; - atomic->setFrame(NULL); - atomic->clump = NULL; - atomic->pipeline = NULL; + atomic->setFrame(nil); + atomic->clump = nil; + atomic->pipeline = nil; atomic->renderCB = Atomic::defaultRenderCB; atomic->object.object.flags = Atomic::COLLISIONTEST | Atomic::RENDER; atomic->constructPlugins(); @@ -603,7 +431,7 @@ Atomic::destroy(void) this->geometry->destroy(); if(this->clump) this->inClump.remove(); - this->setFrame(NULL); + this->setFrame(nil); free(this); } @@ -612,7 +440,7 @@ Atomic::removeFromClump(void) { if(this->clump){ this->inClump.remove(); - this->clump = NULL; + this->clump = nil; } } @@ -640,13 +468,26 @@ Atomic::streamReadClump(Stream *stream, { int32 buf[4]; uint32 version; - assert(findChunk(stream, ID_STRUCT, NULL, &version)); + if(!findChunk(stream, ID_STRUCT, nil, &version)){ + RWERROR((ERR_CHUNK, "STRUCT")); + return nil; + } stream->read(buf, version < 0x30400 ? 12 : 16); Atomic *atomic = Atomic::create(); + if(atomic == nil) + return nil; atomic->setFrame(frameList[buf[0]]); if(version < 0x30400){ - assert(findChunk(stream, ID_GEOMETRY, NULL, NULL)); + if(!findChunk(stream, ID_GEOMETRY, nil, nil)){ + RWERROR((ERR_CHUNK, "STRUCT")); + // TODO: free + return nil; + } atomic->geometry = Geometry::streamRead(stream); + if(atomic->geometry == nil){ + // TODO: free + return nil; + } }else atomic->geometry = geometryList[buf[1]]; atomic->object.object.flags = buf[2]; @@ -663,7 +504,7 @@ Atomic::streamWriteClump(Stream *stream, Frame **frameList, int32 numFrames) { int32 buf[4] = { 0, 0, 0, 0 }; Clump *c = this->clump; - if(c == NULL) + if(c == nil) return false; writeChunkHeader(stream, ID_ATOMIC, this->streamGetSize()); writeChunkHeader(stream, ID_STRUCT, rw::version < 0x30400 ? 12 : 16); @@ -737,7 +578,7 @@ static int32 getSizeAtomicRights(void *object, int32, int32) { Atomic *atomic = (Atomic*)object; - if(atomic->pipeline == NULL || atomic->pipeline->pluginID == 0) + if(atomic->pipeline == nil || atomic->pipeline->pluginID == 0) return -1; return 8; } @@ -745,272 +586,11 @@ getSizeAtomicRights(void *object, int32, int32) void registerAtomicRightsPlugin(void) { - Atomic::registerPlugin(0, ID_RIGHTTORENDER, NULL, NULL, NULL); + Atomic::registerPlugin(0, ID_RIGHTTORENDER, nil, nil, nil); Atomic::registerPluginStream(ID_RIGHTTORENDER, readAtomicRights, writeAtomicRights, getSizeAtomicRights); } - -// -// Light -// - -Light* -Light::create(int32 type) -{ - Light *light = (Light*)malloc(PluginBase::s_size); - assert(light != NULL); - light->object.object.init(Light::ID, type); - light->radius = 0.0f; - light->color.red = 1.0f; - light->color.green = 1.0f; - light->color.blue = 1.0f; - light->color.alpha = 1.0f; - light->minusCosAngle = 1.0f; - light->object.object.privateFlags = 1; - light->object.object.flags = LIGHTATOMICS | LIGHTWORLD; - light->clump = NULL; - light->inClump.init(); - light->constructPlugins(); - return light; -} - -void -Light::destroy(void) -{ - this->destructPlugins(); - if(this->clump) - this->inClump.remove(); - free(this); -} - -void -Light::setAngle(float32 angle) -{ - this->minusCosAngle = -cos(angle); -} - -float32 -Light::getAngle(void) -{ - return acos(-this->minusCosAngle); -} - -void -Light::setColor(float32 r, float32 g, float32 b) -{ - this->color.red = r; - this->color.green = g; - this->color.blue = b; - this->object.object.privateFlags = r == g && r == b; -} - -struct LightChunkData -{ - float32 radius; - float32 red, green, blue; - float32 minusCosAngle; - uint16 flags; - uint16 type; -}; - -Light* -Light::streamRead(Stream *stream) -{ - uint32 version; - LightChunkData buf; - assert(findChunk(stream, ID_STRUCT, NULL, &version)); - stream->read(&buf, sizeof(LightChunkData)); - Light *light = Light::create(buf.type); - light->radius = buf.radius; - light->setColor(buf.red, buf.green, buf.blue); - float32 a = buf.minusCosAngle; - if(version >= 0x30300) - light->minusCosAngle = a; - else - // tan -> -cos - light->minusCosAngle = -1.0f/sqrt(a*a+1.0f); - light->object.object.flags = (uint8)buf.flags; - light->streamReadPlugins(stream); - return light; -} - -bool -Light::streamWrite(Stream *stream) -{ - LightChunkData buf; - writeChunkHeader(stream, ID_LIGHT, this->streamGetSize()); - writeChunkHeader(stream, ID_STRUCT, sizeof(LightChunkData)); - buf.radius = this->radius; - buf.red = this->color.red; - buf.green = this->color.green; - buf.blue = this->color.blue; - if(version >= 0x30300) - buf.minusCosAngle = this->minusCosAngle; - else - buf.minusCosAngle = tan(acos(-this->minusCosAngle)); - buf.flags = this->object.object.flags; - buf.type = this->object.object.subType; - stream->write(&buf, sizeof(LightChunkData)); - - this->streamWritePlugins(stream); - return true; -} - -uint32 -Light::streamGetSize(void) -{ - return 12 + sizeof(LightChunkData) + 12 + this->streamGetPluginSize(); -} - -// -// Camera -// - -Camera* -Camera::create(void) -{ - Camera *cam = (Camera*)malloc(PluginBase::s_size); - cam->object.object.init(Camera::ID, 0); - cam->viewWindow.set(1.0f, 1.0f); - cam->viewOffset.set(0.0f, 0.0f); - cam->nearPlane = 0.05f; - cam->farPlane = 10.0f; - cam->fogPlane = 5.0f; - cam->projection = Camera::PERSPECTIVE; - cam->clump = NULL; - cam->inClump.init(); - cam->constructPlugins(); - return cam; -} - -Camera* -Camera::clone(void) -{ - Camera *cam = Camera::create(); - cam->object.object.copy(&this->object.object); - cam->setFrame(this->getFrame()); - cam->viewWindow = this->viewWindow; - cam->viewOffset = this->viewOffset; - cam->nearPlane = this->nearPlane; - cam->farPlane = this->farPlane; - cam->fogPlane = this->fogPlane; - cam->projection = this->projection; - cam->copyPlugins(this); - return cam; -} - -void -Camera::destroy(void) -{ - this->destructPlugins(); - if(this->clump) - this->inClump.remove(); - free(this); -} - -struct CameraChunkData -{ - V2d viewWindow; - V2d viewOffset; - float32 nearPlane, farPlane; - float32 fogPlane; - int32 projection; -}; - -Camera* -Camera::streamRead(Stream *stream) -{ - CameraChunkData buf; - assert(findChunk(stream, ID_STRUCT, NULL, NULL)); - stream->read(&buf, sizeof(CameraChunkData)); - Camera *cam = Camera::create(); - cam->viewWindow = buf.viewWindow; - cam->viewOffset = buf.viewOffset; - cam->nearPlane = buf.nearPlane; - cam->farPlane = buf.farPlane; - cam->fogPlane = buf.fogPlane; - cam->projection = buf.projection; - cam->streamReadPlugins(stream); - return cam; - -} - -bool -Camera::streamWrite(Stream *stream) -{ - CameraChunkData buf; - writeChunkHeader(stream, ID_CAMERA, this->streamGetSize()); - writeChunkHeader(stream, ID_STRUCT, sizeof(CameraChunkData)); - buf.viewWindow = this->viewWindow; - buf.viewOffset = this->viewOffset; - buf.nearPlane = this->nearPlane; - buf.farPlane = this->farPlane; - buf.fogPlane = this->fogPlane; - buf.projection = this->projection; - stream->write(&buf, sizeof(CameraChunkData)); - this->streamWritePlugins(stream); - return true; -} - -uint32 -Camera::streamGetSize(void) -{ - return 12 + sizeof(CameraChunkData) + 12 + this->streamGetPluginSize(); -} - -void -Camera::updateProjectionMatrix(void) -{ - float32 invwx = 1.0f/this->viewWindow.x; - float32 invwy = 1.0f/this->viewWindow.y; - float32 invz = 1.0f/(this->farPlane-this->nearPlane); - if(rw::platform == PLATFORM_D3D8 || rw::platform == PLATFORM_D3D9 || - rw::platform == PLATFORM_XBOX){ - // is this all really correct? - this->projMat[0] = invwx; - this->projMat[1] = 0.0f; - this->projMat[2] = 0.0f; - this->projMat[3] = 0.0f; - - this->projMat[4] = 0.0f; - this->projMat[5] = invwy; - this->projMat[6] = 0.0f; - this->projMat[7] = 0.0f; - - if(this->projection == PERSPECTIVE){ - this->projMat[8] = this->viewOffset.x*invwx; - this->projMat[9] = this->viewOffset.y*invwy; - this->projMat[10] = this->farPlane*invz; - this->projMat[11] = 1.0f; - - this->projMat[12] = 0.0f; - this->projMat[13] = 0.0f; - this->projMat[14] = -this->nearPlane*this->projMat[10]; - this->projMat[15] = 0.0f; - }else{ - this->projMat[8] = 0.0f; - this->projMat[9] = 0.0f; - this->projMat[10] = invz; - this->projMat[11] = 0.0f; - - this->projMat[12] = this->viewOffset.x*invwx; - this->projMat[13] = this->viewOffset.y*invwy; - this->projMat[14] = -this->nearPlane*this->projMat[10]; - this->projMat[15] = 1.0f; - } - } -} - -void -Camera::setFOV(float32 fov, float32 ratio) -{ - float32 a = tan(fov*3.14159f/360.0f); - this->viewWindow.x = a; - this->viewWindow.y = a/ratio; - this->viewOffset.set(0.0f, 0.0f); -} - } diff --git a/src/engine.cpp b/src/engine.cpp index 3b65d8b..3257ea1 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -1,5 +1,6 @@ #include -#include +#include +#include #include "rwbase.h" #include "rwplg.h" diff --git a/src/error.cpp b/src/error.cpp new file mode 100644 index 0000000..65e65af --- /dev/null +++ b/src/error.cpp @@ -0,0 +1,49 @@ +#include +#include + +#include "rwbase.h" +#include "rwerror.h" + +namespace rw { + +static Error error; + +void +setError(Error *e) +{ + error = *e; +} + +Error* +getError(Error *e) +{ + *e = error; + error.plugin = 0; + error.code = 0; + return e; +} + +#define ECODE(c, s) s, + +const char *errstrs[] = { + "No error", +#include "base.err" +}; + +#undef ECODE + +char* +dbgsprint(int32 code, ...) +{ + va_list ap; + static char strbuf[512]; + + if(code & 0x80000000) + code &= ~0x80000000; + va_start(ap, code); + vsprintf(strbuf, errstrs[code], ap); + va_end(ap); + return strbuf; +} + +} diff --git a/src/frame.cpp b/src/frame.cpp new file mode 100644 index 0000000..5bfd50b --- /dev/null +++ b/src/frame.cpp @@ -0,0 +1,262 @@ +#include +#include +#include +#include +#include + +#include "rwbase.h" +#include "rwerror.h" +#include "rwplg.h" +#include "rwpipeline.h" +#include "rwobjects.h" +#include "rwengine.h" +#include "rwps2.h" +#include "rwxbox.h" +#include "rwd3d8.h" +#include "rwd3d9.h" +#include "rwwdgl.h" + +#define PLUGIN_ID 0 + +namespace rw { + +LinkList Frame::dirtyList; + +Frame* +Frame::create(void) +{ + Frame *f = (Frame*)malloc(PluginBase::s_size); + if(f == NULL){ + RWERROR((ERR_ALLOC, PluginBase::s_size)); + return NULL; + } + f->object.init(Frame::ID, 0); + f->objectList.init(); + f->child = NULL; + f->next = NULL; + f->root = f; + f->matrix.setIdentity(); + f->ltm.setIdentity(); + f->constructPlugins(); + return f; +} + +Frame* +Frame::cloneHierarchy(void) +{ + Frame *frame = this->cloneAndLink(NULL); + frame->purgeClone(); + return frame; +} + +void +Frame::destroy(void) +{ + this->destructPlugins(); + Frame *parent = this->getParent(); + Frame *child; + if(parent){ + // remove from child list + child = parent->child; + if(child == this) + parent->child = this->next; + else{ + for(child = child->next; child != this; child = child->next) + ; + child->next = this->next; + } + this->object.parent = NULL; + // Doesn't seem to make much sense, blame criterion. + this->setHierarchyRoot(this); + } + for(Frame *f = this->child; f; f = f->next) + f->object.parent = NULL; + free(this); +} + +void +Frame::destroyHierarchy(void) +{ + Frame *next; + for(Frame *child = this->child; child; child = next){ + next = child->next; + child->destroyHierarchy(); + } + this->destructPlugins(); + free(this); +} + +Frame* +Frame::addChild(Frame *child, bool32 append) +{ + Frame *c; + if(child->getParent()) + child->removeChild(); + if(append){ + if(this->child == NULL) + this->child = child; + else{ + for(c = this->child; c->next; c = c->next); + c->next = child; + } + child->next = NULL; + }else{ + child->next = this->child; + this->child = child; + } + child->object.parent = this; + child->root = this->root; + for(c = child->child; c; c = c->next) + c->setHierarchyRoot(this); + if(child->object.privateFlags & Frame::HIERARCHYSYNC){ + child->inDirtyList.remove(); + child->object.privateFlags &= ~Frame::HIERARCHYSYNC; + } + this->updateObjects(); + return this; +} + +Frame* +Frame::removeChild(void) +{ + Frame *parent = this->getParent(); + Frame *child = parent->child; + if(child == this) + parent->child = this->next; + else{ + while(child->next != this) + child = child->next; + child->next = this->next; + } + this->object.parent = this->next = NULL; + this->root = this; + for(child = this->child; child; child = child->next) + child->setHierarchyRoot(this); + this->updateObjects(); + return this; +} + +Frame* +Frame::forAllChildren(Callback cb, void *data) +{ + for(Frame *f = this->child; f; f = f->next) + cb(f, data); + return this; +} + +static Frame* +countCB(Frame *f, void *count) +{ + (*(int32*)count)++; + f->forAllChildren(countCB, count); + return f; +} + +int32 +Frame::count(void) +{ + int32 count = 1; + this->forAllChildren(countCB, (void*)&count); + return count; +} + +static void +syncRecurse(Frame *frame, uint8 flags) +{ + uint8 flg; + for(; frame; frame = frame->next){ + flg = flags | frame->object.privateFlags; + if(flg & Frame::SUBTREESYNCLTM){ + Matrix::mult(&frame->ltm, &frame->getParent()->ltm, + &frame->matrix); + frame->object.privateFlags &= ~Frame::SUBTREESYNCLTM; + } + syncRecurse(frame->child, flg); + } +} + +void +Frame::syncHierarchyLTM(void) +{ + Frame *child; + uint8 flg; + if(this->object.privateFlags & Frame::SUBTREESYNCLTM) + this->ltm = this->matrix; + for(child = this->child; child; child = child->next){ + flg = this->object.privateFlags | child->object.privateFlags; + if(flg & Frame::SUBTREESYNCLTM){ + Matrix::mult(&child->ltm, &this->ltm, &child->matrix); + child->object.privateFlags &= ~Frame::SUBTREESYNCLTM; + } + syncRecurse(child, flg); + } + this->object.privateFlags &= ~Frame::SYNCLTM; +} + +Matrix* +Frame::getLTM(void) +{ + if(this->root->object.privateFlags & Frame::HIERARCHYSYNCLTM) + this->root->syncHierarchyLTM(); + return &this->ltm; +} + +void +Frame::updateObjects(void) +{ + if((this->root->object.privateFlags & HIERARCHYSYNC) == 0) + Frame::dirtyList.add(&this->inDirtyList); + this->root->object.privateFlags |= HIERARCHYSYNC; + this->object.privateFlags |= SUBTREESYNC; +} + +void +Frame::setHierarchyRoot(Frame *root) +{ + this->root = root; + for(Frame *child = this->child; child; child = child->next) + child->setHierarchyRoot(root); +} + +// Clone a frame hierarchy. Link cloned frames into Frame::root of the originals. +Frame* +Frame::cloneAndLink(Frame *clonedroot) +{ + Frame *frame = Frame::create(); + if(clonedroot == NULL) + clonedroot = frame; + frame->object.copy(&this->object); + frame->matrix = this->matrix; + //memcpy(frame->matrix, this->matrix, sizeof(this->matrix)); + frame->root = clonedroot; + this->root = frame; // Remember cloned frame + for(Frame *child = this->child; child; child = child->next){ + Frame *clonedchild = child->cloneAndLink(clonedroot); + clonedchild->next = frame->child; + frame->child = clonedchild; + clonedchild->object.parent = frame; + } + frame->copyPlugins(this); + return frame; +} + +// Remove links to cloned frames from hierarchy. +void +Frame::purgeClone(void) +{ + Frame *parent = this->getParent(); + this->setHierarchyRoot(parent ? parent->root : this); +} + +Frame** +makeFrameList(Frame *frame, Frame **flist) +{ + *flist++ = frame; + if(frame->next) + flist = makeFrameList(frame->next, flist); + if(frame->child) + flist = makeFrameList(frame->child, flist); + return flist; +} + +} diff --git a/src/geometry.cpp b/src/geometry.cpp index cee18a0..e34237c 100644 --- a/src/geometry.cpp +++ b/src/geometry.cpp @@ -5,10 +5,13 @@ #include #include "rwbase.h" +#include "rwerror.h" #include "rwplg.h" #include "rwpipeline.h" #include "rwobjects.h" +#define PLUGIN_ID 2 + using namespace std; namespace rw { @@ -17,7 +20,10 @@ Geometry* Geometry::create(int32 numVerts, int32 numTris, uint32 flags) { Geometry *geo = (Geometry*)malloc(PluginBase::s_size); - assert(geo != NULL); + if(geo == nil){ + RWERROR((ERR_ALLOC, PluginBase::s_size)); + return nil; + } geo->object.init(Geometry::ID, 0); geo->geoflags = flags & 0xFF00FFFF; geo->numTexCoordSets = (flags & 0xFF0000) >> 16; @@ -28,10 +34,10 @@ Geometry::create(int32 numVerts, int32 numTris, uint32 flags) geo->numVertices = numVerts; geo->numMorphTargets = 1; - geo->colors = NULL; + geo->colors = nil; for(int32 i = 0; i < geo->numTexCoordSets; i++) - geo->texCoords[i] = NULL; - geo->triangles = NULL; + geo->texCoords[i] = nil; + geo->triangles = nil; if(!(geo->geoflags & NATIVE) && geo->numVertices){ if(geo->geoflags & PRELIT) geo->colors = new uint8[4*geo->numVertices]; @@ -45,24 +51,23 @@ Geometry::create(int32 numVerts, int32 numTris, uint32 flags) MorphTarget *m = geo->morphTargets; m->boundingSphere.center.set(0.0f, 0.0f, 0.0f); m->boundingSphere.radius = 0.0f; - m->vertices = NULL; - m->normals = NULL; + m->vertices = nil; + m->normals = nil; if(!(geo->geoflags & NATIVE) && geo->numVertices){ m->vertices = new float32[3*geo->numVertices]; if(geo->geoflags & NORMALS) m->normals = new float32[3*geo->numVertices]; } geo->numMaterials = 0; - geo->materialList = NULL; - geo->meshHeader = NULL; - geo->instData = NULL; + geo->materialList = nil; + geo->meshHeader = nil; + geo->instData = nil; geo->refCount = 1; geo->constructPlugins(); return geo; } - void Geometry::destroy(void) { @@ -101,10 +106,15 @@ Geometry::streamRead(Stream *stream) { uint32 version; GeoStreamData buf; - assert(findChunk(stream, ID_STRUCT, NULL, &version)); + if(!findChunk(stream, ID_STRUCT, nil, &version)){ + RWERROR((ERR_CHUNK, "STRUCT")); + return nil; + } stream->read(&buf, sizeof(buf)); Geometry *geo = Geometry::create(buf.numVertices, buf.numTriangles, buf.flags); + if(geo == nil) + return nil; geo->addMorphTargets(buf.numMorphTargets-1); // skip surface properties if(version < 0x34000) @@ -137,13 +147,25 @@ Geometry::streamRead(Stream *stream) stream->read(m->normals, 3*geo->numVertices*4); } - assert(findChunk(stream, ID_MATLIST, NULL, NULL)); - assert(findChunk(stream, ID_STRUCT, NULL, NULL)); + if(!findChunk(stream, ID_MATLIST, nil, nil)){ + RWERROR((ERR_CHUNK, "MATLIST")); + // TODO: free + return nil; + } + if(!findChunk(stream, ID_STRUCT, nil, nil)){ + RWERROR((ERR_CHUNK, "STRUCT")); + // TODO: free + return nil; + } geo->numMaterials = stream->readI32(); geo->materialList = new Material*[geo->numMaterials]; stream->seek(geo->numMaterials*4); // unused (-1) for(int32 i = 0; i < geo->numMaterials; i++){ - assert(findChunk(stream, ID_MATERIAL, NULL, NULL)); + if(!findChunk(stream, ID_MATERIAL, nil, nil)){ + RWERROR((ERR_CHUNK, "MATERIAL")); + // TODO: free + return nil; + } geo->materialList[i] = Material::streamRead(stream); } @@ -217,8 +239,8 @@ Geometry::streamWrite(Stream *stream) MorphTarget *m = &this->morphTargets[i]; stream->write(&m->boundingSphere, 4*4); if(!(this->geoflags & NATIVE)){ - stream->writeI32(m->vertices != NULL); - stream->writeI32(m->normals != NULL); + stream->writeI32(m->vertices != nil); + stream->writeI32(m->normals != nil); if(m->vertices) stream->write(m->vertices, 3*this->numVertices*4); @@ -270,8 +292,8 @@ Geometry::addMorphTargets(int32 n) this->morphTargets = morphTargets; for(int32 i = this->numMorphTargets; i < n; i++){ MorphTarget *m = &morphTargets[i]; - m->vertices = NULL; - m->normals = NULL; + m->vertices = nil; + m->normals = nil; if(!(this->geoflags & NATIVE)){ m->vertices = new float32[3*this->numVertices]; if(this->geoflags & NORMALS) @@ -344,7 +366,7 @@ void Geometry::generateTriangles(int8 *adc) { MeshHeader *header = this->meshHeader; - assert(header != NULL); + assert(header != nil); this->numTriangles = 0; Mesh *m = header->mesh; @@ -452,7 +474,7 @@ Geometry::buildMeshes(void) void Geometry::removeUnusedMaterials(void) { - if(this->meshHeader == NULL) + if(this->meshHeader == nil) return; MeshHeader *mh = this->meshHeader; int32 *map = new int32[this->numMaterials]; @@ -515,13 +537,16 @@ Material* Material::create(void) { Material *mat = (Material*)malloc(PluginBase::s_size); - assert(mat != NULL); - mat->texture = NULL; + if(mat == nil){ + RWERROR((ERR_ALLOC, PluginBase::s_size)); + return nil; + } + mat->texture = nil; memset(&mat->color, 0xFF, 4); mat->surfaceProps.ambient = 1.0f; mat->surfaceProps.specular = 1.0f; mat->surfaceProps.diffuse = 1.0f; - mat->pipeline = NULL; + mat->pipeline = nil; mat->refCount = 1; mat->constructPlugins(); return mat; @@ -531,6 +556,10 @@ Material* Material::clone(void) { Material *mat = Material::create(); + if(mat == nil){ + RWERROR((ERR_ALLOC, PluginBase::s_size)); + return nil; + } mat->color = this->color; mat->surfaceProps = this->surfaceProps; if(this->texture){ @@ -570,9 +599,14 @@ Material::streamRead(Stream *stream) uint32 length, version; MatStreamData buf; - assert(findChunk(stream, ID_STRUCT, NULL, &version)); + if(!findChunk(stream, ID_STRUCT, nil, &version)){ + RWERROR((ERR_CHUNK, "STRUCT")); + return nil; + } stream->read(&buf, sizeof(buf)); Material *mat = Material::create(); + if(mat == nil) + return nil; mat->color = buf.color; if(version < 0x30400){ mat->surfaceProps.ambient = 1.0f; @@ -586,8 +620,16 @@ Material::streamRead(Stream *stream) mat->surfaceProps.diffuse = surfaceProps[2]; } if(buf.textured){ - assert(findChunk(stream, ID_TEXTURE, &length, NULL)); + if(!findChunk(stream, ID_TEXTURE, &length, nil)){ + RWERROR((ERR_CHUNK, "TEXTURE")); + // TODO: free + return nil; + } mat->texture = Texture::streamRead(stream); + if(mat->texture == nil){ + // TODO: fre + return nil; + } } materialRights[0] = 0; @@ -609,7 +651,7 @@ Material::streamWrite(Stream *stream) buf.color = this->color; buf.flags = 0; buf.unused = 0; - buf.textured = this->texture != NULL; + buf.textured = this->texture != nil; stream->write(&buf, sizeof(buf)); if(rw::version >= 0x30400){ @@ -663,7 +705,7 @@ static int32 getSizeMaterialRights(void *object, int32, int32) { Material *material = (Material*)object; - if(material->pipeline == NULL || material->pipeline->pluginID == 0) + if(material->pipeline == nil || material->pipeline->pluginID == 0) return -1; return 8; } @@ -671,7 +713,7 @@ getSizeMaterialRights(void *object, int32, int32) void registerMaterialRightsPlugin(void) { - Material::registerPlugin(0, ID_RIGHTTORENDER, NULL, NULL, NULL); + Material::registerPlugin(0, ID_RIGHTTORENDER, nil, nil, nil); Material::registerPluginStream(ID_RIGHTTORENDER, readMaterialRights, writeMaterialRights, diff --git a/src/light.cpp b/src/light.cpp new file mode 100644 index 0000000..10967bb --- /dev/null +++ b/src/light.cpp @@ -0,0 +1,131 @@ +#include +#include + +#include "rwbase.h" +#include "rwerror.h" +#include "rwplg.h" +#include "rwpipeline.h" +#include "rwobjects.h" + +#define PLUGIN_ID 2 + +namespace rw { + +Light* +Light::create(int32 type) +{ + Light *light = (Light*)malloc(PluginBase::s_size); + if(light == NULL){ + RWERROR((ERR_ALLOC, PluginBase::s_size)); + return NULL; + } + light->object.object.init(Light::ID, type); + light->radius = 0.0f; + light->color.red = 1.0f; + light->color.green = 1.0f; + light->color.blue = 1.0f; + light->color.alpha = 1.0f; + light->minusCosAngle = 1.0f; + light->object.object.privateFlags = 1; + light->object.object.flags = LIGHTATOMICS | LIGHTWORLD; + light->clump = NULL; + light->inClump.init(); + light->constructPlugins(); + return light; +} + +void +Light::destroy(void) +{ + this->destructPlugins(); + if(this->clump) + this->inClump.remove(); + free(this); +} + +void +Light::setAngle(float32 angle) +{ + this->minusCosAngle = -cos(angle); +} + +float32 +Light::getAngle(void) +{ + return acos(-this->minusCosAngle); +} + +void +Light::setColor(float32 r, float32 g, float32 b) +{ + this->color.red = r; + this->color.green = g; + this->color.blue = b; + this->object.object.privateFlags = r == g && r == b; +} + +struct LightChunkData +{ + float32 radius; + float32 red, green, blue; + float32 minusCosAngle; + uint16 flags; + uint16 type; +}; + +Light* +Light::streamRead(Stream *stream) +{ + uint32 version; + LightChunkData buf; + + if(!findChunk(stream, ID_STRUCT, NULL, &version)){ + RWERROR((ERR_CHUNK, "STRUCT")); + return NULL; + } + stream->read(&buf, sizeof(LightChunkData)); + Light *light = Light::create(buf.type); + if(light == NULL) + return NULL; + light->radius = buf.radius; + light->setColor(buf.red, buf.green, buf.blue); + float32 a = buf.minusCosAngle; + if(version >= 0x30300) + light->minusCosAngle = a; + else + // tan -> -cos + light->minusCosAngle = -1.0f/sqrt(a*a+1.0f); + light->object.object.flags = (uint8)buf.flags; + light->streamReadPlugins(stream); + return light; +} + +bool +Light::streamWrite(Stream *stream) +{ + LightChunkData buf; + writeChunkHeader(stream, ID_LIGHT, this->streamGetSize()); + writeChunkHeader(stream, ID_STRUCT, sizeof(LightChunkData)); + buf.radius = this->radius; + buf.red = this->color.red; + buf.green = this->color.green; + buf.blue = this->color.blue; + if(version >= 0x30300) + buf.minusCosAngle = this->minusCosAngle; + else + buf.minusCosAngle = tan(acos(-this->minusCosAngle)); + buf.flags = this->object.object.flags; + buf.type = this->object.object.subType; + stream->write(&buf, sizeof(LightChunkData)); + + this->streamWritePlugins(stream); + return true; +} + +uint32 +Light::streamGetSize(void) +{ + return 12 + sizeof(LightChunkData) + 12 + this->streamGetPluginSize(); +} + +} diff --git a/src/rwbase.cpp b/src/rwbase.cpp index 5581741..3a936f2 100644 --- a/src/rwbase.cpp +++ b/src/rwbase.cpp @@ -6,6 +6,7 @@ #include #include "rwbase.h" +#include "rwerror.h" #include "rwplg.h" #include "rwpipeline.h" #include "rwobjects.h" @@ -21,6 +22,8 @@ using namespace std; namespace rw { +#define PLUGIN_ID 0 + int32 version = 0x36003; int32 build = 0xFFFF; #ifdef RW_PS2 @@ -665,7 +668,11 @@ StreamFile* StreamFile::open(const char *path, const char *mode) { this->file = fopen(path, mode); - return this->file ? this : NULL; + if(this->file == NULL){ + RWERROR((ERR_FILE, path)); + return NULL; + } + return this; } void @@ -758,10 +765,8 @@ findPointer(void *p, void **list, int32 num) int i; for(i = 0; i < num; i++) if(list[i] == p) - goto found; + return i; return -1; -found: - return i; } uint8* diff --git a/src/rwbase.h b/src/rwbase.h index 1fd28e8..d8ea4d9 100644 --- a/src/rwbase.h +++ b/src/rwbase.h @@ -33,6 +33,8 @@ typedef int32 bool32; typedef uint8 byte; typedef uint32 uint; +#define nil NULL + #define nelem(A) (sizeof(A) / sizeof A[0]) struct RGBA @@ -284,6 +286,16 @@ enum PluginID ID_VERTEXFMT = 0x511, }; +#define ECODE(c, s) c, + +enum Errors +{ + ERR_NONE = 0x80000000, +#include "base.err" +}; + +#undef ECODE + extern int version; extern int build; extern int platform; diff --git a/src/rwerror.h b/src/rwerror.h new file mode 100644 index 0000000..e382e89 --- /dev/null +++ b/src/rwerror.h @@ -0,0 +1,25 @@ +namespace rw { + +struct Error +{ + uint32 plugin; + uint32 code; +}; + +void setError(Error *e); +Error *getError(Error *e); + +#define _ERRORCODE(code, ...) code +char *dbgsprint(int32 code, ...); + +/* ecode is supposed to be in format "(errorcode, printf-arguments..)" */ +#define RWERROR(ecode) do{ \ + rw::Error _e; \ + _e.plugin = PLUGIN_ID; \ + _e.code = _ERRORCODE ecode; \ + fprintf(stderr, "%s:%d: ", __FILE__, __LINE__); \ + fprintf(stderr, "%s\n", rw::dbgsprint ecode); \ + rw::setError(&_e); \ +}while(0); + +} diff --git a/src/rwobjects.h b/src/rwobjects.h index 4be9040..78b8231 100644 --- a/src/rwobjects.h +++ b/src/rwobjects.h @@ -544,7 +544,7 @@ struct Clump : PluginBase uint32 streamGetSize(void); void render(void); - void frameListStreamRead(Stream *stream, Frame ***flp, int32 *nf); + bool frameListStreamRead(Stream *stream, Frame ***flp, int32 *nf); void frameListStreamWrite(Stream *stream, Frame **flp, int32 nf); }; diff --git a/src/rwplg.h b/src/rwplg.h index c9bf186..fd7893e 100644 --- a/src/rwplg.h +++ b/src/rwplg.h @@ -205,13 +205,13 @@ PluginBase::getPluginOffset(uint32 id) template void* PluginBase::operator new(size_t) { - assert(0); + abort(); return NULL; } template void PluginBase::operator delete(void *p) { - assert(0); + abort(); } }