Working savegame support.

Implemented also the movement of Manny's head when looking at usable items.
This commit also introduces a new Object class with a ObjectPtr used for
caching the resources loaded by ResourceLoader. This fixes also the lipsync
regression.
This commit is contained in:
Giulio Camuffo 2011-03-21 05:16:27 +08:00 committed by Paweł Kołodziejski
parent 24f02a74d7
commit 59dcece9ae
49 changed files with 2603 additions and 431 deletions

View file

@ -30,13 +30,16 @@
#include "engines/grim/lipsync.h" #include "engines/grim/lipsync.h"
#include "engines/grim/smush/smush.h" #include "engines/grim/smush/smush.h"
#include "engines/grim/imuse/imuse.h" #include "engines/grim/imuse/imuse.h"
#include "engines/grim/lua.h"
namespace Grim { namespace Grim {
int Actor::s_id = 0;
int g_winX1, g_winY1, g_winX2, g_winY2; int g_winX1, g_winY1, g_winX2, g_winY2;
Actor::Actor(const char *actorName) : Actor::Actor(const char *actorName) :
_name(actorName), _setName(""), _talkColor(255, 255, 255), _pos(0, 0, 0), Object(), _name(actorName), _setName(""), _talkColor(255, 255, 255), _pos(0, 0, 0),
// Some actors don't set walk and turn rates, so we default the // Some actors don't set walk and turn rates, so we default the
// _turnRate so Doug at the cat races can turn and we set the // _turnRate so Doug at the cat races can turn and we set the
// _walkRate so Glottis at the demon beaver entrance can walk // _walkRate so Glottis at the demon beaver entrance can walk
@ -48,7 +51,6 @@ Actor::Actor(const char *actorName) :
_turnCostume(NULL), _leftTurnChore(-1), _rightTurnChore(-1), _turnCostume(NULL), _leftTurnChore(-1), _rightTurnChore(-1),
_lastTurnDir(0), _currTurnDir(0), _lastTurnDir(0), _currTurnDir(0),
_mumbleCostume(NULL), _mumbleChore(-1), _sayLineText(NULL) { _mumbleCostume(NULL), _mumbleChore(-1), _sayLineText(NULL) {
g_grim->registerActor(this);
_lookingMode = false; _lookingMode = false;
_constrain = false; _constrain = false;
_talkSoundName = ""; _talkSoundName = "";
@ -61,27 +63,338 @@ Actor::Actor(const char *actorName) :
_shadowArray[i].active = false; _shadowArray[i].active = false;
_shadowArray[i].dontNegate = false; _shadowArray[i].dontNegate = false;
_shadowArray[i].shadowMask = NULL; _shadowArray[i].shadowMask = NULL;
_shadowArray[i].shadowMaskSize = 0;
} }
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
_talkCostume[i] = NULL; _talkCostume[i] = NULL;
_talkChore[i] = -1; _talkChore[i] = -1;
} }
++s_id;
_id = s_id;
g_grim->registerActor(this);
} }
Actor::Actor() :
Object() {
_shadowArray = new Shadow[5];
_winX1 = _winY1 = 1000;
_winX2 = _winY2 = -1000;
for (int i = 0; i < 5; i++) {
_shadowArray[i].active = false;
_shadowArray[i].dontNegate = false;
_shadowArray[i].shadowMask = NULL;
_shadowArray[i].shadowMaskSize = 0;
}
}
Actor::~Actor() { Actor::~Actor() {
clearShadowPlanes(); if (_shadowArray) {
delete[] _shadowArray; clearShadowPlanes();
delete[] _shadowArray;
}
} }
void Actor::saveState(SaveGame *savedState) { void Actor::saveState(SaveGame *savedState) const {
int32 size;
// store actor name // store actor name
size = strlen(name()); savedState->writeString(_name);
savedState->writeLESint32(size); savedState->writeString(_setName);
savedState->write(name(), size);
savedState->writeColor(_talkColor);
savedState->writeVector3d(_pos);
savedState->writeFloat(_pitch);
savedState->writeFloat(_yaw);
savedState->writeFloat(_roll);
savedState->writeFloat(_walkRate);
savedState->writeFloat(_turnRate);
savedState->writeLESint32(_constrain);
savedState->writeFloat(_reflectionAngle);
savedState->writeLESint32(_visible);
savedState->writeLESint32(_lookingMode),
savedState->writeString(_talkSoundName);
if (_lipSync) {
savedState->writeLEUint32(1);
savedState->writeCharString(_lipSync->filename());
} else {
savedState->writeLEUint32(0);
}
savedState->writeLESint32(_costumeStack.size());
for (Common::List<CostumePtr>::const_iterator i = _costumeStack.begin(); i != _costumeStack.end(); ++i) {
const CostumePtr &c = *i;
savedState->writeCharString(c->filename());
Costume *pc = c->previousCostume();
int depth = 0;
while (pc) {
++depth;
pc = pc->previousCostume();
}
savedState->writeLEUint32(depth);
pc = c->previousCostume();
for (int j = 0; j < depth; ++j) { //save the previousCostume hierarchy
savedState->writeCharString(pc->filename());
pc = pc->previousCostume();
}
c->saveState(savedState);
}
savedState->writeLESint32(_turning);
savedState->writeFloat(_destYaw);
savedState->writeLESint32(_walking);
savedState->writeVector3d(_destPos);
if (_restCostume) {
savedState->writeLEUint32(1);
savedState->writeCharString(_restCostume->filename());
} else {
savedState->writeLEUint32(0);
}
savedState->writeLESint32(_restChore);
if (_walkCostume) {
savedState->writeLEUint32(1);
savedState->writeCharString(_walkCostume->filename());
} else {
savedState->writeLEUint32(0);
}
savedState->writeLESint32(_walkChore);
savedState->writeLESint32(_walkedLast);
savedState->writeLESint32(_walkedCur);
if (_turnCostume) {
savedState->writeLEUint32(1);
savedState->writeCharString(_turnCostume->filename());
} else {
savedState->writeLEUint32(0);
}
savedState->writeLESint32(_leftTurnChore);
savedState->writeLESint32(_rightTurnChore);
savedState->writeLESint32(_lastTurnDir);
savedState->writeLESint32(_currTurnDir);
for (int i = 0; i < 10; ++i) {
if (_talkCostume[i]) {
savedState->writeLEUint32(1);
savedState->writeCharString(_talkCostume[i]->filename());
} else {
savedState->writeLEUint32(0);
}
savedState->writeLESint32(_talkChore[i]);
}
savedState->writeLESint32(_talkAnim);
if (_mumbleCostume) {
savedState->writeLEUint32(1);
savedState->writeCharString(_mumbleCostume->filename());
} else {
savedState->writeLEUint32(0);
}
savedState->writeLESint32(_mumbleChore);
for (int i = 0; i < 5; ++i) {
Shadow &shadow = _shadowArray[i];
savedState->writeString(shadow.name);
savedState->writeVector3d(shadow.pos);
savedState->writeLESint32(shadow.planeList.size());
for (SectorListType::iterator j = shadow.planeList.begin(); j != shadow.planeList.end(); ++j) {
Sector *sec = *j;
Scene *s = g_grim->currScene();
for (int k = 0; k < s->getSectorCount(); ++k) {
if (s->getSectorBase(k) == sec) {
savedState->writeLEUint32(k);
break;
}
}
}
savedState->writeLESint32(shadow.shadowMaskSize);
for (int j = 0; j < shadow.shadowMaskSize; ++j) {
savedState->writeByte(shadow.shadowMask[j]);
}
savedState->writeLESint32(shadow.active);
savedState->writeLESint32(shadow.dontNegate);
}
savedState->writeLESint32(_activeShadowSlot);
if (_sayLineText) {
savedState->writeLEUint32(g_grim->textObjectId(_sayLineText));
} else {
savedState->writeLEUint32(0);
}
savedState->writeVector3d(_lookAtVector);
savedState->writeFloat(_lookAtRate);
savedState->writeLESint32(_winX1);
savedState->writeLESint32(_winY1);
savedState->writeLESint32(_winX2);
savedState->writeLESint32(_winY2);
}
bool Actor::restoreState(SaveGame *savedState) {
// load actor name
_name = savedState->readString();
_setName = savedState->readString();
_talkColor = savedState->readColor();
_pos = savedState->readVector3d();
_pitch = savedState->readFloat();
_yaw = savedState->readFloat();
_roll = savedState->readFloat();
_walkRate = savedState->readFloat();
_turnRate = savedState->readFloat();
_constrain = savedState->readLESint32();
_reflectionAngle = savedState->readFloat();
_visible = savedState->readLESint32();
_lookingMode = savedState->readLESint32();
_talkSoundName = savedState->readString();
if (savedState->readLEUint32()) {
const char *fn = savedState->readCharString();
_lipSync = g_resourceloader->getLipSync(fn);
delete[] fn;
} else {
_lipSync = NULL;
}
int32 size = savedState->readLESint32();
_costumeStack.clear();
for (int32 i = 0; i < size; ++i) {
const char *fname = savedState->readCharString();
const int depth = savedState->readLEUint32();
CostumePtr pc = NULL;
if (depth > 0) { //build all the previousCostume hierarchy
const char **names = new const char*[depth];
for (int j = 0; j < depth; ++j) {
names[j] = savedState->readCharString();
}
for (int j = depth - 1; j >= 0; --j) {
pc = g_resourceloader->getCostume(names[j], pc);
}
for (int j = 0; j < depth; ++j) {
delete[] names[j];
}
delete[] names;
}
CostumePtr c = g_resourceloader->getCostume(fname, pc);
c->restoreState(savedState);
_costumeStack.push_back(c);
}
_turning = savedState->readLESint32();
_destYaw = savedState->readFloat();
_walking = savedState->readLESint32();
_destPos = savedState->readVector3d();
if (savedState->readLEUint32()) {
const char *fname = savedState->readCharString();
_restCostume = g_resourceloader->getCostume(fname, 0);
delete[] fname;
} else {
_restCostume = NULL;
}
_restChore = savedState->readLESint32();
if (savedState->readLEUint32()) {
const char *fname = savedState->readCharString();
_walkCostume = g_resourceloader->getCostume(fname, 0);
delete[] fname;
} else {
_walkCostume = NULL;
}
_walkChore = savedState->readLESint32();
_walkedLast = savedState->readLESint32();
_walkedCur = savedState->readLESint32();
if (savedState->readLEUint32()) {
const char *fname = savedState->readCharString();
_turnCostume = g_resourceloader->getCostume(fname, 0);
delete[] fname;
} else {
_turnCostume = NULL;
}
_leftTurnChore = savedState->readLESint32();
_rightTurnChore = savedState->readLESint32();
_lastTurnDir = savedState->readLESint32();
_currTurnDir = savedState->readLESint32();
for (int i = 0; i < 10; ++i) {
if (savedState->readLEUint32()) {
const char *fname = savedState->readCharString();
_talkCostume[i] = g_resourceloader->getCostume(fname, 0);
delete[] fname;
} else {
_talkCostume[i] = NULL;
}
_talkChore[i] = savedState->readLESint32();
}
_talkAnim = savedState->readLESint32();
if (savedState->readLEUint32()) {
const char *fname = savedState->readCharString();
_mumbleCostume = g_resourceloader->getCostume(fname, 0);
delete[] fname;
} else {
_mumbleCostume = NULL;
}
_mumbleChore = savedState->readLESint32();
for (int i = 0; i < 5; ++i) {
Shadow &shadow = _shadowArray[i];
shadow.name = savedState->readString();
shadow.pos = savedState->readVector3d();
size = savedState->readLESint32();
shadow.planeList.clear();
for (int j = 0; j < size; ++j) {
int32 id = savedState->readLEUint32();
Sector *s = g_grim->currScene()->getSectorBase(id);
shadow.planeList.push_back(s);
}
shadow.shadowMaskSize = savedState->readLESint32();
delete[] shadow.shadowMask;
if (shadow.shadowMaskSize > 0) {
shadow.shadowMask = new byte[shadow.shadowMaskSize];
for (int j = 0; j < shadow.shadowMaskSize; ++j) {
shadow.shadowMask[j] = savedState->readByte();
}
} else {
shadow.shadowMask = NULL;
}
shadow.active = savedState->readLESint32();
shadow.dontNegate = savedState->readLESint32();
}
_activeShadowSlot = savedState->readLESint32();
_sayLineText = g_grim->textObject(savedState->readLEUint32());
_lookAtVector = savedState->readVector3d();
_lookAtRate = savedState->readFloat();
_winX1 = savedState->readLESint32();
_winY1 = savedState->readLESint32();
_winX2 = savedState->readLESint32();
_winY2 = savedState->readLESint32();
return true;
} }
void Actor::setYaw(float yawParam) { void Actor::setYaw(float yawParam) {
@ -222,7 +535,7 @@ Graphics::Vector3d Actor::puckVector() const {
} }
void Actor::setRestChore(int chore, Costume *cost) { void Actor::setRestChore(int chore, Costume *cost) {
if (_restCostume == cost && _restChore == chore) if (_restCostume.object() == cost && _restChore == chore)
return; return;
if (_restChore >= 0) if (_restChore >= 0)
@ -236,7 +549,7 @@ void Actor::setRestChore(int chore, Costume *cost) {
} }
void Actor::setWalkChore(int chore, Costume *cost) { void Actor::setWalkChore(int chore, Costume *cost) {
if (_walkCostume == cost && _walkChore == chore) if (_walkCostume.object() == cost && _walkChore == chore)
return; return;
if (_walkChore >= 0) if (_walkChore >= 0)
@ -247,7 +560,7 @@ void Actor::setWalkChore(int chore, Costume *cost) {
} }
void Actor::setTurnChores(int left_chore, int right_chore, Costume *cost) { void Actor::setTurnChores(int left_chore, int right_chore, Costume *cost) {
if (_turnCostume == cost && _leftTurnChore == left_chore && if (_turnCostume.object() == cost && _leftTurnChore == left_chore &&
_rightTurnChore == right_chore) _rightTurnChore == right_chore)
return; return;
@ -270,7 +583,7 @@ void Actor::setTalkChore(int index, int chore, Costume *cost) {
index--; index--;
if (_talkCostume[index] == cost && _talkChore[index] == chore) if (_talkCostume[index].object() == cost && _talkChore[index] == chore)
return; return;
if (_talkChore[index] >= 0) if (_talkChore[index] >= 0)
@ -353,7 +666,7 @@ void Actor::sayLine(const char *msg, const char *msgId) {
// For example, when reading the work order (a LIP file exists for no reason). // For example, when reading the work order (a LIP file exists for no reason).
// Also, some lip sync files have no entries // Also, some lip sync files have no entries
// In these cases, revert to using the mumble chore. // In these cases, revert to using the mumble chore.
_lipSync = g_resourceloader->loadLipSync(soundLip.c_str()); _lipSync = g_resourceloader->getLipSync(soundLip.c_str());
// If there's no lip sync file then load the mumble chore if it exists // If there's no lip sync file then load the mumble chore if it exists
// (the mumble chore doesn't exist with the cat races announcer) // (the mumble chore doesn't exist with the cat races announcer)
if (!_lipSync && _mumbleChore != -1) if (!_lipSync && _mumbleChore != -1)
@ -393,7 +706,7 @@ void Actor::sayLine(const char *msg, const char *msgId) {
bool Actor::talking() { bool Actor::talking() {
// If there's no sound file then we're obviously not talking // If there's no sound file then we're obviously not talking
if (strlen(_talkSoundName.c_str()) == 0) if (strlen(_talkSoundName.c_str()) == 0)
return false; return false;
return g_imuse->getSoundStatus(_talkSoundName.c_str()); return g_imuse->getSoundStatus(_talkSoundName.c_str());
@ -423,7 +736,7 @@ void Actor::shutUp() {
} }
void Actor::pushCostume(const char *n) { void Actor::pushCostume(const char *n) {
Costume *newCost = g_resourceloader->loadCostume(n, currentCostume()); CostumePtr newCost = g_resourceloader->getCostume(n, currentCostume());
newCost->setColormap(NULL); newCost->setColormap(NULL);
_costumeStack.push_back(newCost); _costumeStack.push_back(newCost);
@ -447,8 +760,8 @@ void Actor::setCostume(const char *n) {
void Actor::popCostume() { void Actor::popCostume() {
if (!_costumeStack.empty()) { if (!_costumeStack.empty()) {
freeCostumeChore(_costumeStack.back(), _restCostume, _restChore); freeCostumeChore(_costumeStack.back().object(), _restCostume, _restChore);
freeCostumeChore(_costumeStack.back(), _walkCostume, _walkChore); freeCostumeChore(_costumeStack.back().object(), _walkCostume, _walkChore);
if (_turnCostume == _costumeStack.back()) { if (_turnCostume == _costumeStack.back()) {
_turnCostume = NULL; _turnCostume = NULL;
@ -489,9 +802,10 @@ void Actor::setHead(int joint1, int joint2, int joint3, float maxRoll, float max
} }
Costume *Actor::findCostume(const char *n) { Costume *Actor::findCostume(const char *n) {
for (Common::List<Costume *>::iterator i = _costumeStack.begin(); i != _costumeStack.end(); ++i) for (Common::List<CostumePtr>::iterator i = _costumeStack.begin(); i != _costumeStack.end(); ++i) {
if (strcasecmp((*i)->filename(), n) == 0) if (strcasecmp((*i)->filename(), n) == 0)
return *i; return *i;
}
return NULL; return NULL;
} }
@ -541,8 +855,9 @@ void Actor::update() {
// It seems that we need to allow an already active turning motion to // It seems that we need to allow an already active turning motion to
// continue or else turning actors away from barriers won't work right // continue or else turning actors away from barriers won't work right
// _turning = false; // _turning = false;
} else } else {
_pos += dir * walkAmt; _pos += dir * walkAmt;
}
_walkedCur = true; _walkedCur = true;
} }
@ -602,8 +917,9 @@ void Actor::update() {
} }
} }
for (Common::List<Costume *>::iterator i = _costumeStack.begin(); i != _costumeStack.end(); ++i) { for (Common::List<CostumePtr>::iterator i = _costumeStack.begin(); i != _costumeStack.end(); ++i) {
(*i)->setPosRotate(_pos, _pitch, _yaw, _roll); (*i)->setPosRotate(_pos, _pitch, _yaw, _roll);
(*i)->setLookAt(_lookAtVector);
(*i)->update(); (*i)->update();
} }
@ -616,7 +932,7 @@ void Actor::draw() {
g_winX1 = g_winY1 = 1000; g_winX1 = g_winY1 = 1000;
g_winX2 = g_winY2 = -1000; g_winX2 = g_winY2 = -1000;
for (Common::List<Costume *>::iterator i = _costumeStack.begin(); i != _costumeStack.end(); ++i) for (Common::List<CostumePtr>::iterator i = _costumeStack.begin(); i != _costumeStack.end(); ++i)
(*i)->setupTextures(); (*i)->setupTextures();
if (!g_driver->isHardwareAccelerated() && g_grim->getFlagRefreshShadowMask()) { if (!g_driver->isHardwareAccelerated() && g_grim->getFlagRefreshShadowMask()) {
@ -735,10 +1051,22 @@ void Actor::clearShadowPlanes() {
shadow->planeList.pop_back(); shadow->planeList.pop_back();
} }
delete[] shadow->shadowMask; delete[] shadow->shadowMask;
shadow->shadowMaskSize = 0;
shadow->shadowMask = NULL; shadow->shadowMask = NULL;
shadow->active = false; shadow->active = false;
shadow->dontNegate = false; shadow->dontNegate = false;
} }
} }
bool Actor::inSet(const char *setName) const {
return _setName == setName;
}
void Actor::freeCostumeChore(Costume *toFree, CostumePtr &cost, int &chore) {
if (cost.object() == toFree) {
cost = NULL;
chore = -1;
}
}
} // end of namespace Grim } // end of namespace Grim

View file

@ -26,6 +26,7 @@
#ifndef GRIM_ACTOR_H #ifndef GRIM_ACTOR_H
#define GRIM_ACTOR_H #define GRIM_ACTOR_H
#include "engines/grim/object.h"
#include "engines/grim/color.h" #include "engines/grim/color.h"
#include "engines/grim/resource.h" #include "engines/grim/resource.h"
#include "engines/grim/savegame.h" #include "engines/grim/savegame.h"
@ -45,16 +46,20 @@ struct Shadow {
Graphics::Vector3d pos; Graphics::Vector3d pos;
SectorListType planeList; SectorListType planeList;
byte *shadowMask; byte *shadowMask;
int shadowMaskSize;
bool active; bool active;
bool dontNegate; bool dontNegate;
}; };
class Actor { class Actor : public Object {
GRIM_OBJECT(Actor)
public: public:
Actor(const char *name); Actor(const char *name);
Actor();
~Actor(); ~Actor();
void saveState(SaveGame *savedState); void saveState(SaveGame *savedState) const;
bool restoreState(SaveGame *savedState);
const char *name() const { return _name.c_str(); } const char *name() const { return _name.c_str(); }
@ -93,9 +98,7 @@ public:
float angleTo(const Actor &a) const; float angleTo(const Actor &a) const;
float yawTo(Graphics::Vector3d p) const; float yawTo(Graphics::Vector3d p) const;
bool inSet(const char *setName) const { bool inSet(const char *setName) const;
return _setName == setName;
}
void walkForward(); void walkForward();
void setReflection(float angle) { _reflectionAngle = angle; } void setReflection(float angle) { _reflectionAngle = angle; }
Graphics::Vector3d puckVector() const; Graphics::Vector3d puckVector() const;
@ -168,6 +171,7 @@ public:
private: private:
Common::String _name; Common::String _name;
Common::String _setName; // The actual current set Common::String _setName; // The actual current set
Color _talkColor; Color _talkColor;
Graphics::Vector3d _pos; Graphics::Vector3d _pos;
float _pitch, _yaw, _roll; float _pitch, _yaw, _roll;
@ -178,8 +182,8 @@ private:
bool _visible; bool _visible;
bool _lookingMode; bool _lookingMode;
Common::String _talkSoundName; Common::String _talkSoundName;
LipSync *_lipSync; LipSyncPtr _lipSync;
Common::List<Costume *> _costumeStack; Common::List<CostumePtr> _costumeStack;
// Variables for gradual turning // Variables for gradual turning
bool _turning; bool _turning;
@ -190,28 +194,28 @@ private:
Graphics::Vector3d _destPos; Graphics::Vector3d _destPos;
// chores // chores
Costume *_restCostume; CostumePtr _restCostume;
int _restChore; int _restChore;
Costume *_walkCostume; CostumePtr _walkCostume;
int _walkChore; int _walkChore;
bool _walkedLast, _walkedCur; bool _walkedLast, _walkedCur;
Costume *_turnCostume; CostumePtr _turnCostume;
int _leftTurnChore, _rightTurnChore; int _leftTurnChore, _rightTurnChore;
int _lastTurnDir, _currTurnDir; int _lastTurnDir, _currTurnDir;
Costume *_talkCostume[10]; CostumePtr _talkCostume[10];
int _talkChore[10]; int _talkChore[10];
int _talkAnim; int _talkAnim;
Costume *_mumbleCostume; CostumePtr _mumbleCostume;
int _mumbleChore; int _mumbleChore;
Shadow *_shadowArray; Shadow *_shadowArray;
int _activeShadowSlot; int _activeShadowSlot;
static Font *_sayLineFont; static FontPtr _sayLineFont;
TextObject *_sayLineText; TextObject *_sayLineText;
// Validate a yaw angle then set it appropriately // Validate a yaw angle then set it appropriately
@ -221,12 +225,7 @@ private:
return (dir > 0 ? _rightTurnChore : _leftTurnChore); return (dir > 0 ? _rightTurnChore : _leftTurnChore);
} }
void freeCostumeChore(Costume *toFree, Costume *&cost, int &chore) { void freeCostumeChore(Costume *toFree, CostumePtr &cost, int &chore);
if (cost == toFree) {
cost = NULL;
chore = -1;
}
}
// lookAt // lookAt
Graphics::Vector3d _lookAtVector; Graphics::Vector3d _lookAtVector;
@ -234,6 +233,9 @@ private:
int _winX1, _winY1, _winX2, _winY2; int _winX1, _winY1, _winX2, _winY2;
int _id;
static int s_id;
friend class GrimEngine; friend class GrimEngine;
}; };

View file

@ -28,12 +28,14 @@
#include "engines/grim/grim.h" #include "engines/grim/grim.h"
#include "engines/grim/bitmap.h" #include "engines/grim/bitmap.h"
#include "engines/grim/gfx_base.h" #include "engines/grim/gfx_base.h"
#include "engines/grim/savegame.h"
namespace Grim { namespace Grim {
static void decompress_codec3(const char *compressed, char *result); static void decompress_codec3(const char *compressed, char *result);
Bitmap::Bitmap(const char *fname, const char *data, int len) { Bitmap::Bitmap(const char *fname, const char *data, int len) :
Object() {
_fname = fname; _fname = fname;
if (len < 8 || memcmp(data, "BM F\0\0\0", 8) != 0) { if (len < 8 || memcmp(data, "BM F\0\0\0", 8) != 0) {
@ -44,19 +46,19 @@ Bitmap::Bitmap(const char *fname, const char *data, int len) {
strcpy(_filename, fname); strcpy(_filename, fname);
int codec = READ_LE_UINT32(data + 8); int codec = READ_LE_UINT32(data + 8);
// _paletteIncluded = READ_LE_UINT32(data + 12); // _paletteIncluded = READ_LE_UINT32(data + 12);
_numImages = READ_LE_UINT32(data + 16); _numImages = READ_LE_UINT32(data + 16);
_x = READ_LE_UINT32(data + 20); _x = READ_LE_UINT32(data + 20);
_y = READ_LE_UINT32(data + 24); _y = READ_LE_UINT32(data + 24);
// _transparentColor = READ_LE_UINT32(data + 28); // _transparentColor = READ_LE_UINT32(data + 28);
_format = READ_LE_UINT32(data + 32); _format = READ_LE_UINT32(data + 32);
// _numBits = READ_LE_UINT32(data + 36); // _numBits = READ_LE_UINT32(data + 36);
// _blueBits = READ_LE_UINT32(data + 40); // _blueBits = READ_LE_UINT32(data + 40);
// _greenBits = READ_LE_UINT32(data + 44); // _greenBits = READ_LE_UINT32(data + 44);
// _redBits = READ_LE_UINT32(data + 48); // _redBits = READ_LE_UINT32(data + 48);
// _blueShift = READ_LE_UINT32(data + 52); // _blueShift = READ_LE_UINT32(data + 52);
// _greenShift = READ_LE_UINT32(data + 56); // _greenShift = READ_LE_UINT32(data + 56);
// _redShift = READ_LE_UINT32(data + 60); // _redShift = READ_LE_UINT32(data + 60);
_width = READ_LE_UINT32(data + 128); _width = READ_LE_UINT32(data + 128);
_height = READ_LE_UINT32(data + 132); _height = READ_LE_UINT32(data + 132);
_currImage = 1; _currImage = 1;
@ -85,7 +87,7 @@ Bitmap::Bitmap(const char *fname, const char *data, int len) {
g_driver->createBitmap(this); g_driver->createBitmap(this);
} }
Bitmap::Bitmap(const char *data, int w, int h, const char *fname) { Bitmap::Bitmap(const char *data, int w, int h, const char *fname) : Object() {
_fname = fname; _fname = fname;
if (gDebugLevel == DEBUG_BITMAPS || gDebugLevel == DEBUG_NORMAL || gDebugLevel == DEBUG_ALL) if (gDebugLevel == DEBUG_BITMAPS || gDebugLevel == DEBUG_NORMAL || gDebugLevel == DEBUG_ALL)
printf("New bitmap loaded: %s\n", fname); printf("New bitmap loaded: %s\n", fname);
@ -121,8 +123,11 @@ Bitmap::~Bitmap() {
delete[] _data; delete[] _data;
_data = NULL; _data = NULL;
g_driver->destroyBitmap(this);
} }
g_driver->destroyBitmap(this); if (g_resourceloader)
g_resourceloader->uncacheBitmap(this);
} }
#define GET_BIT do { bit = bitstr_value & 1; \ #define GET_BIT do { bit = bitstr_value & 1; \

View file

@ -27,14 +27,17 @@
#define GRIM_BITMAP_H #define GRIM_BITMAP_H
#include "engines/grim/resource.h" #include "engines/grim/resource.h"
#include "engines/grim/object.h"
namespace Grim { namespace Grim {
class Bitmap { class Bitmap : public Object {
GRIM_OBJECT(Bitmap)
public: public:
// Construct a bitmap from the given data. // Construct a bitmap from the given data.
Bitmap(const char *filename, const char *data, int len); Bitmap(const char *filename, const char *data, int len);
Bitmap(const char *data, int width, int height, const char *filename); Bitmap(const char *data, int width, int height, const char *filename);
Bitmap() : Object() { _data = 0; }
const char *filename() const { return _fname.c_str(); } const char *filename() const { return _fname.c_str(); }
@ -57,7 +60,7 @@ public:
char *getFilename() { return _filename; } char *getFilename() { return _filename; }
~Bitmap(); virtual ~Bitmap();
//private: //private:
Common::String _fname; Common::String _fname;

View file

@ -27,10 +27,13 @@
#define GRIM_COLOR_H #define GRIM_COLOR_H
#include "common/sys.h" #include "common/sys.h"
#include "engines/grim/savegame.h"
#include "engines/grim/object.h"
namespace Grim { namespace Grim {
class Color { class Color : public Object {
GRIM_OBJECT(Color)
public: public:
byte _vals[3]; byte _vals[3];
@ -57,6 +60,20 @@ public:
_vals[0] = c->_vals[0]; _vals[1] = c->_vals[1]; _vals[2] = c->_vals[2]; _vals[0] = c->_vals[0]; _vals[1] = c->_vals[1]; _vals[2] = c->_vals[2];
return *this; return *this;
} }
void saveState(SaveGame *state) const {
state->writeByte(_vals[0]);
state->writeByte(_vals[1]);
state->writeByte(_vals[2]);
}
bool restoreState(SaveGame *state) {
_vals[0] = state->readByte();
_vals[1] = state->readByte();
_vals[2] = state->readByte();
return true;
}
}; };
} // end of namespace Grim } // end of namespace Grim

View file

@ -29,23 +29,39 @@
#include "common/endian.h" #include "common/endian.h"
#include "engines/grim/resource.h" #include "engines/grim/resource.h"
#include "engines/grim/object.h"
namespace Grim { namespace Grim {
class CMap { class CMap : public Object {
GRIM_OBJECT(ColorMap)
public: public:
// Load a colormap from the given data. // Load a colormap from the given data.
CMap(const char *fileName, const char *data, int len) { CMap(const char *fileName, const char *data, int len) :
Object() {
_fname = fileName; _fname = fileName;
if (len < 4 || READ_BE_UINT32(data) != MKID_BE('CMP ')) if (len < 4 || READ_BE_UINT32(data) != MKID_BE('CMP '))
error("Invalid magic loading colormap"); error("Invalid magic loading colormap");
memcpy(_colors, data + 64, sizeof(_colors)); memcpy(_colors, data + 64, sizeof(_colors));
} }
CMap() : Object() {}
~CMap() {
if (g_resourceloader)
g_resourceloader->uncacheColormap(this);
}
const char *filename() const { return _fname.c_str(); } const char *filename() const { return _fname.c_str(); }
// The color data, in RGB format // The color data, in RGB format
char _colors[256 * 3]; char _colors[256 * 3];
Common::String _fname; Common::String _fname;
bool operator==(const CMap &c) const {
if (_fname != c._fname) {
return false;
}
return true;
}
}; };
} // end of namespace Grim } // end of namespace Grim

View file

@ -124,11 +124,12 @@ public:
~ModelComponent(); ~ModelComponent();
Model::HierNode *hierarchy() { return _hier; } Model::HierNode *hierarchy() { return _hier; }
int numNodes() { return _obj->numNodes(); }
void draw(); void draw();
protected: protected:
Common::String _filename; Common::String _filename;
Model *_obj; ModelPtr _obj;
Model::HierNode *_hier; Model::HierNode *_hier;
Graphics::Matrix4 _matrix; Graphics::Matrix4 _matrix;
}; };
@ -241,10 +242,11 @@ void ModelComponent::init() {
if (gDebugLevel == DEBUG_MODEL || gDebugLevel == DEBUG_WARN || gDebugLevel == DEBUG_ALL) if (gDebugLevel == DEBUG_MODEL || gDebugLevel == DEBUG_WARN || gDebugLevel == DEBUG_ALL)
warning("No colormap specified for %s, using %s", _filename.c_str(), DEFAULT_COLORMAP); warning("No colormap specified for %s, using %s", _filename.c_str(), DEFAULT_COLORMAP);
cm = g_resourceloader->loadColormap(DEFAULT_COLORMAP); cm = g_resourceloader->getColormap(DEFAULT_COLORMAP);
} }
_obj = g_resourceloader->loadModel(_filename.c_str(), cm); _obj = g_resourceloader->getModel(_filename.c_str(), cm);
_hier = _obj->copyHierarchy(); _hier = _obj->copyHierarchy();
// Use parent availablity to decide whether to default the // Use parent availablity to decide whether to default the
// component to being visible // component to being visible
if (!_parent || !_parent->visible()) if (!_parent || !_parent->visible())
@ -297,8 +299,9 @@ void ModelComponent::resetColormap() {
} }
ModelComponent::~ModelComponent() { ModelComponent::~ModelComponent() {
if (_hier && _hier->_parent) if (_hier && _hier->_parent) {
_hier->_parent->removeChild(_hier); _hier->_parent->removeChild(_hier);
}
delete[] _hier; delete[] _hier;
} }
@ -316,13 +319,16 @@ void translateObject(Model::HierNode *node, bool reset) {
void ModelComponent::draw() { void ModelComponent::draw() {
// If the object was drawn by being a component // If the object was drawn by being a component
// of it's parent then don't draw it // of it's parent then don't draw it
if (_parent && _parent->visible()) if (_parent && _parent->visible())
return; return;
// Need to translate object to be in accordance // Need to translate object to be in accordance
// with the setup of the parent // with the setup of the parent
if (_hier->_parent) if (_hier->_parent)
translateObject(_hier->_parent, false); translateObject(_hier->_parent, false);
_hier->draw(); _hier->draw();
// Need to un-translate when done // Need to un-translate when done
if (_hier->_parent) if (_hier->_parent)
translateObject(_hier->_parent, true); translateObject(_hier->_parent, true);
@ -376,14 +382,14 @@ public:
~MaterialComponent() { } ~MaterialComponent() { }
private: private:
Material *_mat; MaterialPtr _mat;
Common::String _filename; Common::String _filename;
int _num; int _num;
}; };
ColormapComponent::ColormapComponent(Costume::Component *p, int parentID, const char *filename, tag32 t) : ColormapComponent::ColormapComponent(Costume::Component *p, int parentID, const char *filename, tag32 t) :
Costume::Component(p, parentID, t) { Costume::Component(p, parentID, t) {
_cmap = g_resourceloader->loadColormap(filename); _cmap = g_resourceloader->getColormap(filename);
if (p) if (p)
p->setColormap(_cmap); p->setColormap(_cmap);
@ -404,7 +410,7 @@ public:
~KeyframeComponent() {} ~KeyframeComponent() {}
private: private:
KeyframeAnim *_keyf; KeyframeAnimPtr _keyf;
int _priority1, _priority2; int _priority1, _priority2;
Model::HierNode *_hier; Model::HierNode *_hier;
bool _active; bool _active;
@ -419,10 +425,10 @@ KeyframeComponent::KeyframeComponent(Costume::Component *p, int parentID, const
const char *comma = strchr(filename, ','); const char *comma = strchr(filename, ',');
if (comma) { if (comma) {
Common::String realName(filename, comma); Common::String realName(filename, comma);
_keyf = g_resourceloader->loadKeyframe(realName.c_str()); _keyf = g_resourceloader->getKeyframe(realName.c_str());
sscanf(comma + 1, "%d,%d", &_priority1, &_priority2); sscanf(comma + 1, "%d,%d", &_priority1, &_priority2);
} else } else
_keyf = g_resourceloader->loadKeyframe(filename); _keyf = g_resourceloader->getKeyframe(filename);
} }
void KeyframeComponent::setKey(int val) { void KeyframeComponent::setKey(int val) {
@ -541,9 +547,9 @@ void MaterialComponent::init() {
if (gDebugLevel == DEBUG_MODEL || gDebugLevel == DEBUG_WARN || gDebugLevel == DEBUG_ALL) if (gDebugLevel == DEBUG_MODEL || gDebugLevel == DEBUG_WARN || gDebugLevel == DEBUG_ALL)
warning("MaterialComponent::init on %s", _filename.c_str()); warning("MaterialComponent::init on %s", _filename.c_str());
cm = g_resourceloader->loadColormap(DEFAULT_COLORMAP); cm = g_resourceloader->getColormap(DEFAULT_COLORMAP);
} }
_mat = g_resourceloader->loadMaterial(_filename.c_str(), cm); _mat = g_resourceloader->getMaterial(_filename.c_str(), cm);
} }
void MaterialComponent::setKey(int val) { void MaterialComponent::setKey(int val) {
@ -583,9 +589,9 @@ public:
void setKey(int val); void setKey(int val);
void reset(); void reset();
~SoundComponent() { ~SoundComponent() {
// Stop the sound if it's in progress // Stop the sound if it's in progress
reset(); reset();
} }
private: private:
Common::String _soundName; Common::String _soundName;
@ -626,12 +632,27 @@ void SoundComponent::setKey(int val) {
void SoundComponent::reset() { void SoundComponent::reset() {
// A lot of the sound components this gets called against aren't actually running // A lot of the sound components this gets called against aren't actually running
if (g_imuse->getSoundStatus(_soundName.c_str())) if (g_imuse && g_imuse->getSoundStatus(_soundName.c_str()))
g_imuse->stopSound(_soundName.c_str()); g_imuse->stopSound(_soundName.c_str());
} }
Costume::Costume(const char *fname, const char *data, int len, Costume *prevCost) : Costume::Costume(const char *fname, const char *data, int len, Costume *prevCost) :
_fname(fname), _cmap(NULL) { Object() {
load(fname, data, len, prevCost);
}
void Costume::load(const char *filename, const char *data, int len, Costume *prevCost) {
_fname = filename;
_headNode = NULL;
_neckNode = NULL;
_head.maxPitch = 0;
_headYaw = 0;
_headPitch = 0;
_lastTime = 0;
_headZ = 0;
_prevCostume = prevCost;
TextSplitter ts(data, len); TextSplitter ts(data, len);
ts.expectString("costume v0.1"); ts.expectString("costume v0.1");
@ -714,20 +735,55 @@ Costume::Costume(const char *fname, const char *data, int len, Costume *prevCost
ts.scanString("chore %d", 1, &which); ts.scanString("chore %d", 1, &which);
_chores[which].load(this, ts); _chores[which].load(this, ts);
} }
Model::HierNode *hier = 0;
int count = 0;
for (int i = 0; i < _numComponents; i++) {
if (!_components[i])
continue;
// Needs to handle Main Models (pigeons) and normal Models
// (when Manny climbs the rope)
if (FROM_BE_32(_components[i]->tag()) == MKID_BE('MMDL')) {
ModelComponent *c = static_cast<ModelComponent *>(_components[i]);
hier = c->hierarchy();
count = c->numNodes();
break;
}
}
for (int i = 0; i < count; i++) {
if (strcmp(hier[i]._name, "m_head_2") == 0) {
_headNode = hier + i;
break;
}
}
if (_headNode) {
Model::HierNode *hn = _headNode->_parent;
while (hn) {
_headZ += hn->_animPos.z();
if (strcmp(hn->_name, "m_nck_b1") == 0)
_neckNode = hn;
hn = hn->_parent;
}
}
} }
Costume::~Costume() { Costume::~Costume() {
stopChores(); if (_chores) {
for (int i = _numComponents - 1; i >= 0; i--) { stopChores();
// The "Sprite" component can be NULL for (int i = _numComponents - 1; i >= 0; i--) {
if (_components[i]) // The "Sprite" component can be NULL
delete _components[i]; if (_components[i])
delete _components[i];
}
delete[] _components;
delete[] _chores;
g_resourceloader->uncacheCostume(this);
} }
delete[] _components;
delete[] _chores;
} }
Costume::Component::Component(Component *p, int parentID, tag32 t) { Costume::Component::Component(Component *p, int parentID, tag32 t) {
_visible = true; _visible = true;
_previousCmap = NULL; _previousCmap = NULL;
_cmap = NULL; _cmap = NULL;
@ -952,7 +1008,7 @@ void Costume::setColormap(const char *map) {
// see where raoul is gone in hh.set // see where raoul is gone in hh.set
if (!map) if (!map)
return; return;
_cmap = g_resourceloader->loadColormap(map); _cmap = g_resourceloader->getColormap(map);
for (int i = 0; i < _numComponents; i++) for (int i = 0; i < _numComponents; i++)
_components[i]->setColormap(NULL); _components[i]->setColormap(NULL);
} }
@ -1007,6 +1063,120 @@ void Costume::update() {
_components[i]->update(); _components[i]->update();
} }
} }
moveHead();
}
void Costume::moveHead() {
if (_headNode && _head.maxPitch) {
Model::HierNode *p = _headNode->_parent;
if (p && strcmp(p->_name, "m_head_2") == 0) { //Strange enough, when talking happens that a
//new "m_head_2" gets created as the parent of
//the old one.
return;
}
const int time = g_system->getMillis();
const int elapsed = time - _lastTime;
_lastTime = time;
float yawStep = 0.3 * elapsed;
float pitchStep = 0.1 * elapsed;
if (_lookAt.isZero()) {
//animate yaw
if (_headYaw > yawStep) {
_headYaw -= yawStep;
} else if (_headYaw < -yawStep) {
_headYaw += yawStep;
} else {
_headYaw = 0;
}
//animate pitch
if (_headPitch > pitchStep) {
_headPitch -= pitchStep;
} else if (_headPitch < -pitchStep) {
_headPitch += pitchStep;
} else {
_headPitch = 0;
}
_headNode->_animYaw = _headYaw;
_neckNode->_animPitch = _headPitch;
_headNode->_animRoll = _headNode->_animYaw / 10.;
if (_headNode->_animRoll > _head.maxRoll)
_headNode->_animRoll = _head.maxRoll;
if (_headNode->_animRoll < -_head.maxRoll)
_headNode->_animRoll = -_head.maxRoll;
return;
}
Graphics::Vector3d v = -(_headNode->_animPos + _matrix._pos + Graphics::Vector3d(0, 0, _headZ)) + _lookAt;
if (v.isZero()) {
return;
}
// cout<<_lookAt.x()<<" "<<_lookAt.y()<<" "<<_lookAt.z()<<" "<<v.x()<<" "<<v.y()<<" "<<v.z()<<endl;
float magnitude = sqrt(v.x() * v.x() + v.y() * v.y());
float a = v.x() / magnitude;
float b = v.y() / magnitude;
float yaw;
yaw = acos(a) * (180.0f / LOCAL_PI);
if (b < 0.0f)
yaw = 360.0f - yaw;
float h = sqrt(v.x() * v.x() + v.y() * v.y());
magnitude = sqrt(v.z() * v.z() + h * h);
a = h / magnitude;
b = v.z() / magnitude;
float pitch;
pitch = acos(a) * (180.0f / LOCAL_PI);
if (b < 0.0f)
pitch = 360.0f - pitch;
_neckNode->_animPitch = pitch;
_headNode->_animYaw = - 90 + yaw - _matrix._rot.getYaw();
if (_neckNode->_animPitch > 180)
_neckNode->_animPitch -= 360;
if (_headNode->_animYaw < 0)
_headNode->_animYaw += 360.;
if (_headNode->_animYaw > 180.)
_headNode->_animYaw -= 360;
//animate pitch
if (_neckNode->_animPitch - _headPitch > pitchStep)
_neckNode->_animPitch = _headPitch + pitchStep;
if (_headPitch - _neckNode->_animPitch > pitchStep)
_neckNode->_animPitch = _headPitch - pitchStep;
//animate yaw
if (_headNode->_animYaw - _headYaw > yawStep)
_headNode->_animYaw = _headYaw + yawStep;
if (_headYaw - _headNode->_animYaw > yawStep)
_headNode->_animYaw = _headYaw - yawStep;
if (_neckNode->_animPitch > _head.maxPitch)
_neckNode->_animPitch = _head.maxPitch;
if (_neckNode->_animPitch < -_head.maxPitch)
_neckNode->_animPitch = -_head.maxPitch;
if (_headNode->_animYaw > _head.maxYaw)
_headNode->_animYaw = _head.maxYaw;
if (_headNode->_animYaw < -_head.maxYaw)
_headNode->_animYaw = -_head.maxYaw;
_headNode->_animRoll = _headNode->_animYaw / 10.;
if (_headNode->_animRoll > _head.maxRoll)
_headNode->_animRoll = _head.maxRoll;
if (_headNode->_animRoll < -_head.maxRoll)
_headNode->_animRoll = -_head.maxRoll;
_headPitch = _neckNode->_animPitch;
_headYaw = _headNode->_animYaw;
}
}
void Costume::setLookAt(const Graphics::Vector3d &vec) {
_lookAt = vec;
} }
void Costume::setHead(int joint1, int joint2, int joint3, float maxRoll, float maxPitch, float maxYaw) { void Costume::setHead(int joint1, int joint2, int joint3, float maxRoll, float maxPitch, float maxYaw) {
@ -1023,4 +1193,62 @@ void Costume::setPosRotate(Graphics::Vector3d pos, float pitch, float yaw, float
_matrix._rot.buildFromPitchYawRoll(pitch, yaw, roll); _matrix._rot.buildFromPitchYawRoll(pitch, yaw, roll);
} }
Costume *Costume::previousCostume() const {
return _prevCostume;
}
void Costume::saveState(SaveGame *state) const {
if (_cmap) {
state->writeLEUint32(1);
state->writeCharString(_cmap->filename());
} else {
state->writeLEUint32(0);
}
for (int i = 0; i < _numChores; ++i) {
Chore &c = _chores[i];
state->writeLESint32(c._hasPlayed);
state->writeLESint32(c._playing);
state->writeLESint32(c._looping);
state->writeLESint32(c._currTime);
}
for (int i = 0; i < _numComponents; ++i) {
Component *c = _components[i];
if (c) {
state->writeLESint32(c->_visible);
state->writeVector3d(c->_matrix._pos);
}
}
}
bool Costume::restoreState(SaveGame *state) {
if (state->readLEUint32()) {
const char *str = state->readCharString();
setColormap(str);
delete[] str;
}
for (int i = 0; i < _numChores; ++i) {
Chore &c = _chores[i];
c._hasPlayed = state->readLESint32();
c._playing = state->readLESint32();
c._looping = state->readLESint32();
c._currTime = state->readLESint32();
}
for (int i = 0; i < _numComponents; ++i) {
Component *c = _components[i];
if (c) {
c->_visible = state->readLESint32();
c->_matrix._pos = state->readVector3d();
}
}
return true;
}
} // end of namespace Grim } // end of namespace Grim

View file

@ -27,6 +27,8 @@
#define GRIM_COSTUME_H #define GRIM_COSTUME_H
#include "engines/grim/model.h" #include "engines/grim/model.h"
#include "engines/grim/object.h"
#include "engines/grim/colormap.h"
namespace Grim { namespace Grim {
@ -34,11 +36,15 @@ namespace Grim {
typedef uint32 tag32; typedef uint32 tag32;
class Costume { class Costume : public Object {
GRIM_OBJECT(Costume)
public: public:
Costume(const char *filename, const char *data, int len, Costume *prevCost); Costume(const char *filename, const char *data, int len, Costume *prevCost);
Costume() : Object() { _chores = 0; }
~Costume(); void load(const char *filename, const char *data, int len, Costume *prevCost);
virtual ~Costume();
const char *filename() const { return _fname.c_str(); } const char *filename() const { return _fname.c_str(); }
void playChore(int num); void playChore(int num);
@ -47,12 +53,14 @@ public:
void setChoreLooping(int num, bool val) { _chores[num].setLooping(val); } void setChoreLooping(int num, bool val) { _chores[num].setLooping(val); }
void stopChore(int num) { _chores[num].stop(); } void stopChore(int num) { _chores[num].stop(); }
Model::HierNode *getModelNodes(); Model::HierNode *getModelNodes();
Model *getModel();
void setColormap(const char *map); void setColormap(const char *map);
void stopChores(); void stopChores();
int isChoring(const char *name, bool excludeLooping); int isChoring(const char *name, bool excludeLooping);
int isChoring(int num, bool excludeLooping); int isChoring(int num, bool excludeLooping);
int isChoring(bool excludeLooping); int isChoring(bool excludeLooping);
void setLookAt(const Graphics::Vector3d &vec);
void setHead(int joint1, int joint2, int joint3, float maxRoll, float maxPitch, float maxYaw); void setHead(int joint1, int joint2, int joint3, float maxRoll, float maxPitch, float maxYaw);
void update(); void update();
@ -60,6 +68,11 @@ public:
void draw(); void draw();
void setPosRotate(Graphics::Vector3d pos, float pitch, float yaw, float roll); void setPosRotate(Graphics::Vector3d pos, float pitch, float yaw, float roll);
Costume *previousCostume() const;
void saveState(SaveGame *state) const;
bool restoreState(SaveGame *state);
class Component { class Component {
public: public:
Component(Component *parent, int parentID, tag32 tag); Component(Component *parent, int parentID, tag32 tag);
@ -80,7 +93,7 @@ public:
virtual ~Component() { } virtual ~Component() { }
protected: protected:
CMap *_cmap, *_previousCmap; CMapPtr _cmap, _previousCmap;
tag32 _tag; tag32 _tag;
int _parentID; int _parentID;
bool _visible; bool _visible;
@ -95,7 +108,10 @@ public:
private: private:
Component *loadComponent(tag32 tag, Component *parent, int parentID, const char *name, Component *prevComponent); Component *loadComponent(tag32 tag, Component *parent, int parentID, const char *name, Component *prevComponent);
Common::String _fname; void moveHead();
Common::String _fname;
CostumePtr _prevCostume;
int _numComponents; int _numComponents;
Component **_components; Component **_components;
@ -147,10 +163,18 @@ private:
friend class Costume; friend class Costume;
}; };
CMap *_cmap; CMapPtr _cmap;
int _numChores; int _numChores;
Chore *_chores; Chore *_chores;
Graphics::Matrix4 _matrix; Graphics::Matrix4 _matrix;
Model::HierNode *_headNode;
Model::HierNode *_neckNode;
float _headZ;
Graphics::Vector3d _lookAt;
float _headPitch;
float _headYaw;
int _lastTime;
}; };
} // end of namespace Grim } // end of namespace Grim

View file

@ -26,58 +26,190 @@
#include "common/endian.h" #include "common/endian.h"
#include "engines/grim/grim.h" #include "engines/grim/grim.h"
#include "engines/grim/savegame.h"
#include "engines/grim/font.h" #include "engines/grim/font.h"
#include "engines/grim/lua.h"
#include <iostream>
using namespace std;
namespace Grim { namespace Grim {
Font::Font(const char *filename, const char *data, int /*len*/) { Font::Font(const char *filename, const char *data, int len) : Object() {
_fname = filename; load(filename, data, len);
_filename = filename;
_numChars = READ_LE_UINT32(data);
_dataSize = READ_LE_UINT32(data + 4);
_height = READ_LE_UINT32(data + 8);
_baseOffsetY = READ_LE_UINT32(data + 12);
_firstChar = READ_LE_UINT32(data + 24);
_lastChar = READ_LE_UINT32(data + 28);
data += 32;
// Read character indexes - are the key/value reversed?
_charIndex = new uint16[_numChars];
if (!_charIndex)
error("Could not load font %s. Out of memory", filename);
for (uint i = 0; i < _numChars; ++i) {
_charIndex[i] = READ_LE_UINT16(data + 2 * i);
}
data += _numChars * 2;
// Read character headers
_charHeaders = new CharHeader[_numChars];
if (!_charHeaders)
error("Could not load font %s. Out of memory", filename);
for (uint i = 0; i < _numChars; ++i) {
_charHeaders[i].offset = READ_LE_UINT32(data);
_charHeaders[i].width = *(int8 *)(data + 4);
_charHeaders[i].startingCol = *(int8 *)(data + 5);
_charHeaders[i].startingLine = *(int8 *)(data + 6);
_charHeaders[i].dataWidth = READ_LE_UINT32(data + 8);
_charHeaders[i].dataHeight = READ_LE_UINT32(data + 12);
data += 16;
}
// Read font data
_fontData = new byte[_dataSize];
if (!_fontData)
error("Could not load font %s. Out of memory", filename);
memcpy(_fontData, data, _dataSize);
} }
Font::~Font() { Font::~Font() {
delete[] _charIndex; if (_charIndex) {
delete[] _charHeaders; delete[] _charIndex;
delete[] _fontData; delete[] _charHeaders;
delete[] _fontData;
g_resourceloader->uncacheFont(this);
}
}
void Font::load(const char *filename, const char *data, int len) {
_fname = filename;
_filename = filename;
_numChars = READ_LE_UINT32(data);
_dataSize = READ_LE_UINT32(data + 4);
_height = READ_LE_UINT32(data + 8);
_baseOffsetY = READ_LE_UINT32(data + 12);
_firstChar = READ_LE_UINT32(data + 24);
_lastChar = READ_LE_UINT32(data + 28);
data += 32;
// Read character indexes - are the key/value reversed?
_charIndex = new uint16[_numChars];
if (!_charIndex)
error("Could not load font %s. Out of memory", filename);
for (uint i = 0; i < _numChars; ++i) {
_charIndex[i] = READ_LE_UINT16(data + 2 * i);
}
data += _numChars * 2;
// Read character headers
_charHeaders = new CharHeader[_numChars];
if (!_charHeaders)
error("Could not load font %s. Out of memory", filename);
for (uint i = 0; i < _numChars; ++i) {
_charHeaders[i].offset = READ_LE_UINT32(data);
_charHeaders[i].width = *(int8 *)(data + 4);
_charHeaders[i].startingCol = *(int8 *)(data + 5);
_charHeaders[i].startingLine = *(int8 *)(data + 6);
_charHeaders[i].dataWidth = READ_LE_UINT32(data + 8);
_charHeaders[i].dataHeight = READ_LE_UINT32(data + 12);
data += 16;
}
// Read font data
_fontData = new byte[_dataSize];
if (!_fontData)
error("Could not load font %s. Out of memory", filename);
memcpy(_fontData, data, _dataSize);
}
void Font::saveState(SaveGame *savedState) const {
int32 size;
const char *str;
str = _fname.c_str();
size = strlen(str);
savedState->writeLESint32(size);
savedState->write(str, size);
// savedState->writeLESint32(_fname.size());
// savedState->write(_fname.c_str(), _fname.size());
// savedState->writeLESint32(_filename.size());
// savedState->write(_filename.c_str(), _filename.size());
//
// //_fontData
// savedState->writeLEUint32(_dataSize);
// PointerId ptr = makeIdFromPointer(_fontData);
// // cout<<ptr.low<<endl;
// savedState->writeLEUint32(ptr.low);
// savedState->writeLEUint32(ptr.hi);
// for (uint32 i = 0; i < _dataSize; ++i) {
// savedState->writeByte(_fontData[i]);
// }
//
// //_charHeaders
// savedState->writeLEUint32(_numChars);
// ptr = makeIdFromPointer(_charHeaders);
// savedState->writeLEUint32(ptr.low);
// savedState->writeLEUint32(ptr.hi);
// // cout<<_numChars<<endl;
// for (uint32 i = 0; i < _numChars; ++i) {
// savedState->writeLESint32(_charHeaders[i].offset);
// savedState->writeLESint32(_charHeaders[i].width);
// savedState->writeLESint32(_charHeaders[i].startingCol);
// savedState->writeLESint32(_charHeaders[i].startingLine);
// savedState->writeLESint32(_charHeaders[i].dataWidth);
// savedState->writeLESint32(_charHeaders[i].dataHeight);
// }
//
// //_charIndex
// ptr = makeIdFromPointer(_charIndex);
// savedState->writeLEUint32(ptr.low);
// savedState->writeLEUint32(ptr.hi);
// for (uint32 i = 0; i < _numChars; ++i) {
// savedState->writeLEUint32(_charIndex[i]);
// }
//
// savedState->writeLEUint32(_firstChar);
// savedState->writeLEUint32(_lastChar);
// savedState->writeLEUint32(_height);
// savedState->writeLEUint32(_baseOffsetY);
}
bool Font::restoreState(SaveGame *savedState) {
int32 size;
char *str = 0;
// load actor name
size = savedState->readLESint32();
str = new char[size + 1];
savedState->read(str, size);
str[size] = '\0';
Block *b = g_resourceloader->getBlock(str);
if (b) {
load(str, b->data(), b->len());
}
delete[] str;
return true;
// int32 size = savedState->readLESint32();
// char *str = new char[size];
// savedState->read(str, size);
// _fname.load(str, size);
// delete str;
// size = savedState->readLESint32();
// str = new char[size];
// savedState->read(str, size);
// _filename.load(str, size);
// delete str;
//
// _dataSize = savedState->readLEUint32();
// PointerId ptr;
// ptr.low = savedState->readLEUint32();
// ptr.hi = savedState->readLEUint32();
// _fontData = static_cast<byte *>(makePointerFromId(ptr));
// for (uint32 i = 0; i < _dataSize; ++i) {
// _fontData[i] = savedState->readByte();
// }
//
// _numChars = savedState->readLEUint32();
// ptr.low = savedState->readLEUint32();
// ptr.hi = savedState->readLEUint32();
// _charHeaders = static_cast<CharHeader *>(makePointerFromId(ptr));
// for (uint32 i = 0; i < _numChars; ++i) {
// _charHeaders[i].offset = savedState->readLESint32();
// _charHeaders[i].width = savedState->readLESint32();
// _charHeaders[i].startingCol = savedState->readLESint32();
// _charHeaders[i].startingLine = savedState->readLESint32();
// _charHeaders[i].dataWidth = savedState->readLESint32();
// _charHeaders[i].dataHeight = savedState->readLESint32();
// }
//
// //_charIndex
// ptr.low = savedState->readLEUint32();
// ptr.hi = savedState->readLEUint32();
// _charIndex = static_cast<uint16 *>(makePointerFromId(ptr));
// for (uint32 i = 0; i < _numChars; ++i) {
// _charIndex[i] = savedState->readLEUint32();
// }
//
// _firstChar = savedState->readLEUint32();
// _lastChar = savedState->readLEUint32();
// _height = savedState->readLEUint32();
// _baseOffsetY = savedState->readLEUint32();
} }
uint16 Font::getCharIndex(unsigned char c) { uint16 Font::getCharIndex(unsigned char c) {

View file

@ -27,14 +27,21 @@
#define GRIM_FONT_H #define GRIM_FONT_H
#include "engines/grim/resource.h" #include "engines/grim/resource.h"
#include "engines/grim/object.h"
namespace Grim { namespace Grim {
class Font { class SaveGame;
class Font : public Object {
GRIM_OBJECT(Font)
public: public:
Font(const char *filename, const char *data, int len); Font(const char *filename, const char *data, int len);
Font() : Object() { _charIndex = 0; }
~Font(); ~Font();
void load(const char *filename, const char *data, int len);
Common::String getFilename() { return _filename; } Common::String getFilename() { return _filename; }
int32 getHeight() { return _height; } int32 getHeight() { return _height; }
int32 getBaseOffsetY() { return _baseOffsetY; } int32 getBaseOffsetY() { return _baseOffsetY; }
@ -45,6 +52,9 @@ public:
int32 getCharStartingLine(unsigned char c) { return _charHeaders[getCharIndex(c)].startingLine; } int32 getCharStartingLine(unsigned char c) { return _charHeaders[getCharIndex(c)].startingLine; }
const byte *getCharData(unsigned char c) { return _fontData + (_charHeaders[getCharIndex(c)].offset); } const byte *getCharData(unsigned char c) { return _fontData + (_charHeaders[getCharIndex(c)].offset); }
void saveState(SaveGame *savedState) const;
bool restoreState(SaveGame *savedState);
static const uint8 emerFont[][13]; static const uint8 emerFont[][13];
private: private:

View file

@ -249,6 +249,7 @@ void GfxOpenGL::startActorDraw(Graphics::Vector3d pos, float yaw, float pitch, f
// TODO find out why shadowMask at device in woods is null // TODO find out why shadowMask at device in woods is null
if (!_currentShadowArray->shadowMask) { if (!_currentShadowArray->shadowMask) {
_currentShadowArray->shadowMask = new byte[_screenWidth * _screenHeight]; _currentShadowArray->shadowMask = new byte[_screenWidth * _screenHeight];
_currentShadowArray->shadowMaskSize = _screenWidth * _screenHeight;
} }
SectorListType::iterator i = _currentShadowArray->planeList.begin(); SectorListType::iterator i = _currentShadowArray->planeList.begin();
Sector *shadowSector = *i; Sector *shadowSector = *i;

View file

@ -355,6 +355,7 @@ void GfxTinyGL::startActorDraw(Graphics::Vector3d pos, float yaw, float pitch, f
// TODO find out why shadowMask at device in woods is null // TODO find out why shadowMask at device in woods is null
if (!_currentShadowArray->shadowMask) { if (!_currentShadowArray->shadowMask) {
_currentShadowArray->shadowMask = new byte[_screenWidth * _screenHeight]; _currentShadowArray->shadowMask = new byte[_screenWidth * _screenHeight];
_currentShadowArray->shadowMaskSize = _screenWidth * _screenHeight;
} }
assert(_currentShadowArray->shadowMask); assert(_currentShadowArray->shadowMask);
//tglSetShadowColor(255, 255, 255); //tglSetShadowColor(255, 255, 255);
@ -400,6 +401,7 @@ void GfxTinyGL::drawShadowPlanes() {
tglEnable(TGL_SHADOW_MASK_MODE); tglEnable(TGL_SHADOW_MASK_MODE);
if (!_currentShadowArray->shadowMask) { if (!_currentShadowArray->shadowMask) {
_currentShadowArray->shadowMask = new byte[_screenWidth * _screenHeight]; _currentShadowArray->shadowMask = new byte[_screenWidth * _screenHeight];
_currentShadowArray->shadowMaskSize = _screenWidth * _screenHeight;
} }
memset(_currentShadowArray->shadowMask, 0, _screenWidth * _screenHeight); memset(_currentShadowArray->shadowMask, 0, _screenWidth * _screenHeight);

View file

@ -46,13 +46,26 @@
#include "engines/grim/localize.h" #include "engines/grim/localize.h"
#include "engines/grim/gfx_tinygl.h" #include "engines/grim/gfx_tinygl.h"
#include "engines/grim/gfx_opengl.h" #include "engines/grim/gfx_opengl.h"
#include "engines/grim/object.h"
#include "engines/grim/costume.h"
#include "engines/grim/material.h"
#include "engines/grim/lua/lualib.h" #include "engines/grim/lua/lualib.h"
#include "engines/grim/imuse/imuse.h" #include "engines/grim/imuse/imuse.h"
#include "lua/lobject.h"
#include "lua/lstate.h"
namespace Grim { namespace Grim {
static const bool color = ObjectManager::registerType<Color>();
static const bool luafile = ObjectManager::registerType<LuaFile>();
static const bool bitmap = ObjectManager::registerType<Bitmap>();
static const bool costume = ObjectManager::registerType<Costume>();
static const bool font = ObjectManager::registerType<Font>();
static const bool material = ObjectManager::registerType<Material>();
static bool g_lua_initialized = false; static bool g_lua_initialized = false;
// Entries in the system.controls table // Entries in the system.controls table
@ -308,10 +321,10 @@ GrimEngine::~GrimEngine() {
delete[] _controlsState; delete[] _controlsState;
for (SceneListType::const_iterator i = _scenes.begin(); i != _scenes.end(); ++i) for (SceneListType::const_iterator i = _scenes.begin(); i != _scenes.end(); ++i)
delete (*i); delete i->_value;
for (ActorListType::const_iterator i = _actors.begin(); i != _actors.end(); ++i) for (ActorListType::const_iterator i = _actors.begin(); i != _actors.end(); ++i)
delete (*i); delete i->_value;
killPrimitiveObjects(); killPrimitiveObjects();
killTextObjects(); killTextObjects();
@ -362,7 +375,7 @@ Common::Error GrimEngine::run() {
g_driver->setupScreen(640, 480, fullscreen); g_driver->setupScreen(640, 480, fullscreen);
Bitmap *splash_bm = NULL; BitmapPtr splash_bm;
if (!(_gameFlags & GF_DEMO)) if (!(_gameFlags & GF_DEMO))
splash_bm = g_resourceloader->loadBitmap("splash.bm"); splash_bm = g_resourceloader->loadBitmap("splash.bm");
@ -664,12 +677,12 @@ static void cameraPostChangeHandle(int num) {
void GrimEngine::drawPrimitives() { void GrimEngine::drawPrimitives() {
// Draw Primitives // Draw Primitives
for (PrimitiveListType::iterator i = _primitiveObjects.begin(); i != _primitiveObjects.end(); ++i) { for (PrimitiveListType::iterator i = _primitiveObjects.begin(); i != _primitiveObjects.end(); ++i) {
(*i)->draw(); i->_value->draw();
} }
// Draw text // Draw text
for (TextListType::iterator i = _textObjects.begin(); i != _textObjects.end(); ++i) { for (TextListType::iterator i = _textObjects.begin(); i != _textObjects.end(); ++i) {
(*i)->draw(); i->_value->draw();
} }
} }
@ -775,10 +788,10 @@ void GrimEngine::updateDisplayScene() {
// Update actor costumes & sets // Update actor costumes & sets
for (ActorListType::iterator i = _actors.begin(); i != _actors.end(); ++i) { for (ActorListType::iterator i = _actors.begin(); i != _actors.end(); ++i) {
Actor *a = *i; Actor *a = i->_value;
// Update the actor's costumes & chores // Update the actor's costumes & chores
g_currentUpdatedActor = *i; g_currentUpdatedActor = i->_value;
// Note that the actor need not be visible to update chores, for example: // Note that the actor need not be visible to update chores, for example:
// when Manny has just brought Meche back he is offscreen several times // when Manny has just brought Meche back he is offscreen several times
// when he needs to perform certain chores // when he needs to perform certain chores
@ -789,7 +802,7 @@ void GrimEngine::updateDisplayScene() {
// Draw actors // Draw actors
for (ActorListType::iterator i = _actors.begin(); i != _actors.end(); ++i) { for (ActorListType::iterator i = _actors.begin(); i != _actors.end(); ++i) {
Actor *a = *i; Actor *a = i->_value;
if (a->inSet(_currScene->name()) && a->visible()) if (a->inSet(_currScene->name()) && a->visible())
a->draw(); a->draw();
a->undraw(a->inSet(_currScene->name()) && a->visible()); a->undraw(a->inSet(_currScene->name()) && a->visible());
@ -955,6 +968,21 @@ void GrimEngine::savegameRestore() {
// free all resource // free all resource
// lock resources // lock resources
// killActors();
// killScenes();
// killPrimitiveObjects();
// killTextObjects();
// killFonts();
_selectedActor = NULL;
_currScene = NULL;
restoreObjectStates(_savedState);
restoreScenes(_savedState);
restoreTextObjects(_savedState);
restorePrimitives(_savedState);
restoreActors(_savedState);
//Chore_Restore(_savedState); //Chore_Restore(_savedState);
//Resource_Restore(_savedState); //Resource_Restore(_savedState);
//Text_Restore(_savedState); //Text_Restore(_savedState);
@ -969,7 +997,6 @@ void GrimEngine::savegameRestore() {
_savedState->endSection(); _savedState->endSection();
// unlock resources // unlock resources
delete _savedState; delete _savedState;
//bundle_dofile("patch05.bin"); //bundle_dofile("patch05.bin");
g_imuse->pause(false); g_imuse->pause(false);
@ -977,6 +1004,134 @@ void GrimEngine::savegameRestore() {
printf("GrimEngine::savegameRestore() finished.\n"); printf("GrimEngine::savegameRestore() finished.\n");
} }
void GrimEngine::restoreActors(SaveGame *state) {
state->beginSection('ACTR');
int32 size = state->readLEUint32();
for (int32 i = 0; i < size; ++i) {
int32 id = state->readLEUint32();
Actor *a = actor(id);
if (!a) {
a = new Actor();
a->_id = id;
registerActor(a);
if (id > Actor::s_id) {
Actor::s_id = id;
}
}
a->restoreState(state);
}
int32 id = state->readLEUint32();
if (id != 0) {
_selectedActor = _actors[id];
}
state->endSection();
}
void GrimEngine::restoreTextObjects(SaveGame *state) {
state->beginSection('TEXT');
sayLineDefaults.disabled = state->readLESint32();
sayLineDefaults.fgColor.red() = state->readByte();
sayLineDefaults.fgColor.green() = state->readByte();
sayLineDefaults.fgColor.blue() = state->readByte();
sayLineDefaults.font = g_resourceloader->getFont(state->readString().c_str());
sayLineDefaults.height = state->readLESint32();
sayLineDefaults.justify = state->readLESint32();
sayLineDefaults.width = state->readLESint32();
sayLineDefaults.x = state->readLESint32();
sayLineDefaults.y = state->readLESint32();
int32 size = state->readLESint32();
for (int32 i = 0; i < size; ++i) {
int32 id = state->readLEUint32();
TextObject *t = textObject(id);
if (!t) {
t = new TextObject();
t->_id = id;
registerTextObject(t);
if (id > TextObject::s_id) {
TextObject::s_id = id;
}
}
t->restoreState(state);
}
state->endSection();
}
void GrimEngine::restoreScenes(SaveGame *state) {
state->beginSection('SET ');
int32 size = state->readLESint32();
for (int32 i = 0; i < size; ++i) {
int32 id = state->readLEUint32();
Scene *s = scene(id);
if (!s) {
s = new Scene();
s->_id = id;
registerScene(s);
if (id > Scene::s_id) {
Scene::s_id = id;
}
}
s->restoreState(state);
}
_currScene = scene(state->readLEUint32());
state->endSection();
}
void GrimEngine::restorePrimitives(SaveGame *state) {
state->beginSection('PRIM');
int32 size = state->readLESint32();
for (int32 i = 0; i < size; ++i) {
int32 id = state->readLEUint32();
PrimitiveObject *p = primitiveObject(id);
if (!p) {
p = new PrimitiveObject();
p->_id = id;
registerPrimitiveObject(p);
if (id > PrimitiveObject::s_id) {
PrimitiveObject::s_id = id;
}
}
p->restoreState(state);
}
state->endSection();
}
void GrimEngine::restoreObjectStates(SaveGame *state) {
state->beginSection('STAT');
int32 size = state->readLESint32();
for (int32 i = 0; i < size; ++i) {
int32 id = state->readLEUint32();
ObjectState *o = objectState(id);
if (!o) {
o = new ObjectState();
o->_id = id;
registerObjectState(o);
if (id > ObjectState::s_id) {
ObjectState::s_id = id;
}
}
o->restoreState(state);
}
state->endSection();
}
void GrimEngine::storeSaveGameImage(SaveGame *state) { void GrimEngine::storeSaveGameImage(SaveGame *state) {
int width = 250, height = 188; int width = 250, height = 188;
Bitmap *screenshot; Bitmap *screenshot;
@ -1022,7 +1177,8 @@ void GrimEngine::savegameSave() {
savegameCallback(); savegameCallback();
saveFonts(_savedState); saveObjectStates(_savedState);
saveScenes(_savedState);
saveTextObjects(_savedState); saveTextObjects(_savedState);
savePrimitives(_savedState); savePrimitives(_savedState);
saveActors(_savedState); saveActors(_savedState);
@ -1050,47 +1206,30 @@ void GrimEngine::savegameSave() {
void GrimEngine::saveActors(SaveGame *state) { void GrimEngine::saveActors(SaveGame *state) {
state->beginSection('ACTR'); state->beginSection('ACTR');
state->writeLESint32(_actors.size()); state->writeLEUint32(_actors.size());
for (ActorListType::iterator i = _actors.begin(); i != _actors.end(); ++i) { for (ActorListType::iterator i = _actors.begin(); i != _actors.end(); ++i) {
Actor *a = *i; Actor *a = i->_value;
PointerId ptr = makeIdFromPointer(a); state->writeLEUint32(actorId(a));
state->writeLEUint32(ptr.low);
state->writeLEUint32(ptr.hi);
a->saveState(state); a->saveState(state);
} }
state->endSection(); if (_selectedActor) {
} state->writeLEUint32(actorId(_selectedActor));
} else {
void GrimEngine::saveFonts(SaveGame *state) { state->writeLEUint32(0);
state->beginSection('FONT');
state->writeLESint32(_fonts.size());
for (Common::List<Font *>::iterator i = _fonts.begin(); i != _fonts.end(); ++i) {
Font *f = *i;
PointerId ptr = makeIdFromPointer(f);
state->writeLEUint32(ptr.low);
state->writeLEUint32(ptr.hi);
Common::String filename = f->getFilename();
state->writeLESint32(filename.size());
state->write(filename.c_str(), filename.size());
} }
state->endSection(); state->endSection();
} }
void GrimEngine::saveTextObjects(SaveGame *state) { void GrimEngine::saveTextObjects(SaveGame *state) {
PointerId ptr;
state->beginSection('TEXT'); state->beginSection('TEXT');
state->writeLESint32(sayLineDefaults.disabled); state->writeLESint32(sayLineDefaults.disabled);
state->writeByte(sayLineDefaults.fgColor.red()); state->writeByte(sayLineDefaults.fgColor.red());
state->writeByte(sayLineDefaults.fgColor.green()); state->writeByte(sayLineDefaults.fgColor.green());
state->writeByte(sayLineDefaults.fgColor.blue()); state->writeByte(sayLineDefaults.fgColor.blue());
ptr = makeIdFromPointer(sayLineDefaults.font); state->writeString(sayLineDefaults.font->getFilename());
state->writeLEUint32(ptr.low);
state->writeLEUint32(ptr.hi);
state->writeLESint32(sayLineDefaults.height); state->writeLESint32(sayLineDefaults.height);
state->writeLESint32(sayLineDefaults.justify); state->writeLESint32(sayLineDefaults.justify);
state->writeLESint32(sayLineDefaults.width); state->writeLESint32(sayLineDefaults.width);
@ -1099,10 +1238,8 @@ void GrimEngine::saveTextObjects(SaveGame *state) {
state->writeLESint32(_textObjects.size()); state->writeLESint32(_textObjects.size());
for (TextListType::iterator i = _textObjects.begin(); i != _textObjects.end(); ++i) { for (TextListType::iterator i = _textObjects.begin(); i != _textObjects.end(); ++i) {
TextObject *t = *i; TextObject *t = i->_value;
ptr = makeIdFromPointer(t); state->writeLEUint32(i->_key);
state->writeLEUint32(ptr.low);
state->writeLEUint32(ptr.hi);
t->saveState(state); t->saveState(state);
} }
@ -1114,30 +1251,42 @@ void GrimEngine::saveScenes(SaveGame *state) {
state->writeLESint32(_scenes.size()); state->writeLESint32(_scenes.size());
for (SceneListType::iterator i = _scenes.begin(); i != _scenes.end(); ++i) { for (SceneListType::iterator i = _scenes.begin(); i != _scenes.end(); ++i) {
Scene *s = *i; Scene *s = i->_value;
state->writeLEUint32(s->_id);
s->saveState(state); s->saveState(state);
} }
state->writeLEUint32(_currScene->_id);
state->endSection(); state->endSection();
} }
void GrimEngine::savePrimitives(SaveGame *state) { void GrimEngine::savePrimitives(SaveGame *state) {
PointerId ptr;
state->beginSection('PRIM'); state->beginSection('PRIM');
state->writeLESint32(_primitiveObjects.size()); state->writeLESint32(_primitiveObjects.size());
for (PrimitiveListType::iterator i = _primitiveObjects.begin(); i != _primitiveObjects.end(); ++i) { for (PrimitiveListType::iterator i = _primitiveObjects.begin(); i != _primitiveObjects.end(); ++i) {
PrimitiveObject *p = *i; PrimitiveObject *p = i->_value;
ptr = makeIdFromPointer(p); state->writeLEUint32(p->_id);
state->writeLEUint32(ptr.low);
state->writeLEUint32(ptr.hi);
p->saveState(state); p->saveState(state);
} }
state->endSection(); state->endSection();
} }
void GrimEngine::saveObjectStates(SaveGame *state) {
state->beginSection('STAT');
state->writeLESint32(_objectStates.size());
for (Common::HashMap<int, ObjectState *>::iterator i = _objectStates.begin(); i != _objectStates.end(); ++i) {
ObjectState *o = i->_value;
state->writeLEUint32(o->_id);
o->saveState(state);
}
state->endSection();
}
void GrimEngine::savegameCallback() { void GrimEngine::savegameCallback() {
lua_Object funcParam1; lua_Object funcParam1;
@ -1169,8 +1318,8 @@ void GrimEngine::savegameCallback() {
Scene *GrimEngine::findScene(const char *name) { Scene *GrimEngine::findScene(const char *name) {
// Find scene object // Find scene object
for (SceneListType::const_iterator i = scenesBegin(); i != scenesEnd(); ++i) { for (SceneListType::const_iterator i = scenesBegin(); i != scenesEnd(); ++i) {
if (!strcmp((*i)->name(), name)) if (!strcmp(i->_value->name(), name))
return *i; return i->_value;
} }
return NULL; return NULL;
} }
@ -1212,7 +1361,6 @@ void GrimEngine::setScene(const char *name) {
void GrimEngine::setScene(Scene *scene) { void GrimEngine::setScene(Scene *scene) {
Scene *lastScene = _currScene; Scene *lastScene = _currScene;
_currScene = scene; _currScene = scene;
_currScene->setSoundParameters(20, 127); _currScene->setSoundParameters(20, 127);
// should delete the old scene after setting the new one // should delete the old scene after setting the new one
@ -1248,4 +1396,121 @@ bool GrimEngine::getControlState(int num) {
return _controlsState[num]; return _controlsState[num];
} }
void GrimEngine::registerTextObject(TextObject *t) {
_textObjects[t->_id] = t;
}
void GrimEngine::killTextObject(TextObject *t) {
_textObjects.erase(t->_id);
delete t;
}
void GrimEngine::killTextObjects() {
while (!_textObjects.empty()) {
killTextObject(_textObjects.begin()->_value);
}
}
int GrimEngine::textObjectId(TextObject *t) const {
return t->_id;
}
TextObject *GrimEngine::textObject(int id) const {
return _textObjects[id];
}
void GrimEngine::registerActor(Actor *a) {
_actors[a->_id] = a;
}
void GrimEngine::killActor(Actor *a) {
_actors.erase(a->_id);
}
void GrimEngine::killActors() {
// _actors.clear();
// while (!_actors.empty()) {
// delete _actors.back();
// _actors.pop_back();
// }
}
int GrimEngine::actorId(Actor *a) const {
return a->_id;
}
Actor *GrimEngine::actor(int id) const {
if (_actors.contains(id)) {
return _actors[id];
}
return 0;
}
void GrimEngine::registerObjectState(ObjectState *o) {
_objectStates[o->_id] = o;
}
void GrimEngine::killObjectState(ObjectState *o) {
_objectStates.erase(o->_id);
}
void GrimEngine::killObjectStates() {
}
int GrimEngine::objectStateId(ObjectState *o) const {
return o->_id;
}
ObjectState *GrimEngine::objectState(int id) const {
return _objectStates[id];
}
void GrimEngine::registerPrimitiveObject(PrimitiveObject *p) {
_primitiveObjects[p->_id] = p;
}
void GrimEngine::killPrimitiveObject(PrimitiveObject *p) {
_primitiveObjects.erase(p->_id);
}
void GrimEngine::killPrimitiveObjects() {
while (!_primitiveObjects.empty()) {
PrimitiveObject *p = _primitiveObjects.begin()->_value;
killPrimitiveObject(p);
delete p;
}
}
int GrimEngine::primitiveObjectId(PrimitiveObject *p) const {
return p->_id;
}
PrimitiveObject *GrimEngine::primitiveObject(int id) const {
return _primitiveObjects[id];
}
void GrimEngine::registerScene(Scene *s) {
_scenes[s->_id] = s;
}
void GrimEngine::removeScene(Scene *s) {
_scenes.erase(s->_id);
}
void GrimEngine::killScenes() {
while (!_scenes.empty()) {
removeScene(_scenes.begin()->_value);
}
}
int GrimEngine::sceneId(Scene *s) const {
return s->_id;
}
Scene *GrimEngine::scene(int id) const {
return _scenes[id];
}
} // end of namespace Grim } // end of namespace Grim

View file

@ -127,17 +127,18 @@ public:
void makeCurrentSetup(int num); void makeCurrentSetup(int num);
// Scene registration // Scene registration
typedef Common::List<Scene *> SceneListType; typedef Common::HashMap<int, Scene *> SceneListType;
SceneListType::const_iterator scenesBegin() const { SceneListType::const_iterator scenesBegin() const {
return _scenes.begin(); return _scenes.begin();
} }
SceneListType::const_iterator scenesEnd() const { SceneListType::const_iterator scenesEnd() const {
return _scenes.end(); return _scenes.end();
} }
void registerScene(Scene *a) { _scenes.push_back(a); } void registerScene(Scene *a);
void removeScene(Scene *a) { void removeScene(Scene *a);
_scenes.remove(a); void killScenes();
} int sceneId(Scene *s) const;
Scene *scene(int id) const;
void flagRefreshShadowMask(bool flag) { void flagRefreshShadowMask(bool flag) {
_refreshShadowMask = flag; _refreshShadowMask = flag;
@ -156,43 +157,44 @@ public:
_bitmaps.push_back(b); _bitmaps.push_back(b);
return b; return b;
} }
void registerBitmap(Bitmap *bitmap) {
_bitmaps.push_back(bitmap);
}
void killBitmap(Bitmap *b) { _bitmaps.remove(b); } void killBitmap(Bitmap *b) { _bitmaps.remove(b); }
// Actor registration // Actor registration
typedef Common::List<Actor *> ActorListType; typedef Common::HashMap<int, Actor *> ActorListType;
ActorListType::const_iterator actorsBegin() const { ActorListType::const_iterator actorsBegin() const {
return _actors.begin(); return _actors.begin();
} }
ActorListType::const_iterator actorsEnd() const { ActorListType::const_iterator actorsEnd() const {
return _actors.end(); return _actors.end();
} }
void registerActor(Actor *a) { _actors.push_back(a); } void registerActor(Actor *a);
void killActor(Actor *a) { _actors.remove(a); } void killActor(Actor *a);
int actorId(Actor *a) const;
Actor *actor(int id) const;
void setSelectedActor(Actor *a) { _selectedActor = a; } void setSelectedActor(Actor *a) { _selectedActor = a; }
Actor *selectedActor() { return _selectedActor; } Actor *selectedActor() { return _selectedActor; }
void killActors();
// Text Object Registration // Text Object Registration
typedef Common::List<TextObject *> TextListType; typedef Common::HashMap<int, TextObject *> TextListType;
TextListType::const_iterator textsBegin() const { TextListType::const_iterator textsBegin() const {
return _textObjects.begin(); return _textObjects.begin();
} }
TextListType::const_iterator textsEnd() const { TextListType::const_iterator textsEnd() const {
return _textObjects.end(); return _textObjects.end();
} }
void registerTextObject(TextObject *a) { _textObjects.push_back(a); } void registerTextObject(TextObject *a);
void killTextObject(TextObject *a) { void killTextObject(TextObject *a);
_textObjects.remove(a); void killTextObjects();
delete a; int textObjectId(TextObject *t) const;
} TextObject *textObject(int id) const;
void killTextObjects() {
while (!_textObjects.empty()) {
delete _textObjects.back();
_textObjects.pop_back();
}
}
// Primitives Object Registration // Primitives Object Registration
typedef Common::List<PrimitiveObject *> PrimitiveListType; typedef Common::HashMap<int, PrimitiveObject *> PrimitiveListType;
PrimitiveListType::const_iterator primitivesBegin() const { PrimitiveListType::const_iterator primitivesBegin() const {
return _primitiveObjects.begin(); return _primitiveObjects.begin();
} }
@ -200,29 +202,31 @@ public:
return _primitiveObjects.end(); return _primitiveObjects.end();
} }
void registerPrimitiveObject(PrimitiveObject *a) { _primitiveObjects.push_back(a); } void registerPrimitiveObject(PrimitiveObject *a);
void killPrimitiveObject(PrimitiveObject *a) { void killPrimitiveObject(PrimitiveObject *a);
_primitiveObjects.remove(a); void killPrimitiveObjects();
} int primitiveObjectId(PrimitiveObject *p) const;
void killPrimitiveObjects() { PrimitiveObject *primitiveObject(int id) const;
while (!_primitiveObjects.empty()) {
delete _primitiveObjects.back();
_primitiveObjects.pop_back();
}
}
void registerFont(Font *a) { _fonts.push_back(a); } void registerObjectState(ObjectState *o);
void unregisterFont(Font *a) { void killObjectState(ObjectState *o);
_fonts.remove(a); void killObjectStates();
} int objectStateId(ObjectState *o) const;
ObjectState *objectState(int id) const;
void savegameSave(); void savegameSave();
void savegameRestore();
void saveActors(SaveGame *savedState); void saveActors(SaveGame *savedState);
void saveFonts(SaveGame *savedState);
void saveTextObjects(SaveGame *savedState); void saveTextObjects(SaveGame *savedState);
void savePrimitives(SaveGame *savedState); void savePrimitives(SaveGame *savedState);
void saveScenes(SaveGame *savedState); void saveScenes(SaveGame *savedState);
void saveObjectStates(SaveGame *savedState);
void savegameRestore();
void restoreActors(SaveGame *savedState);
void restoreTextObjects(SaveGame *savedState);
void restorePrimitives(SaveGame *savedState);
void restoreScenes(SaveGame *savedState);
void restoreObjectStates(SaveGame *savedState);
void savegameCallback(); void savegameCallback();
static void savegameReadStream(void *data, int32 size); static void savegameReadStream(void *data, int32 size);
@ -274,8 +278,8 @@ private:
Actor *_selectedActor; Actor *_selectedActor;
TextListType _textObjects; TextListType _textObjects;
PrimitiveListType _primitiveObjects; PrimitiveListType _primitiveObjects;
Common::List<Font *> _fonts;
Common::List<Bitmap *> _bitmaps; Common::List<Bitmap *> _bitmaps;
Common::HashMap<int, ObjectState *> _objectStates;
int _gameFlags; int _gameFlags;
}; };

View file

@ -31,7 +31,8 @@
namespace Grim { namespace Grim {
KeyframeAnim::KeyframeAnim(const char *fname, const char *data, int len) { KeyframeAnim::KeyframeAnim(const char *fname, const char *data, int len) :
Object() {
_fname = fname; _fname = fname;
if (len >= 4 && READ_BE_UINT32(data) == MKID_BE('FYEK')) if (len >= 4 && READ_BE_UINT32(data) == MKID_BE('FYEK'))
@ -140,6 +141,7 @@ KeyframeAnim::~KeyframeAnim() {
for (int i = 0; i < _numJoints; i++) for (int i = 0; i < _numJoints; i++)
delete _nodes[i]; delete _nodes[i];
delete[] _markers; delete[] _markers;
g_resourceloader->uncacheKeyframe(this);
} }
void KeyframeAnim::animate(Model::HierNode *nodes, float time, int priority1, int priority2) const { void KeyframeAnim::animate(Model::HierNode *nodes, float time, int priority1, int priority2) const {

View file

@ -27,10 +27,12 @@
#define GRIM_KEYFRAME_H #define GRIM_KEYFRAME_H
#include "engines/grim/model.h" #include "engines/grim/model.h"
#include "engines/grim/object.h"
namespace Grim { namespace Grim {
class KeyframeAnim { class KeyframeAnim : public Object {
GRIM_OBJECT(KeyFrameAnim)
public: public:
KeyframeAnim(const char *filename, const char *data, int len); KeyframeAnim(const char *filename, const char *data, int len);
~KeyframeAnim(); ~KeyframeAnim();

View file

@ -32,7 +32,8 @@ namespace Grim {
// A new define that'll be around when theres a configure script :) // A new define that'll be around when theres a configure script :)
#undef DEBUG_VERBOSE #undef DEBUG_VERBOSE
LipSync::LipSync(const char *filename, const char *data, int len) { LipSync::LipSync(const char *filename, const char *data, int len) :
Object() {
_fname = filename; _fname = filename;
uint16 readPhoneme; uint16 readPhoneme;
int j; int j;
@ -76,6 +77,7 @@ LipSync::LipSync(const char *filename, const char *data, int len) {
LipSync::~LipSync() { LipSync::~LipSync() {
delete[] _entries; delete[] _entries;
g_resourceloader->uncacheLipSync(this);
} }
int LipSync::getAnim(int pos) { int LipSync::getAnim(int pos) {
@ -100,6 +102,10 @@ int LipSync::getAnim(int pos) {
return -1; return -1;
} }
const char *LipSync::filename() const {
return _fname.c_str();
}
const LipSync::PhonemeAnim LipSync::_animTable[] = { const LipSync::PhonemeAnim LipSync::_animTable[] = {
{0x005F, 0}, {0x0251, 1}, {0x0061, 1}, {0x00E6, 1}, {0x028C, 8}, {0x005F, 0}, {0x0251, 1}, {0x0061, 1}, {0x00E6, 1}, {0x028C, 8},
{0x0254, 1}, {0x0259, 1}, {0x0062, 6}, {0x02A7, 2}, {0x0064, 2}, {0x0254, 1}, {0x0259, 1}, {0x0062, 6}, {0x02A7, 2}, {0x0064, 2},

View file

@ -27,10 +27,11 @@
#define GRIM_LIPSYNC_H #define GRIM_LIPSYNC_H
#include "engines/grim/resource.h" #include "engines/grim/resource.h"
#include "engines/grim/object.h"
namespace Grim { namespace Grim {
class LipSync { class LipSync : public Object {
public: public:
LipSync(const char *filename, const char *data, int len); LipSync(const char *filename, const char *data, int len);
~LipSync(); ~LipSync();
@ -42,6 +43,9 @@ public:
int getAnim(int pos); int getAnim(int pos);
bool isValid() { return _numEntries > 0; } bool isValid() { return _numEntries > 0; }
const char *filename() const;
int typeId() const { return 16; }
private: private:
LipEntry *_entries; LipEntry *_entries;

View file

@ -75,6 +75,7 @@ static void checkCparams(int32 nParams) {
static lua_Object put_luaObject(TObject *o) { static lua_Object put_luaObject(TObject *o) {
luaD_openstack((lua_state->stack.top - lua_state->stack.stack) - lua_state->Cstack.base); luaD_openstack((lua_state->stack.top - lua_state->stack.stack) - lua_state->Cstack.base);
lua_state->stack.stack[lua_state->Cstack.base++] = *o; lua_state->stack.stack[lua_state->Cstack.base++] = *o;
return lua_state->Cstack.base; // this is +1 real position (see Ref) return lua_state->Cstack.base; // this is +1 real position (see Ref)
} }
@ -414,15 +415,21 @@ int32 lua_setlocal(lua_Function func, int32 local_number) {
void lua_funcinfo(lua_Object func, const char **filename, int32 *linedefined) { void lua_funcinfo(lua_Object func, const char **filename, int32 *linedefined) {
if (!lua_isfunction(func)) if (!lua_isfunction(func))
lua_error("API - `funcinfo' called with a non-function value"); lua_error("API - `funcinfo' called with a non-function value");
else { else {
TObject *f = luaA_protovalue(Address(func)); //FIXME: After loading a savegame tfvalue(f) will point to a
if (normalized_type(f) == LUA_T_PROTO) { // TProtoFunc which was deleted by lua_close(), called by lua_restore(). so
*filename = tfvalue(f)->fileName->str; // it will crash. Anyway commenting it doesn't seem to cause any harm aside the
*linedefined = tfvalue(f)->lineDefined; // fact that an eventual lua stack will not report the file names.
} else { // So it is commented until we come up with a fix.
// TObject *f = luaA_protovalue(Address(func));
// if (normalized_type(f) == LUA_T_PROTO) {
// *filename = tfvalue(f)->fileName->str;
// *linedefined = tfvalue(f)->lineDefined;
// } else {
*filename = "(C)"; *filename = "(C)";
*linedefined = -1; *linedefined = -1;
} // }
} }
} }

View file

@ -320,7 +320,7 @@ void lua_error(const char *s) {
static void do_callinc(int32 nResults) { static void do_callinc(int32 nResults) {
StkId base = lua_state->Cstack.base; StkId base = lua_state->Cstack.base;
luaD_call(base + 1, nResults); luaD_call(base + 1, nResults);
lua_state->Cstack.lua2C = base; // position of the luaM_new results lua_state->Cstack.lua2C = base; // position of the luaM_new results
lua_state->Cstack.num = (lua_state->stack.top - lua_state->stack.stack) - base; // number of results lua_state->Cstack.num = (lua_state->stack.top - lua_state->stack.stack) - base; // number of results
lua_state->Cstack.base = base + lua_state->Cstack.num; // incorporate results on lua_state->stack.stack/ lua_state->Cstack.base = base + lua_state->Cstack.num; // incorporate results on lua_state->stack.stack/
} }
@ -373,10 +373,10 @@ static int32 protectedparser(ZIO *z, int32 bin) {
} }
lua_state->errorJmp = oldErr; lua_state->errorJmp = oldErr;
if (status) if (status)
return 1; // error code return 1; // error code
if (tf == NULL) if (tf == NULL)
return 2; // 'natural' end return 2; // 'natural' end
luaD_adjusttop(lua_state->Cstack.base + 1); // one slot for the pseudo-function luaD_adjusttop(lua_state->Cstack.base + 1); // one slot for the pseudo-function
lua_state->stack.stack[lua_state->Cstack.base].ttype = LUA_T_PROTO; lua_state->stack.stack[lua_state->Cstack.base].ttype = LUA_T_PROTO;
lua_state->stack.stack[lua_state->Cstack.base].value.tf = tf; lua_state->stack.stack[lua_state->Cstack.base].value.tf = tf;
luaV_closure(0); luaV_closure(0);
@ -391,7 +391,7 @@ static int32 do_main(ZIO *z, int32 bin) {
if (status == 1) if (status == 1)
return 1; // error return 1; // error
else if (status == 2) else if (status == 2)
return 0; // 'natural' end return 0; // 'natural' end
else { else {
int32 newelems2 = 2 * (nblocks - old_blocks); int32 newelems2 = 2 * (nblocks - old_blocks);
GCthreshold += newelems2; GCthreshold += newelems2;

View file

@ -100,6 +100,46 @@ void LuaFile::seek(int32 pos, int whence) {
assert(0); assert(0);
} }
void LuaFile::saveState(SaveGame *state) const {
state->writeString(_name);
state->writeString(_filename);
if (_in) {
state->writeLESint32(1);
} else {
state->writeLESint32(0);
}
if (_out) {
state->writeLESint32(1);
} else {
state->writeLESint32(0);
}
state->writeLESint32(_stdin);
state->writeLESint32(_stdout);
state->writeLESint32(_stderr);
}
bool LuaFile::restoreState(SaveGame *state) {
_name = state->readString();;
_filename = state->readString();
if (state->readLESint32()) {
Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
_in = saveFileMan->openForLoading(_filename.c_str());
}
if (state->readLESint32()) {
Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
_out = saveFileMan->openForSaving(_filename.c_str());
}
_stdin = state->readLESint32();
_stdout = state->readLESint32();
_stderr = state->readLESint32();
return true;
}
static int32 gettag(int32 i) { static int32 gettag(int32 i) {
return (int32)lua_getnumber(lua_getparam(i)); return (int32)lua_getnumber(lua_getparam(i));
} }
@ -179,6 +219,7 @@ static void io_readfrom() {
else { else {
current = new LuaFile(); current = new LuaFile();
current->_in = inFile; current->_in = inFile;
current->_filename = s;
} }
if (!current) { if (!current) {
delete current; delete current;
@ -217,6 +258,7 @@ static void io_writeto() {
} }
current = new LuaFile(); current = new LuaFile();
current->_out = outFile; current->_out = outFile;
current->_filename = s;
setreturn(current, FOUTPUT); setreturn(current, FOUTPUT);
} }
} }
@ -243,6 +285,7 @@ static void io_appendto() {
outFile->write(buf, size); outFile->write(buf, size);
LuaFile *current = new LuaFile(); LuaFile *current = new LuaFile();
current->_out = outFile; current->_out = outFile;
current->_filename = s;
setreturn(current, FOUTPUT); setreturn(current, FOUTPUT);
} }
delete[] buf; delete[] buf;
@ -351,7 +394,7 @@ static void lua_printstack() {
case 't': case 't':
sprintf(buf, "`%s' tag method", name); sprintf(buf, "`%s' tag method", name);
break; break;
default: default:
{ {
if (linedefined == 0) if (linedefined == 0)
sprintf(buf, "main of %s", filename); sprintf(buf, "main of %s", filename);

View file

@ -6,6 +6,8 @@
#include "engines/grim/lua/lobject.h" #include "engines/grim/lua/lobject.h"
#include "engines/grim/lua/lua.h" #include "engines/grim/lua/lua.h"
#include "engines/grim/lua/lstring.h"
#include "engines/grim/lua/lstate.h"
namespace Grim { namespace Grim {
@ -78,4 +80,23 @@ void luaO_insertlist(GCnode *root, GCnode *node) {
node->marked = 0; node->marked = 0;
} }
void luaO_resetObject(void *o) {
TaggedString *tempString;
if (string_root) {
for (int i = 0; i < NUM_HASHS; i++) {
stringtable *tempStringTable = &string_root[i];
for (int l = 0; l < tempStringTable->size; l++) {
if (tempStringTable->hash[l] && tempStringTable->hash[l] != &EMPTY) {
tempString = tempStringTable->hash[l];
if (tempString->constindex == -1) {
if (tempString->globalval.value.ts == o) {
tempString->globalval.value.ts = NULL;
}
}
}
}
}
}
}
} // end of namespace Grim } // end of namespace Grim

View file

@ -142,6 +142,8 @@ int32 luaO_redimension(int32 oldsize);
int luaO_findstring(const char *name, const char *list[]); int luaO_findstring(const char *name, const char *list[]);
void luaO_insertlist(GCnode *root, GCnode *node); void luaO_insertlist(GCnode *root, GCnode *node);
void luaO_resetObject(void *o);
#define luaO_memup(d, s, n) memmove(d, s, n) #define luaO_memup(d, s, n) memmove(d, s, n)
#define luaO_memdown(d, s, n) memmove(d, s, n) #define luaO_memdown(d, s, n) memmove(d, s, n)

View file

@ -265,7 +265,7 @@ void lua_Restore(RestoreStream restoreStream, RestoreSint32 restoreSint32, Resto
restoreObjectValue(&obj, restoreSint32, restoreUint32); restoreObjectValue(&obj, restoreSint32, restoreUint32);
int32 length = restoreSint32(); int32 length = restoreSint32();
restoreStream(tempStringBuffer, length); restoreStream(tempStringBuffer, length);
tempStringBuffer[length] = 0; tempStringBuffer[length] = '\0';
tempString = luaS_new(tempStringBuffer); tempString = luaS_new(tempStringBuffer);
tempString->globalval = obj; tempString->globalval = obj;
} else { } else {
@ -273,10 +273,30 @@ void lua_Restore(RestoreStream restoreStream, RestoreSint32 restoreSint32, Resto
lua_Type tag = (lua_Type)restoreSint32(); lua_Type tag = (lua_Type)restoreSint32();
ptr.low = restoreUint32(); ptr.low = restoreUint32();
ptr.hi = restoreUint32(); ptr.hi = restoreUint32();
void *pointer = 0;
if (restoreUint32()) {
int x = restoreUint32();
if (x == 1) {
int id = restoreUint32();
pointer = g_grim->actor(id);
} else if (x == 2) {
int id = restoreUint32();
pointer = g_grim->textObject(id);
} else if (x == 3) {
int id = restoreUint32();
pointer = g_grim->objectState(id);
} else {
pointer = ObjectManager::restoreObject(g_grim->_savedState);
}
if (!pointer) {
pointer = makePointerFromId(ptr);
}
}
if (tag == 0) if (tag == 0)
tempString = luaS_createudata((void *)makePointerFromId(ptr), LUA_ANYTAG); tempString = luaS_createudata(pointer, LUA_ANYTAG);
else else
tempString = luaS_createudata((void *)makePointerFromId(ptr), tag); tempString = luaS_createudata(pointer, tag);
if (restoreCallbackPtr) { if (restoreCallbackPtr) {
ptr = makeIdFromPointer(tempString->globalval.value.ts); ptr = makeIdFromPointer(tempString->globalval.value.ts);
ptr = restoreCallbackPtr(tempString->globalval.ttype, ptr, restoreSint32); ptr = restoreCallbackPtr(tempString->globalval.ttype, ptr, restoreSint32);
@ -293,6 +313,7 @@ void lua_Restore(RestoreStream restoreStream, RestoreSint32 restoreSint32, Resto
int32 l; int32 l;
Closure *tempClosure; Closure *tempClosure;
GCnode *prevClosure = &rootcl;
arraysObj = (ArrayIDObj *)luaM_malloc(sizeof(ArrayIDObj) * arrayClosuresCount); arraysObj = (ArrayIDObj *)luaM_malloc(sizeof(ArrayIDObj) * arrayClosuresCount);
arrayClosures = arraysObj; arrayClosures = arraysObj;
for (i = 0; i < arrayClosuresCount; i++) { for (i = 0; i < arrayClosuresCount; i++) {
@ -300,7 +321,8 @@ void lua_Restore(RestoreStream restoreStream, RestoreSint32 restoreSint32, Resto
arraysObj->idObj.hi = restoreSint32(); arraysObj->idObj.hi = restoreSint32();
int32 countElements = restoreSint32(); int32 countElements = restoreSint32();
tempClosure = (Closure *)luaM_malloc((countElements * sizeof(TObject)) + sizeof(Closure)); tempClosure = (Closure *)luaM_malloc((countElements * sizeof(TObject)) + sizeof(Closure));
luaO_insertlist(&rootcl, (GCnode *)tempClosure); luaO_insertlist(prevClosure, (GCnode *)tempClosure);
prevClosure = (GCnode *)tempClosure;
tempClosure->nelems = countElements; tempClosure->nelems = countElements;
for (l = 0; l <= tempClosure->nelems; l++) { for (l = 0; l <= tempClosure->nelems; l++) {
@ -311,6 +333,7 @@ void lua_Restore(RestoreStream restoreStream, RestoreSint32 restoreSint32, Resto
} }
Hash *tempHash; Hash *tempHash;
GCnode *prevHash = &roottable;
arraysObj = (ArrayIDObj *)luaM_malloc(sizeof(ArrayIDObj) * arrayHashTablesCount); arraysObj = (ArrayIDObj *)luaM_malloc(sizeof(ArrayIDObj) * arrayHashTablesCount);
arrayHashTables = arraysObj; arrayHashTables = arraysObj;
for (i = 0; i < arrayHashTablesCount; i++) { for (i = 0; i < arrayHashTablesCount; i++) {
@ -321,7 +344,8 @@ void lua_Restore(RestoreStream restoreStream, RestoreSint32 restoreSint32, Resto
tempHash->nuse = restoreSint32(); tempHash->nuse = restoreSint32();
tempHash->htag = restoreSint32(); tempHash->htag = restoreSint32();
tempHash->node = hashnodecreate(tempHash->nhash); tempHash->node = hashnodecreate(tempHash->nhash);
luaO_insertlist(&roottable, (GCnode *)tempHash); luaO_insertlist(prevHash, (GCnode *)tempHash);
prevHash = (GCnode *)tempHash;
for (l = 0; l < tempHash->nuse; l++) { for (l = 0; l < tempHash->nuse; l++) {
restoreObjectValue(&tempHash->node[l].ref, restoreSint32, restoreUint32); restoreObjectValue(&tempHash->node[l].ref, restoreSint32, restoreUint32);
@ -332,20 +356,26 @@ void lua_Restore(RestoreStream restoreStream, RestoreSint32 restoreSint32, Resto
} }
TProtoFunc *tempProtoFunc; TProtoFunc *tempProtoFunc;
GCnode *oldProto = &rootproto;
arrayProtoFuncs = (ArrayIDObj *)luaM_malloc(sizeof(ArrayIDObj) * arrayProtoFuncsCount); arrayProtoFuncs = (ArrayIDObj *)luaM_malloc(sizeof(ArrayIDObj) * arrayProtoFuncsCount);
arraysObj = arrayProtoFuncs; arraysObj = arrayProtoFuncs;
for (i = 0; i < arrayProtoFuncsCount; i++) { for (i = 0; i < arrayProtoFuncsCount; i++) {
arraysObj->idObj.low = restoreSint32(); arraysObj->idObj.low = restoreSint32();
arraysObj->idObj.hi = restoreSint32(); arraysObj->idObj.hi = restoreSint32();
tempProtoFunc = luaM_new(TProtoFunc); tempProtoFunc = luaM_new(TProtoFunc);
luaO_insertlist(&rootproto, (GCnode *)tempProtoFunc); luaO_insertlist(oldProto, (GCnode *)tempProtoFunc);
oldProto = (GCnode *)tempProtoFunc;
PointerId ptr; PointerId ptr;
ptr.low = restoreSint32(); ptr.low = restoreSint32();
ptr.hi = restoreSint32(); ptr.hi = restoreSint32();
tempProtoFunc->fileName = (TaggedString *)makePointerFromId(ptr); tempProtoFunc->fileName = (TaggedString *)makePointerFromId(ptr);
tempProtoFunc->lineDefined = restoreSint32(); tempProtoFunc->lineDefined = restoreSint32();
tempProtoFunc->nconsts = restoreSint32(); tempProtoFunc->nconsts = restoreSint32();
tempProtoFunc->consts = (TObject *)luaM_malloc(tempProtoFunc->nconsts * sizeof(TObject)); if (tempProtoFunc->nconsts > 0) {
tempProtoFunc->consts = (TObject *)luaM_malloc(tempProtoFunc->nconsts * sizeof(TObject));
} else {
tempProtoFunc->consts = NULL;
}
for (l = 0; l < tempProtoFunc->nconsts; l++) { for (l = 0; l < tempProtoFunc->nconsts; l++) {
restoreObjectValue(&tempProtoFunc->consts[l], restoreSint32, restoreUint32); restoreObjectValue(&tempProtoFunc->consts[l], restoreSint32, restoreUint32);
@ -389,7 +419,6 @@ void lua_Restore(RestoreStream restoreStream, RestoreSint32 restoreSint32, Resto
tempObj.ttype = LUA_T_STRING; tempObj.ttype = LUA_T_STRING;
recreateObj(&tempObj); recreateObj(&tempObj);
tempProtoFunc->fileName = (TaggedString *)tempObj.value.ts; tempProtoFunc->fileName = (TaggedString *)tempObj.value.ts;
for (i = 0; i < tempProtoFunc->nconsts; i++) { for (i = 0; i < tempProtoFunc->nconsts; i++) {
recreateObj(&tempProtoFunc->consts[i]); recreateObj(&tempProtoFunc->consts[i]);
} }
@ -454,22 +483,30 @@ void lua_Restore(RestoreStream restoreStream, RestoreSint32 restoreSint32, Resto
recreateObj(&errorim); recreateObj(&errorim);
IMtable_size = restoreSint32(); IMtable_size = restoreSint32();
IMtable = (IM *)luaM_malloc(IMtable_size * sizeof(IM)); if (IMtable_size > 0) {
for (i = 0; i < IMtable_size; i++) { IMtable = (IM *)luaM_malloc(IMtable_size * sizeof(IM));
IM *im = &IMtable[i]; for (i = 0; i < IMtable_size; i++) {
for (l = 0; l < IM_N; l++) { IM *im = &IMtable[i];
restoreObjectValue(&im->int_method[l], restoreSint32, restoreUint32); for (l = 0; l < IM_N; l++) {
recreateObj(&im->int_method[l]); restoreObjectValue(&im->int_method[l], restoreSint32, restoreUint32);
recreateObj(&im->int_method[l]);
}
} }
} else {
IMtable = NULL;
} }
last_tag = restoreSint32(); last_tag = restoreSint32();
refSize = restoreSint32(); refSize = restoreSint32();
refArray = (ref *)luaM_malloc(refSize * sizeof(ref)); if (refSize > 0) {
for (i = 0; i < refSize; i++) { refArray = (ref *)luaM_malloc(refSize * sizeof(ref));
restoreObjectValue(&refArray[i].o, restoreSint32, restoreUint32); for (i = 0; i < refSize; i++) {
recreateObj(&refArray[i].o); restoreObjectValue(&refArray[i].o, restoreSint32, restoreUint32);
refArray[i].status = (Status)restoreSint32(); recreateObj(&refArray[i].o);
refArray[i].status = (Status)restoreSint32();
}
} else {
refArray = NULL;
} }
GCthreshold = restoreSint32(); GCthreshold = restoreSint32();
@ -501,10 +538,18 @@ void lua_Restore(RestoreStream restoreStream, RestoreSint32 restoreSint32, Resto
} }
int32 countTasks = restoreSint32(); int32 countTasks = restoreSint32();
if (countTasks) { if (countTasks) {
lua_Task *task;
for (i = 0; i < countTasks; i++) { for (i = 0; i < countTasks; i++) {
lua_Task *task = state->task; if (i == 0) {
task = luaM_new(lua_Task); task = state->task = luaM_new(lua_Task);
lua_taskinit(task, NULL, 0, 0); lua_taskinit(task, NULL, 0, 0);
} else {
lua_Task *t = luaM_new(lua_Task);
lua_taskinit(t, NULL, 0, 0);
task->next = t;
task = t;
}
task->S = &state->stack; task->S = &state->stack;
TObject tempObj; TObject tempObj;
@ -527,7 +572,7 @@ void lua_Restore(RestoreStream restoreStream, RestoreSint32 restoreSint32, Resto
task->some_results = restoreSint32(); task->some_results = restoreSint32();
task->some_flag = restoreSint32(); task->some_flag = restoreSint32();
int32 pcOffset = restoreSint32(); int32 pcOffset = restoreSint32();
task->pc = state->task->tf->code + pcOffset; task->pc = task->tf->code + pcOffset;
task->aux = restoreSint32(); task->aux = restoreSint32();
task->consts = task->tf->consts; task->consts = task->tf->consts;
} }

View file

@ -14,6 +14,7 @@
#include "engines/grim/lua/lopcodes.h" #include "engines/grim/lua/lopcodes.h"
#include "engines/grim/lua/lstring.h" #include "engines/grim/lua/lstring.h"
#include "engines/grim/lua/lua.h" #include "engines/grim/lua/lua.h"
#include "engines/grim/actor.h"
namespace Grim { namespace Grim {
@ -241,6 +242,26 @@ void lua_Save(SaveStream saveStream, SaveSint32 saveSint32, SaveUint32 saveUint3
tempString->globalval.value.ts = (TaggedString *)makePointerFromId(ptr); tempString->globalval.value.ts = (TaggedString *)makePointerFromId(ptr);
} }
saveObjectValue((TObject *)&tempString->globalval, saveSint32, saveUint32); saveObjectValue((TObject *)&tempString->globalval, saveSint32, saveUint32);
if (tempString->globalval.value.ts) {
saveUint32(1);
Object *o = (Object *)tempString->globalval.value.ts;
if (Actor *a = dynamic_cast<Actor *>(o)) {
saveUint32(1);
saveUint32(g_grim->actorId(a));
} else if (TextObject *t = dynamic_cast<TextObject *>(o)) {
saveUint32(2);
saveUint32(g_grim->textObjectId(t));
} else if (ObjectState *s = dynamic_cast<ObjectState *>(o)) {
saveUint32(3);
saveUint32(g_grim->objectStateId(s));
} else {
saveUint32(4);
ObjectManager::saveObject(g_grim->_savedState, o);
}
} else {
saveUint32(0);
}
} }
} }
} }
@ -358,7 +379,7 @@ void lua_Save(SaveStream saveStream, SaveSint32 saveSint32, SaveUint32 saveUint3
int32 countStates = 0, currentState = 0; int32 countStates = 0, currentState = 0;
LState *state = lua_rootState; LState *state = lua_rootState;
while (state) { while (state) {
if (lua_rootState == state) if (lua_state == state)
currentState = countStates; currentState = countStates;
countStates++; countStates++;
state = state->next; state = state->next;

View file

@ -371,7 +371,7 @@ static void add_localvar (TaggedString *name)
} }
/* /*
** dotted variables <a.x> must be stored like regular indexed vars <a["x"]> ** dotted variables <a.x> must be stored like regular indexed vars <a["x"]>
*/ */
static vardesc var2store (vardesc var) static vardesc var2store (vardesc var)

View file

@ -9,6 +9,7 @@
#include "common/sys.h" #include "common/sys.h"
#include "common/str.h" #include "common/str.h"
#include "engines/grim/object.h"
#ifndef GRIM_LUA_H #ifndef GRIM_LUA_H
#define GRIM_LUA_H #define GRIM_LUA_H
@ -41,9 +42,11 @@ struct PointerId {
PointerId makeIdFromPointer(void *ptr); PointerId makeIdFromPointer(void *ptr);
void *makePointerFromId(PointerId ptr); void *makePointerFromId(PointerId ptr);
class LuaFile { class LuaFile : public Object {
GRIM_OBJECT(LuaFile)
public: public:
Common::String _name; Common::String _name;
Common::String _filename;
Common::SeekableReadStream *_in; Common::SeekableReadStream *_in;
Common::WriteStream *_out; Common::WriteStream *_out;
bool _stdin, _stdout, _stderr; bool _stdin, _stdout, _stderr;
@ -52,6 +55,9 @@ public:
LuaFile(); LuaFile();
~LuaFile(); ~LuaFile();
void saveState(SaveGame *state) const;
bool restoreState(SaveGame *state);
void close(); void close();
bool isOpen() const; bool isOpen() const;
uint32 read(void *buf, uint32 len); uint32 read(void *buf, uint32 len);
@ -190,23 +196,23 @@ lua_Object lua_setfallback(const char *event, lua_CFunction fallback);
/****************************************************************************** /******************************************************************************
* Copyright (c) 1994-1998 TeCGraf, PUC-Rio. All rights reserved. * Copyright (c) 1994-1998 TeCGraf, PUC-Rio. All rights reserved.
* *
* Permission is hereby granted, without written agreement and without license * Permission is hereby granted, without written agreement and without license
* or royalty fees, to use, copy, modify, and distribute this software and its * or royalty fees, to use, copy, modify, and distribute this software and its
* documentation for any purpose, including commercial applications, subject to * documentation for any purpose, including commercial applications, subject to
* the following conditions: * the following conditions:
* *
* - The above copyright notice and this permission notice shall appear in all * - The above copyright notice and this permission notice shall appear in all
* copies or substantial portions of this software. * copies or substantial portions of this software.
* *
* - The origin of this software must not be misrepresented; you must not * - The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software in a * claim that you wrote the original software. If you use this software in a
* product, an acknowledgment in the product documentation would be greatly * product, an acknowledgment in the product documentation would be greatly
* appreciated (but it is not required). * appreciated (but it is not required).
* *
* - Altered source versions must be plainly marked as such, and must not be * - Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software. * misrepresented as being the original software.
* *
* The authors specifically disclaim any warranties, including, but not limited * The authors specifically disclaim any warranties, including, but not limited
* to, the implied warranties of merchantability and fitness for a particular * to, the implied warranties of merchantability and fitness for a particular
* purpose. The software provided hereunder is on an "as is" basis, and the * purpose. The software provided hereunder is on an "as is" basis, and the
@ -215,7 +221,7 @@ lua_Object lua_setfallback(const char *event, lua_CFunction fallback);
* authors be held liable to any party for direct, indirect, special, * authors be held liable to any party for direct, indirect, special,
* incidental, or consequential damages arising out of the use of this software * incidental, or consequential damages arising out of the use of this software
* and its documentation. * and its documentation.
* *
* The Lua language and this implementation have been entirely designed and * The Lua language and this implementation have been entirely designed and
* written by Waldemar Celes Filho, Roberto Ierusalimschy and * written by Waldemar Celes Filho, Roberto Ierusalimschy and
* Luiz Henrique de Figueiredo at TeCGraf, PUC-Rio. * Luiz Henrique de Figueiredo at TeCGraf, PUC-Rio.

View file

@ -38,6 +38,9 @@
#include "engines/grim/lua/lauxlib.h" #include "engines/grim/lua/lauxlib.h"
#include "engines/grim/imuse/imuse.h" #include "engines/grim/imuse/imuse.h"
#include <iostream>
using namespace std;
namespace Grim { namespace Grim {
extern Imuse *g_imuse; extern Imuse *g_imuse;
@ -133,7 +136,7 @@ static void PrintWarning() {
static void FunctionName() { static void FunctionName() {
const char *name; const char *name;
char buf[256]; char buf[256];
const char *filename; const char *filename = 0;
int32 line; int32 line;
lua_Object param1 = lua_getparam(1); lua_Object param1 = lua_getparam(1);
@ -153,6 +156,7 @@ static void FunctionName() {
break; break;
default: default:
{ {
// cout<<(void*)filename<<endl;
if (line == 0) if (line == 0)
sprintf(buf, "main of %.100s", filename); sprintf(buf, "main of %.100s", filename);
else if (line < 0) else if (line < 0)
@ -724,13 +728,13 @@ static void GetActorYawToPoint() {
if (lua_istable(pointObj)) { if (lua_istable(pointObj)) {
lua_pushobject(pointObj); lua_pushobject(pointObj);
lua_pushstring("x"); lua_pushstring("x");
xObj = lua_gettable(); xObj = lua_gettable();
lua_pushobject(pointObj); lua_pushobject(pointObj);
lua_pushstring("y"); lua_pushstring("y");
yObj = lua_gettable(); yObj = lua_gettable();
lua_pushobject(pointObj); lua_pushobject(pointObj);
lua_pushstring("z"); lua_pushstring("z");
zObj = lua_gettable(); zObj = lua_gettable();
} else { } else {
xObj = pointObj; xObj = pointObj;
yObj = lua_getparam(3); yObj = lua_getparam(3);
@ -1017,7 +1021,6 @@ static void SetActorColormap() {
Actor *actor = static_cast<Actor *>(lua_getuserdata(actorObj)); Actor *actor = static_cast<Actor *>(lua_getuserdata(actorObj));
if (lua_isstring(nameObj)) { if (lua_isstring(nameObj)) {
const char *name = lua_getstring(nameObj); const char *name = lua_getstring(nameObj);
g_resourceloader->loadColormap(name);
actor->setColormap(name); actor->setColormap(name);
} else if (lua_isnil(nameObj)) { } else if (lua_isnil(nameObj)) {
error("SetActorColormap: implement remove cmap"); error("SetActorColormap: implement remove cmap");
@ -1360,7 +1363,7 @@ static void ActorLookAt() {
fZ = 0.0f; fZ = 0.0f;
Graphics::Vector3d vector; Graphics::Vector3d vector;
vector.set(fX, fY, fZ); vector.set(fX, fY, fZ); //FIXME: This values are wrong when looking at something manny has in his hand
actor->setLookAtVector(vector); actor->setLookAtVector(vector);
} else if (lua_isuserdata(xObj) && lua_tag(xObj) == MKID_BE('ACTR')) { // look at another actor } else if (lua_isuserdata(xObj) && lua_tag(xObj) == MKID_BE('ACTR')) { // look at another actor
Actor *lookedAct = static_cast<Actor *>(lua_getuserdata(xObj)); Actor *lookedAct = static_cast<Actor *>(lua_getuserdata(xObj));
@ -1408,7 +1411,7 @@ static void TurnActorTo() {
} }
// TODO turning stuff below is not complete // TODO turning stuff below is not complete
// Find the vector pointing from the actor to the desired location // Find the vector pointing from the actor to the desired location
Graphics::Vector3d turnToVector(x, y, z); Graphics::Vector3d turnToVector(x, y, z);
Graphics::Vector3d lookVector = turnToVector - actor->pos(); Graphics::Vector3d lookVector = turnToVector - actor->pos();
@ -1447,7 +1450,7 @@ static void PointActorAt() {
} }
// TODO turning stuff below is not complete // TODO turning stuff below is not complete
// Find the vector pointing from the actor to the desired location // Find the vector pointing from the actor to the desired location
Graphics::Vector3d turnToVector(x, y, z); Graphics::Vector3d turnToVector(x, y, z);
Graphics::Vector3d lookVector = turnToVector - actor->pos(); Graphics::Vector3d lookVector = turnToVector - actor->pos();
@ -1715,12 +1718,13 @@ static void GetVisibleThings() {
// TODO verify code below // TODO verify code below
for (GrimEngine::ActorListType::const_iterator i = g_grim->actorsBegin(); i != g_grim->actorsEnd(); ++i) { for (GrimEngine::ActorListType::const_iterator i = g_grim->actorsBegin(); i != g_grim->actorsEnd(); ++i) {
if (!(*i)->inSet(g_grim->sceneName())) Actor *a = i->_value;
if (!i->_value->inSet(g_grim->sceneName()))
continue; continue;
// Consider the active actor visible // Consider the active actor visible
if (actor == (*i) || actor->angleTo(*(*i)) < 90) { if (actor == a || actor->angleTo(*a) < 90) {
lua_pushobject(result); lua_pushobject(result);
lua_pushusertag(*i, MKID_BE('ACTR')); lua_pushusertag(a, MKID_BE('ACTR'));
lua_pushnumber(1); lua_pushnumber(1);
lua_settable(); lua_settable();
} }
@ -2612,6 +2616,7 @@ static void FileFindDispose() {
if (g_filesiter) if (g_filesiter)
g_filesiter->begin(); g_filesiter->begin();
g_listfiles.clear(); g_listfiles.clear();
g_filesiter = NULL;
} }
static void luaFileFindNext() { static void luaFileFindNext() {
@ -2630,7 +2635,7 @@ static void luaFileFindFirst() {
lua_pushnil(); lua_pushnil();
return; return;
} }
FileFindDispose(); FileFindDispose();
const char *extension = lua_getstring(extObj); const char *extension = lua_getstring(extObj);
@ -2716,7 +2721,7 @@ void GetControlState() {
static void killBitmapPrimitives(Bitmap *bitmap) { static void killBitmapPrimitives(Bitmap *bitmap) {
for (GrimEngine::PrimitiveListType::const_iterator i = g_grim->primitivesBegin(); i != g_grim->primitivesEnd(); ++i) { for (GrimEngine::PrimitiveListType::const_iterator i = g_grim->primitivesBegin(); i != g_grim->primitivesEnd(); ++i) {
PrimitiveObject *p = *i; PrimitiveObject *p = i->_value;
if (p->isBitmap() && p->getBitmapHandle() == bitmap) { if (p->isBitmap() && p->getBitmapHandle() == bitmap) {
g_grim->killPrimitiveObject(p); g_grim->killPrimitiveObject(p);
break; break;
@ -2731,7 +2736,9 @@ static void GetImage() {
return; return;
} }
const char *bitmapName = lua_getstring(nameObj); const char *bitmapName = lua_getstring(nameObj);
Bitmap *image = g_resourceloader->loadBitmap(bitmapName); BitmapPtr ptr = g_resourceloader->getBitmap(bitmapName).object();
Bitmap *image = ptr.object();
image->ref();
lua_pushusertag(image, MKID_BE('VBUF')); lua_pushusertag(image, MKID_BE('VBUF'));
} }
@ -2740,6 +2747,7 @@ static void FreeImage() {
if (!lua_isuserdata(param) || lua_tag(param) != MKID_BE('VBUF')) if (!lua_isuserdata(param) || lua_tag(param) != MKID_BE('VBUF'))
return; return;
Bitmap *bitmap = static_cast<Bitmap *>(lua_getuserdata(param)); Bitmap *bitmap = static_cast<Bitmap *>(lua_getuserdata(param));
bitmap->deref();
killBitmapPrimitives(bitmap); killBitmapPrimitives(bitmap);
} }
@ -2988,11 +2996,11 @@ static void GetTextObjectDimensions() {
static void ExpireText() { static void ExpireText() {
// Expire all the text objects // Expire all the text objects
for (GrimEngine::TextListType::const_iterator i = g_grim->textsBegin(); i != g_grim->textsEnd(); ++i) for (GrimEngine::TextListType::const_iterator i = g_grim->textsBegin(); i != g_grim->textsEnd(); ++i)
(*i)->setDisabled(true); i->_value->setDisabled(true);
// Cleanup actor references to deleted text objects // Cleanup actor references to deleted text objects
for (GrimEngine::ActorListType::const_iterator i = g_grim->actorsBegin(); i != g_grim->actorsEnd(); ++i) for (GrimEngine::ActorListType::const_iterator i = g_grim->actorsBegin(); i != g_grim->actorsEnd(); ++i)
(*i)->lineCleanup(); i->_value->lineCleanup();
} }
static void GetTextCharPosition() { static void GetTextCharPosition() {
@ -3233,7 +3241,7 @@ static void ChangePrimitive() {
psearch = static_cast<PrimitiveObject *>(lua_getuserdata(param1)); psearch = static_cast<PrimitiveObject *>(lua_getuserdata(param1));
for (GrimEngine::PrimitiveListType::const_iterator i = g_grim->primitivesBegin(); i != g_grim->primitivesEnd(); ++i) { for (GrimEngine::PrimitiveListType::const_iterator i = g_grim->primitivesBegin(); i != g_grim->primitivesEnd(); ++i) {
PrimitiveObject *p = *i; PrimitiveObject *p = i->_value;
if (p->getP1().x == psearch->getP1().x && p->getP2().x == psearch->getP2().x if (p->getP1().x == psearch->getP1().x && p->getP2().x == psearch->getP2().x
&& p->getP1().y == psearch->getP1().y && p->getP2().y == psearch->getP2().y) { && p->getP1().y == psearch->getP1().y && p->getP2().y == psearch->getP2().y) {
pmodify = p; pmodify = p;
@ -3441,6 +3449,7 @@ static void NewObjectState() {
bool transparency = getbool(5); bool transparency = getbool(5);
ObjectState *state = new ObjectState(setupID, pos, bitmap, zbitmap, transparency); ObjectState *state = new ObjectState(setupID, pos, bitmap, zbitmap, transparency);
g_grim->registerObjectState(state);
g_grim->currScene()->addObjectState(state); g_grim->currScene()->addObjectState(state);
lua_pushusertag(state, MKID_BE('STAT')); lua_pushusertag(state, MKID_BE('STAT'));
} }
@ -3451,6 +3460,7 @@ static void FreeObjectState() {
return; return;
ObjectState *state = static_cast<ObjectState *>(lua_getuserdata(param)); ObjectState *state = static_cast<ObjectState *>(lua_getuserdata(param));
g_grim->currScene()->deleteObjectState(state); g_grim->currScene()->deleteObjectState(state);
cout<<"free "<<state<<endl;
} }
static void SendObjectToBack() { static void SendObjectToBack() {
@ -3636,10 +3646,11 @@ static void LockFont() {
lua_Object param1 = lua_getparam(1); lua_Object param1 = lua_getparam(1);
if (lua_isstring(param1)) { if (lua_isstring(param1)) {
const char *fontName = lua_getstring(param1); const char *fontName = lua_getstring(param1);
Font *result = g_resourceloader->loadFont(fontName); FontPtr ptr = g_resourceloader->getFont(fontName);
Font *result = ptr.object();
result->ref();
if (result) { if (result) {
lua_pushusertag(result, MKID_BE('FONT')); lua_pushusertag(result, MKID_BE('FONT'));
g_grim->registerFont(result);
return; return;
} }
} }

View file

@ -31,8 +31,8 @@
namespace Grim { namespace Grim {
Material::Material(const char *filename, const char *data, int len, const CMap *cmap) : Material::Material(const char *filename, const char *data, int len, CMap *cmap) :
_fname(filename), _cmap(cmap) { Object(), _fname(filename), _cmap(cmap) {
if (len < 4 || memcmp(data, "MAT ", 4) != 0) if (len < 4 || memcmp(data, "MAT ", 4) != 0)
error("invalid magic loading texture"); error("invalid magic loading texture");
@ -59,6 +59,8 @@ void Material::select() const {
} }
Material::~Material() { Material::~Material() {
if (g_resourceloader)
g_resourceloader->uncacheMaterial(this);
if (_width == 0 || _height == 0) if (_width == 0 || _height == 0)
return; return;
g_driver->destroyMaterial(this); g_driver->destroyMaterial(this);

View file

@ -27,14 +27,17 @@
#define GRIM_MATERIAL_H #define GRIM_MATERIAL_H
#include "engines/grim/resource.h" #include "engines/grim/resource.h"
#include "engines/grim/object.h"
#include "engines/grim/colormap.h"
namespace Grim { namespace Grim {
class Material { class Material : public Object {
GRIM_OBJECT(Material)
public: public:
Material() {} Material() { _width = 0; }
// Load a texture from the given data. // Load a texture from the given data.
Material(const char *filename, const char *data, int len, const CMap *cmap); Material(const char *filename, const char *data, int len, CMap *cmap);
// Load this texture into the GL context // Load this texture into the GL context
void select() const; void select() const;
@ -44,12 +47,13 @@ public:
int numImages() const { return _numImages; } int numImages() const { return _numImages; }
int currentImage() const { return _currImage; } int currentImage() const { return _currImage; }
const char *filename() { return _fname.c_str(); }
~Material(); ~Material();
Common::String _fname; Common::String _fname;
const CMap *_cmap; const CMapPtr _cmap;
int _numImages, _currImage; int _numImages, _currImage;
int _width, _height; int _width, _height;
void *_textures; void *_textures;

View file

@ -34,9 +34,10 @@
namespace Grim { namespace Grim {
Model::Model(const char *filename, const char *data, int len, const CMap *cmap) : Model::Model(const char *filename, const char *data, int len, CMap *cmap) :
_numMaterials(0), _numGeosets(0) { Object(), _numMaterials(0), _numGeosets(0), _cmap(cmap) {
_fname = filename; _fname = filename;
_headNode = NULL;
if (len >= 4 && READ_BE_UINT32(data) == MKID_BE('LDOM')) if (len >= 4 && READ_BE_UINT32(data) == MKID_BE('LDOM'))
loadBinary(data, cmap); loadBinary(data, cmap);
@ -46,35 +47,50 @@ Model::Model(const char *filename, const char *data, int len, const CMap *cmap)
} }
} }
void Model::reload(const CMap *cmap) { void Model::reload(CMap *cmap) {
// Load the new colormap // Load the new colormap
for (int i = 0; i < _numMaterials; i++) for (int i = 0; i < _numMaterials; i++) {
_materials[i] = g_resourceloader->loadMaterial(_materialNames[i], cmap); _materials[i] = g_resourceloader->getMaterial(_materialNames[i], cmap);
}
Material **materials = new Material*[_numMaterials];
for (int j = 0; j < _numMaterials; ++j) {
materials[j] = _materials[j];
}
for (int i = 0; i < _numGeosets; i++) for (int i = 0; i < _numGeosets; i++)
_geosets[i].changeMaterials(_materials); _geosets[i].changeMaterials(materials);
delete[] materials;
} }
void Model::loadBinary(const char *&data, const CMap *cmap) { void Model::loadBinary(const char *&data, CMap *cmap) {
_numMaterials = READ_LE_UINT32(data + 4); _numMaterials = READ_LE_UINT32(data + 4);
data += 8; data += 8;
_materials = new Material*[_numMaterials]; _materials = new MaterialPtr[_numMaterials];
_materialNames = new char[_numMaterials][32]; _materialNames = new char[_numMaterials][32];
for (int i = 0; i < _numMaterials; i++) { for (int i = 0; i < _numMaterials; i++) {
strcpy(_materialNames[i], data); strcpy(_materialNames[i], data);
_materials[i] = g_resourceloader->loadMaterial(_materialNames[i], cmap); _materials[i] = g_resourceloader->getMaterial(_materialNames[i], cmap);
data += 32; data += 32;
} }
data += 32; // skip name data += 32; // skip name
_numGeosets = READ_LE_UINT32(data + 4); _numGeosets = READ_LE_UINT32(data + 4);
data += 8; data += 8;
_geosets = new Geoset[_numGeosets]; _geosets = new Geoset[_numGeosets];
Material **materials = new Material*[_numMaterials];
for (int j = 0; j < _numMaterials; ++j) {
materials[j] = _materials[j];
}
for (int i = 0; i < _numGeosets; i++) for (int i = 0; i < _numGeosets; i++)
_geosets[i].loadBinary(data, _materials); _geosets[i].loadBinary(data, materials);
delete[] materials;
_numHierNodes = READ_LE_UINT32(data + 4); _numHierNodes = READ_LE_UINT32(data + 4);
data += 8; data += 8;
_rootHierNode = new HierNode[_numHierNodes]; _rootHierNode = new HierNode[_numHierNodes];
for (int i = 0; i < _numHierNodes; i++) for (int i = 0; i < _numHierNodes; i++) {
_rootHierNode[i].loadBinary(data, _rootHierNode, &_geosets[0]); _rootHierNode[i].loadBinary(data, _rootHierNode, &_geosets[0]);
if (strcmp(_rootHierNode[i]._name, "head") == 0) {
_headNode = _rootHierNode + i;
}
}
_radius = get_float(data); _radius = get_float(data);
_insertOffset = Graphics::get_vector3d(data + 40); _insertOffset = Graphics::get_vector3d(data + 40);
} }
@ -84,6 +100,7 @@ Model::~Model() {
delete[] _materialNames; delete[] _materialNames;
delete[] _geosets; delete[] _geosets;
delete[] _rootHierNode; delete[] _rootHierNode;
g_resourceloader->uncacheModel(this);
} }
void Model::Geoset::loadBinary(const char *&data, Material *materials[]) { void Model::Geoset::loadBinary(const char *&data, Material *materials[]) {
@ -144,6 +161,7 @@ Model::Mesh::~Mesh() {
delete[] _vertNormals; delete[] _vertNormals;
delete[] _textureVerts; delete[] _textureVerts;
delete[] _faces; delete[] _faces;
delete[] _materialid;
} }
void Model::Mesh::update() { void Model::Mesh::update() {
@ -262,20 +280,20 @@ Model::HierNode *Model::copyHierarchy() {
return result; return result;
} }
void Model::loadText(TextSplitter *ts, const CMap *cmap) { void Model::loadText(TextSplitter *ts, CMap *cmap) {
ts->expectString("section: header"); ts->expectString("section: header");
int major, minor; int major, minor;
ts->scanString("3do %d.%d", 2, &major, &minor); ts->scanString("3do %d.%d", 2, &major, &minor);
ts->expectString("section: modelresource"); ts->expectString("section: modelresource");
ts->scanString("materials %d", 1, &_numMaterials); ts->scanString("materials %d", 1, &_numMaterials);
_materials = new Material*[_numMaterials]; _materials = new MaterialPtr[_numMaterials];
_materialNames = new char[_numMaterials][32]; _materialNames = new char[_numMaterials][32];
for (int i = 0; i < _numMaterials; i++) { for (int i = 0; i < _numMaterials; i++) {
char materialName[32]; char materialName[32];
int num; int num;
ts->scanString("%d: %32s", 2, &num, materialName); ts->scanString("%d: %32s", 2, &num, materialName);
_materials[num] = g_resourceloader->loadMaterial(materialName, cmap); _materials[num] = g_resourceloader->getMaterial(materialName, cmap);
strcpy(_materialNames[num], materialName); strcpy(_materialNames[num], materialName);
} }
@ -284,11 +302,16 @@ void Model::loadText(TextSplitter *ts, const CMap *cmap) {
ts->scanString("insert offset %f %f %f", 3, &_insertOffset.x(), &_insertOffset.y(), &_insertOffset.z()); ts->scanString("insert offset %f %f %f", 3, &_insertOffset.x(), &_insertOffset.y(), &_insertOffset.z());
ts->scanString("geosets %d", 1, &_numGeosets); ts->scanString("geosets %d", 1, &_numGeosets);
_geosets = new Geoset[_numGeosets]; _geosets = new Geoset[_numGeosets];
Material **materials = new Material*[_numMaterials];
for (int j = 0; j < _numMaterials; ++j) {
materials[j] = _materials[j];
}
for (int i = 0; i < _numGeosets; i++) { for (int i = 0; i < _numGeosets; i++) {
int num; int num;
ts->scanString("geoset %d", 1, &num); ts->scanString("geoset %d", 1, &num);
_geosets[num].loadText(ts, _materials); _geosets[num].loadText(ts, materials);
} }
delete[] materials;
ts->expectString("section: hierarchydef"); ts->expectString("section: hierarchydef");
ts->scanString("hierarchy nodes %d", 1, &_numHierNodes); ts->scanString("hierarchy nodes %d", 1, &_numHierNodes);
@ -358,7 +381,7 @@ void Model::Mesh::changeMaterials(Material *materials[]) {
_faces[i].changeMaterial(materials[_materialid[i]]); _faces[i].changeMaterial(materials[_materialid[i]]);
} }
void Model::Mesh::loadText(TextSplitter *ts, Material *materials[]) { void Model::Mesh::loadText(TextSplitter *ts, Material* materials[]) {
ts->scanString("name %32s", 1, _name); ts->scanString("name %32s", 1, _name);
ts->scanString("radius %f", 1, &_radius); ts->scanString("radius %f", 1, &_radius);

View file

@ -27,24 +27,27 @@
#define GRIM_MODEL_H #define GRIM_MODEL_H
#include "engines/grim/resource.h" #include "engines/grim/resource.h"
#include "engines/grim/object.h"
#include "graphics/matrix4.h" #include "graphics/matrix4.h"
namespace Grim { namespace Grim {
class TextSplitter; class TextSplitter;
class Model { class Model : public Object {
GRIM_OBJECT(Model)
public: public:
// Construct a 3D model from the given data. // Construct a 3D model from the given data.
Model(const char *filename, const char *data, int len, const CMap *cmap); Model(const char *filename, const char *data, int len, CMap *cmap);
void loadBinary(const char *&data, const CMap *cmap); void loadBinary(const char *&data, CMap *cmap);
void loadText(TextSplitter *ts, const CMap *cmap); void loadText(TextSplitter *ts, CMap *cmap);
void reload(const CMap *cmap); void reload(CMap *cmap);
void draw() const; void draw() const;
~Model(); ~Model();
Common::String _fname; Common::String _fname;
CMapPtr _cmap;
struct Geoset; struct Geoset;
struct Mesh; struct Mesh;
@ -132,13 +135,14 @@ public:
int _numMaterials; int _numMaterials;
char (*_materialNames)[32]; char (*_materialNames)[32];
Material **_materials; MaterialPtr *_materials;
Graphics::Vector3d _insertOffset; Graphics::Vector3d _insertOffset;
int _numGeosets; int _numGeosets;
Geoset *_geosets; Geoset *_geosets;
float _radius; float _radius;
int _numHierNodes; int _numHierNodes;
HierNode *_rootHierNode; HierNode *_rootHierNode;
HierNode *_headNode;
}; };
} // end of namespace Grim } // end of namespace Grim

View file

@ -59,6 +59,7 @@ MODULE_OBJS := \
scene.o \ scene.o \
textobject.o \ textobject.o \
textsplit.o \ textsplit.o \
object.o \
walkplane.o walkplane.o
# This module can be built as a plugin # This module can be built as a plugin

96
engines/grim/object.cpp Normal file
View file

@ -0,0 +1,96 @@
#include "object.h"
#include "engines/grim/savegame.h"
#include "engines/grim/lua/lobject.h"
namespace Grim {
typedef Object *(*CreatorFunc)();
Common::HashMap<Common::String, CreatorFunc> ObjectManager::_creators;
Object::Object() : _refCount(0) {
}
Object::~Object() {
luaO_resetObject(this); //after climbing the ties rope an ObjectState gets deleted but not removed
//from the lua's userdata list, resulting in a dangling pointer
//that breaks the saving. We need to reset to NULL the pointer manually.
for (Common::List<Pointer *>::iterator i = _pointers.begin(); i != _pointers.end(); ++i) {
(*i)->resetPointer();
}
}
void Object::save(SaveGame *state) const {
state->writeLEUint32(_refCount);
saveState(state);
}
bool Object::restore(SaveGame *state) {
_refCount = state->readLEUint32();
return restoreState(state);
}
void Object::saveState(SaveGame */*state*/) const {
}
bool Object::restoreState(SaveGame */*state*/) {
return false;
}
void Object::ref() {
++_refCount;
}
void Object::deref() {
if (_refCount > 0) {
--_refCount;
}
if (_refCount == 0) {
_refCount = -1;
delete this;
}
}
void ObjectManager::saveObject(SaveGame *state, Object *object) {
const char *str = object->typeName();
int32 len = strlen(str);
state->writeLEUint32(len);
state->write(str, len);
object->save(state);
}
Object *ObjectManager::restoreObject(SaveGame *state) {
int32 len = state->readLEUint32();
char *str = new char[len + 1];
state->read(str, len);
str[len] = '\0';
Object *o = newObject(str);
delete[] str;
o->restore(state);
return o;
}
Object *ObjectManager::newObject(const char *typeName) {
Common::String type = typeName;
if (_creators.contains(type)) {
CreatorFunc func = _creators.getVal(type);
Object *o = (func)();
return o;
} else {
warning("Type name \"%s\" not registered", typeName);
}
return 0;
}
}

212
engines/grim/object.h Normal file
View file

@ -0,0 +1,212 @@
/* Residual - A 3D game interpreter
*
* Residual is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the AUTHORS
* file distributed with this source distribution.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*
* $URL$
* $Id$
*
*/
#ifndef GRIM_OBJECT_H
#define GRIM_OBJECT_H
#include "common/str.h"
#include "common/hashmap.h"
#include "common/hash-str.h"
#include "common/func.h"
#include "common/list.h"
#include <iostream>
using namespace std;
namespace Grim {
class SaveGame;
class Pointer;
class Object {
public:
Object();
virtual ~Object();
virtual const char *typeName() const { return ""; }
void save(SaveGame *state) const;
bool restore(SaveGame *state);
void ref();
void deref();
protected:
virtual void saveState(SaveGame *state) const;
virtual bool restoreState(SaveGame *state);
private:
int _refCount;
Common::List<Pointer *> _pointers;
friend class Pointer;
};
class Pointer {
protected:
virtual ~Pointer() {}
void addPointer(Object *obj) {
obj->_pointers.push_back(this);
}
void rmPointer(Object *obj) {
obj->_pointers.remove(this);
}
virtual void resetPointer() {}
friend class Object;
};
template<class T> class ObjectPtr : public Pointer {
public:
ObjectPtr() :
_obj(NULL) {
}
ObjectPtr(T *obj) :
_obj(obj) {
if (obj) {
_obj->ref();
addPointer(obj);
}
}
ObjectPtr(const ObjectPtr<T> &ptr) {
_obj = NULL;
*this = ptr;
}
~ObjectPtr() {
if (_obj) {
rmPointer(_obj);
_obj->deref();
}
}
ObjectPtr &operator=(T *obj) {
if (obj != _obj) {
if (_obj) {
rmPointer(_obj);
_obj->deref();
_obj = NULL;
}
if (obj) {
_obj = obj;
_obj->ref();
addPointer(obj);
}
}
return *this;
}
ObjectPtr &operator=(const ObjectPtr<T> &ptr) {
if (_obj != ptr._obj) {
if (_obj) {
rmPointer(_obj);
_obj->deref();
_obj = NULL;
}
if (ptr._obj) {
_obj = ptr._obj;
_obj->ref();
addPointer(_obj);
}
}
return *this;
}
bool operator==(const ObjectPtr &ptr) const {
return (_obj == ptr._obj);
}
bool operator==(Object *obj) const {
return (_obj == obj);
}
operator bool() const {
return (_obj);
}
bool operator!() const {
return (!_obj);
}
T *object() const {
return _obj;
}
T *operator->() const {
return _obj;
}
T &operator*() const {
return *_obj;
}
operator T*() const {
return _obj;
}
protected:
void resetPointer() {
_obj = NULL;
}
private:
T *_obj;
};
class ObjectManager {
public:
static void saveObject(SaveGame *state, Object *object);
static Object *restoreObject(SaveGame *state);
static Object *newObject(const char *typeName);
template<class T> static bool registerType() {
T obj;
Common::String type = obj.typeName();
if (_creators.contains(type)) {
warning("Type name %s already registered", type.c_str());
return false;
}
_creators.setVal(type, &createObj<T>);
return true;
}
private:
template<class T> static Object *createObj() {
return new T();
}
typedef Object *(*CreatorFunc)();
static Common::HashMap<Common::String, CreatorFunc> _creators;
};
} // end of namespace Grim
#define GRIM_OBJECT(class) \
public: \
const char *typeName() const { \
return #class; \
}
#endif

View file

@ -26,37 +26,80 @@
#include "engines/grim/objectstate.h" #include "engines/grim/objectstate.h"
#include "engines/grim/savegame.h" #include "engines/grim/savegame.h"
#include "engines/grim/lua.h" #include "engines/grim/lua.h"
#include "engines/grim/grim.h"
namespace Grim { namespace Grim {
int ObjectState::s_id = 0;
ObjectState::ObjectState(int setup, ObjectState::Position position, const char *bitmap, const char *zbitmap, bool transparency) : ObjectState::ObjectState(int setup, ObjectState::Position position, const char *bitmap, const char *zbitmap, bool transparency) :
_setupID(setup), _pos(position), _visibility(false) { Object(), _setupID(setup), _pos(position), _visibility(false) {
_bitmap = g_resourceloader->loadBitmap(bitmap); _bitmap = g_resourceloader->getBitmap(bitmap);
if (zbitmap) if (zbitmap) {
_zbitmap = g_resourceloader->loadBitmap(zbitmap); _zbitmap = g_resourceloader->getBitmap(zbitmap);
else } else
_zbitmap = NULL; _zbitmap = NULL;
++s_id;
_id = s_id;
}
ObjectState::ObjectState() :
Object(), _bitmap(NULL), _zbitmap(NULL) {
} }
ObjectState::~ObjectState() { ObjectState::~ObjectState() {
g_grim->killObjectState(this);
// g_resourceloader->uncache(_bitmap->getFilename()); // g_resourceloader->uncache(_bitmap->getFilename());
// if (_zbitmap) // if (_zbitmap)
// g_resourceloader->uncache(_zbitmap->getFilename()); // g_resourceloader->uncache(_zbitmap->getFilename());
} }
void ObjectState::saveState(SaveGame *savedState) { void ObjectState::saveState(SaveGame *savedState) const {
PointerId ptr;
savedState->writeLESint32(_visibility); savedState->writeLESint32(_visibility);
savedState->writeLEUint32(_setupID); savedState->writeLEUint32(_setupID);
savedState->writeLEUint32(_pos); savedState->writeLEUint32(_pos);
ptr = makeIdFromPointer(_bitmap); //_bitmap
savedState->writeLEUint32(ptr.low); if (_bitmap) {
savedState->writeLEUint32(ptr.hi); savedState->writeLEUint32(1);
ptr = makeIdFromPointer(_zbitmap); savedState->writeCharString(_bitmap->filename());
savedState->writeLEUint32(ptr.low); } else {
savedState->writeLEUint32(ptr.hi); savedState->writeLEUint32(0);
}
//_zbitmap
if (_zbitmap) {
savedState->writeLEUint32(1);
savedState->writeCharString(_zbitmap->filename());
} else {
savedState->writeLEUint32(0);
}
}
bool ObjectState::restoreState(SaveGame *savedState) {
_visibility = savedState->readLEUint32();
_setupID = savedState->readLEUint32();
_pos = (Position) savedState->readLEUint32();
if (savedState->readLEUint32()) {
const char *name = savedState->readCharString();
_bitmap = g_resourceloader->getBitmap(name);
delete[] name;
} else {
_bitmap = 0;
}
if (savedState->readLEUint32()) {
const char *name = savedState->readCharString();
_zbitmap = g_resourceloader->getBitmap(name);
delete[] name;
} else {
_zbitmap = 0;
}
return true;
} }
} // end of namespace Grim } // end of namespace Grim

View file

@ -27,12 +27,14 @@
#define GRIM_OSTATE_H #define GRIM_OSTATE_H
#include "engines/grim/bitmap.h" #include "engines/grim/bitmap.h"
#include "engines/grim/object.h"
namespace Grim { namespace Grim {
class SaveGame; class SaveGame;
class ObjectState { class ObjectState : public Object {
GRIM_OBJECT(ObjectState)
public: public:
enum Position { enum Position {
OBJSTATE_BACKGROUND = 0, OBJSTATE_BACKGROUND = 0,
@ -42,9 +44,11 @@ public:
}; };
ObjectState(int setupID, ObjectState::Position pos, const char *bitmap, const char *zbitmap, bool visible); ObjectState(int setupID, ObjectState::Position pos, const char *bitmap, const char *zbitmap, bool visible);
ObjectState();
~ObjectState(); ~ObjectState();
void saveState(SaveGame *savedState); void saveState(SaveGame *savedState) const;
bool restoreState(SaveGame *savedState);
int setupID() const { return _setupID; } int setupID() const { return _setupID; }
Position pos() const { return _pos; } Position pos() const { return _pos; }
@ -78,7 +82,12 @@ private:
bool _visibility; bool _visibility;
int _setupID; int _setupID;
Position _pos; Position _pos;
Bitmap *_bitmap, *_zbitmap; BitmapPtr _bitmap, _zbitmap;
int _id;
static int s_id;
friend class GrimEngine;
}; };
} // end of namespace Grim } // end of namespace Grim

View file

@ -30,29 +30,32 @@
namespace Grim { namespace Grim {
PrimitiveObject::PrimitiveObject() { int PrimitiveObject::s_id = 0;
memset(&_color, 0, sizeof(Color));
PrimitiveObject::PrimitiveObject() :
Object() {
// memset(&_color, 0, sizeof(Color));
_filled = false; _filled = false;
_type = 0; _type = 0;
_bitmap = NULL; _bitmap = NULL;
++s_id;
_id = s_id;
} }
PrimitiveObject::~PrimitiveObject() { PrimitiveObject::~PrimitiveObject() {
if (_type == 2) if (_bitmap && _type == 2)
g_driver->destroyBitmap(_bitmap); g_driver->destroyBitmap(_bitmap.object());
} }
void PrimitiveObject::saveState(SaveGame *savedState) { void PrimitiveObject::saveState(SaveGame *savedState) const {
PointerId ptr;
savedState->writeLESint32(_type); savedState->writeLESint32(_type);
savedState->writeLEUint32(_color.red());
savedState->writeLEUint32(_color.green()); savedState->writeColor(_color);
savedState->writeLEUint32(_color.blue());
savedState->writeLEUint32(_filled); savedState->writeLEUint32(_filled);
ptr = makeIdFromPointer(_bitmap);
savedState->writeLEUint32(ptr.low); savedState->writeCharString(_bitmap->filename());
savedState->writeLEUint32(ptr.hi);
savedState->writeLEUint32(_p1.x); savedState->writeLEUint32(_p1.x);
savedState->writeLEUint32(_p1.y); savedState->writeLEUint32(_p1.y);
savedState->writeLEUint32(_p2.x); savedState->writeLEUint32(_p2.x);
@ -63,6 +66,29 @@ void PrimitiveObject::saveState(SaveGame *savedState) {
savedState->writeLEUint32(_p4.y); savedState->writeLEUint32(_p4.y);
} }
bool PrimitiveObject::restoreState(SaveGame *savedState) {
_type = savedState->readLESint32();
_color = savedState->readColor();
_filled = savedState->readLEUint32();
const char *name = savedState->readCharString();
_bitmap = g_resourceloader->getBitmap(name);
delete[] name;
_p1.x = savedState->readLEUint32();
_p1.y = savedState->readLEUint32();
_p2.x = savedState->readLEUint32();
_p2.y = savedState->readLEUint32();
_p3.x = savedState->readLEUint32();
_p3.y = savedState->readLEUint32();
_p4.x = savedState->readLEUint32();
_p4.y = savedState->readLEUint32();
return true;
}
void PrimitiveObject::createRectangle(Common::Point p1, Common::Point p2, Color color, bool filled) { void PrimitiveObject::createRectangle(Common::Point p1, Common::Point p2, Color color, bool filled) {
_type = RECTANGLE; _type = RECTANGLE;
_p1 = p1; _p1 = p1;
@ -77,7 +103,7 @@ void PrimitiveObject::createBitmap(Bitmap *bitmap, Common::Point p, bool /*trans
_bitmap->setX(p.x); _bitmap->setX(p.x);
_bitmap->setY(p.y); _bitmap->setY(p.y);
// transparent: what to do ? // transparent: what to do ?
g_driver->createBitmap(_bitmap); g_driver->createBitmap(bitmap);
} }
void PrimitiveObject::createLine(Common::Point p1, Common::Point p2, Color color) { void PrimitiveObject::createLine(Common::Point p1, Common::Point p2, Color color) {
@ -102,7 +128,7 @@ void PrimitiveObject::draw() {
if (_type == RECTANGLE) if (_type == RECTANGLE)
g_driver->drawRectangle(this); g_driver->drawRectangle(this);
else if (_type == BITMAP) else if (_type == BITMAP)
g_driver->drawBitmap(_bitmap); g_driver->drawBitmap(_bitmap.object());
else if (_type == LINE) else if (_type == LINE)
g_driver->drawLine(this); g_driver->drawLine(this);
else if (_type == POLYGON) else if (_type == POLYGON)

View file

@ -34,7 +34,8 @@ namespace Grim {
class SaveGame; class SaveGame;
class PrimitiveObject { class PrimitiveObject : public Object {
GRIM_OBJECT(PrimitiveObject)
public: public:
PrimitiveObject(); PrimitiveObject();
~PrimitiveObject(); ~PrimitiveObject();
@ -60,15 +61,21 @@ public:
bool isFilled() { return _filled; } bool isFilled() { return _filled; }
void draw(); void draw();
bool isBitmap() { return _type == BITMAP; } bool isBitmap() { return _type == BITMAP; }
Bitmap *getBitmapHandle() { assert(_bitmap); return _bitmap; } Bitmap *getBitmapHandle() { assert(_bitmap); return _bitmap.object(); }
void saveState(SaveGame *savedState); void saveState(SaveGame *state) const;
bool restoreState(SaveGame *state);
private: private:
Common::Point _p1, _p2, _p3, _p4; Common::Point _p1, _p2, _p3, _p4;
Color _color; Color _color;
bool _filled; bool _filled;
int _type; int _type;
Bitmap *_bitmap; BitmapPtr _bitmap;
int _id;
static int s_id;
friend class GrimEngine;
}; };
} // end of namespace Grim } // end of namespace Grim

View file

@ -30,6 +30,9 @@
#include "engines/grim/material.h" #include "engines/grim/material.h"
#include "engines/grim/grim.h" #include "engines/grim/grim.h"
#include "engines/grim/lipsync.h" #include "engines/grim/lipsync.h"
#include "engines/grim/savegame.h"
#include "engines/grim/actor.h"
namespace Grim { namespace Grim {
@ -108,7 +111,7 @@ Block *ResourceLoader::getFileFromCache(const char *filename) {
ResourceLoader::ResourceCache *ResourceLoader::getEntryFromCache(const char *filename) { ResourceLoader::ResourceCache *ResourceLoader::getEntryFromCache(const char *filename) {
if (_cache.empty()) if (_cache.empty())
return NULL; return NULL;
if (_cacheDirty) { if (_cacheDirty) {
qsort(_cache.begin(), _cache.size(), sizeof(ResourceCache), sortCallback); qsort(_cache.begin(), _cache.size(), sizeof(ResourceCache), sortCallback);
_cacheDirty = false; _cacheDirty = false;
@ -132,6 +135,20 @@ Block *ResourceLoader::getFileBlock(const char *filename) const {
return l->getFileBlock(filename); return l->getFileBlock(filename);
} }
Block *ResourceLoader::getBlock(const char *filename) {
Common::String fname = filename;
fname.toLowercase();
Block *b = getFileFromCache(fname.c_str());
if (!b) {
b = getFileBlock(fname.c_str());
if (b) {
putIntoCache(fname, b);
}
}
return b;
}
LuaFile *ResourceLoader::openNewStreamLuaFile(const char *filename) const { LuaFile *ResourceLoader::openNewStreamLuaFile(const char *filename) const {
const Lab *l = getLab(filename); const Lab *l = getLab(filename);
@ -182,6 +199,7 @@ Bitmap *ResourceLoader::loadBitmap(const char *filename) {
} }
Bitmap *result = g_grim->registerBitmap(filename, b->data(), b->len()); Bitmap *result = g_grim->registerBitmap(filename, b->data(), b->len());
_bitmaps.push_back(result);
return result; return result;
} }
@ -192,12 +210,14 @@ CMap *ResourceLoader::loadColormap(const char *filename) {
Block *b = getFileFromCache(fname.c_str()); Block *b = getFileFromCache(fname.c_str());
if (!b) { if (!b) {
b = getFileBlock(fname.c_str()); b = getFileBlock(fname.c_str());
if (!b) if (!b) {
error("Could not find colormap %s", filename); error("Could not find colormap %s", filename);
}
putIntoCache(fname, b); putIntoCache(fname, b);
} }
CMap *result = new CMap(filename, b->data(), b->len()); CMap *result = new CMap(filename, b->data(), b->len());
_colormaps.push_back(result);
return result; return result;
} }
@ -209,10 +229,11 @@ Costume *ResourceLoader::loadCostume(const char *filename, Costume *prevCost) {
if (!b) { if (!b) {
b = getFileBlock(fname.c_str()); b = getFileBlock(fname.c_str());
if (!b) if (!b)
error("Could not find costume %s", filename); error("Could not find costume \"%s\"", filename);
putIntoCache(fname, b); putIntoCache(fname, b);
} }
Costume *result = new Costume(filename, b->data(), b->len(), prevCost); Costume *result = new Costume(filename, b->data(), b->len(), prevCost);
_costumes.push_back(result);
return result; return result;
} }
@ -229,6 +250,7 @@ Font *ResourceLoader::loadFont(const char *filename) {
} }
Font *result = new Font(filename, b->data(), b->len()); Font *result = new Font(filename, b->data(), b->len());
_fonts.push_back(result);
return result; return result;
} }
@ -245,6 +267,7 @@ KeyframeAnim *ResourceLoader::loadKeyframe(const char *filename) {
} }
KeyframeAnim *result = new KeyframeAnim(filename, b->data(), b->len()); KeyframeAnim *result = new KeyframeAnim(filename, b->data(), b->len());
_keyframeAnims.push_back(result);
return result; return result;
} }
@ -265,6 +288,7 @@ LipSync *ResourceLoader::loadLipSync(const char *filename) {
// Some lipsync files have no data // Some lipsync files have no data
if (result->isValid()) { if (result->isValid()) {
putIntoCache(fname, b); putIntoCache(fname, b);
_lipsyncs.push_back(result);
} else { } else {
delete result; delete result;
delete b; delete b;
@ -274,7 +298,7 @@ LipSync *ResourceLoader::loadLipSync(const char *filename) {
return result; return result;
} }
Material *ResourceLoader::loadMaterial(const char *filename, const CMap *c) { Material *ResourceLoader::loadMaterial(const char *filename, CMap *c) {
Common::String fname = Common::String(filename); Common::String fname = Common::String(filename);
fname.toLowercase(); fname.toLowercase();
Block *b = getFileFromCache(fname.c_str()); Block *b = getFileFromCache(fname.c_str());
@ -286,11 +310,12 @@ Material *ResourceLoader::loadMaterial(const char *filename, const CMap *c) {
} }
Material *result = new Material(fname.c_str(), b->data(), b->len(), c); Material *result = new Material(fname.c_str(), b->data(), b->len(), c);
_materials.push_back(result);
return result; return result;
} }
Model *ResourceLoader::loadModel(const char *filename, const CMap *c) { Model *ResourceLoader::loadModel(const char *filename, CMap *c) {
Common::String fname = filename; Common::String fname = filename;
fname.toLowercase(); fname.toLowercase();
Block *b = getFileFromCache(fname.c_str()); Block *b = getFileFromCache(fname.c_str());
@ -302,6 +327,7 @@ Model *ResourceLoader::loadModel(const char *filename, const CMap *c) {
} }
Model *result = new Model(filename, b->data(), b->len(), c); Model *result = new Model(filename, b->data(), b->len(), c);
_models.push_back(result);
return result; return result;
} }
@ -326,4 +352,124 @@ void ResourceLoader::uncache(const char *filename) {
} }
} }
void ResourceLoader::uncacheMaterial(Material *mat) {
_materials.remove(mat);
}
void ResourceLoader::uncacheBitmap(Bitmap *bitmap) {
_bitmaps.remove(bitmap);
}
void ResourceLoader::uncacheModel(Model *m) {
_models.remove(m);
}
void ResourceLoader::uncacheColormap(CMap *c) {
_colormaps.remove(c);
}
void ResourceLoader::uncacheKeyframe(KeyframeAnim *k) {
_keyframeAnims.remove(k);
}
void ResourceLoader::uncacheFont(Font *f) {
_fonts.remove(f);
}
void ResourceLoader::uncacheCostume(Costume *c) {
_costumes.remove(c);
}
void ResourceLoader::uncacheLipSync(LipSync *s) {
_lipsyncs.remove(s);
}
MaterialPtr ResourceLoader::getMaterial(const char *fname, CMap *c) {
for (Common::List<Material *>::const_iterator i = _materials.begin(); i != _materials.end(); ++i) {
Material *m = *i;
if (strcmp(fname, m->_fname.c_str()) == 0 && *m->_cmap == *c) {
return m;
}
}
return loadMaterial(fname, c);
}
BitmapPtr ResourceLoader::getBitmap(const char *fname) {
for (Common::List<Bitmap *>::const_iterator i = _bitmaps.begin(); i != _bitmaps.end(); ++i) {
Bitmap *b = *i;
if (strcmp(fname, b->filename()) == 0) {
return b;
}
}
return loadBitmap(fname);
}
ModelPtr ResourceLoader::getModel(const char *fname, CMap *c) {
for (Common::List<Model *>::const_iterator i = _models.begin(); i != _models.end(); ++i) {
Model *m = *i;
if (strcmp(fname, m->_fname.c_str()) == 0 && *m->_cmap == *c) {
return m;
}
}
return loadModel(fname, c);
}
CMapPtr ResourceLoader::getColormap(const char *fname) {
for (Common::List<CMap *>::const_iterator i = _colormaps.begin(); i != _colormaps.end(); ++i) {
CMap *c = *i;
if (strcmp(fname, c->_fname.c_str()) == 0) {
return c;
}
}
return loadColormap(fname);
}
KeyframeAnimPtr ResourceLoader::getKeyframe(const char *fname) {
for (Common::List<KeyframeAnim *>::const_iterator i = _keyframeAnims.begin(); i != _keyframeAnims.end(); ++i) {
KeyframeAnim *k = *i;
if (strcmp(fname, k->filename()) == 0) {
return k;
}
}
return loadKeyframe(fname);
}
FontPtr ResourceLoader::getFont(const char *fname) {
for (Common::List<Font *>::const_iterator i = _fonts.begin(); i != _fonts.end(); ++i) {
Font *f = *i;
if (strcmp(fname, f->getFilename().c_str()) == 0) {
return f;
}
}
return loadFont(fname);
}
CostumePtr ResourceLoader::getCostume(const char *fname, Costume *prev) {
for (Common::List<Costume *>::const_iterator i = _costumes.begin(); i != _costumes.end(); ++i) {
Costume *c = *i;
if (strcmp(fname, c->filename()) == 0) {
return c;
}
}
return loadCostume(fname, prev);
}
LipSyncPtr ResourceLoader::getLipSync(const char *fname) {
for (Common::List<LipSync *>::const_iterator i = _lipsyncs.begin(); i != _lipsyncs.end(); ++i) {
LipSync *l = *i;
if (strcmp(fname, l->filename()) == 0) {
return l;
}
}
return loadLipSync(fname);
}
} // end of namespace Grim } // end of namespace Grim

View file

@ -29,6 +29,7 @@
#include "common/archive.h" #include "common/archive.h"
#include "engines/grim/lab.h" #include "engines/grim/lab.h"
#include "engines/grim/object.h"
namespace Grim { namespace Grim {
@ -40,6 +41,17 @@ class KeyframeAnim;
class Material; class Material;
class Model; class Model;
class LipSync; class LipSync;
class TrackedObject;
class SaveGame;
typedef ObjectPtr<Material> MaterialPtr;
typedef ObjectPtr<Bitmap> BitmapPtr;
typedef ObjectPtr<Model> ModelPtr;
typedef ObjectPtr<CMap> CMapPtr;
typedef ObjectPtr<KeyframeAnim> KeyframeAnimPtr;
typedef ObjectPtr<Font> FontPtr;
typedef ObjectPtr<Costume> CostumePtr;
typedef ObjectPtr<LipSync> LipSyncPtr;
class ResourceLoader { class ResourceLoader {
public: public:
@ -51,23 +63,40 @@ public:
Costume *loadCostume(const char *fname, Costume *prevCost); Costume *loadCostume(const char *fname, Costume *prevCost);
Font *loadFont(const char *fname); Font *loadFont(const char *fname);
KeyframeAnim *loadKeyframe(const char *fname); KeyframeAnim *loadKeyframe(const char *fname);
Material *loadMaterial(const char *fname, const CMap *c); Material *loadMaterial(const char *fname, CMap *c);
Model *loadModel(const char *fname, const CMap *c); Model *loadModel(const char *fname, CMap *c);
LipSync *loadLipSync(const char *fname); LipSync *loadLipSync(const char *fname);
Block *getFileBlock(const char *filename) const; Block *getFileBlock(const char *filename) const;
Block *getBlock(const char *filename);
Common::File *openNewStreamFile(const char *filename) const; Common::File *openNewStreamFile(const char *filename) const;
LuaFile *openNewStreamLuaFile(const char *filename) const; LuaFile *openNewStreamLuaFile(const char *filename) const;
void uncache(const char *fname); void uncache(const char *fname);
bool fileExists(const char *filename) const; bool fileExists(const char *filename) const;
int fileLength(const char *filename) const; int fileLength(const char *filename) const;
MaterialPtr getMaterial(const char *filename, CMap *c);
BitmapPtr getBitmap(const char *fname);
ModelPtr getModel(const char *fname, CMap *c);
CMapPtr getColormap(const char *fname);
KeyframeAnimPtr getKeyframe(const char *fname);
FontPtr getFont(const char *fname);
CostumePtr getCostume(const char *fname, Costume *prevCostume);
LipSyncPtr getLipSync(const char *fname);
void uncacheMaterial(Material *m);
void uncacheBitmap(Bitmap *bitmap);
void uncacheModel(Model *m);
void uncacheColormap(CMap *c);
void uncacheKeyframe(KeyframeAnim *kf);
void uncacheFont(Font *f);
void uncacheCostume(Costume *c);
void uncacheLipSync(LipSync *l);
struct ResourceCache { struct ResourceCache {
char *fname; char *fname;
Block *resPtr; Block *resPtr;
}; };
private: private:
const Lab *getLab(const char *filename) const; const Lab *getLab(const char *filename) const;
Block *getFileFromCache(const char *filename); Block *getFileFromCache(const char *filename);
ResourceLoader::ResourceCache *getEntryFromCache(const char *filename); ResourceLoader::ResourceCache *getEntryFromCache(const char *filename);
@ -80,6 +109,15 @@ private:
Common::Array<ResourceCache> _cache; Common::Array<ResourceCache> _cache;
bool _cacheDirty; bool _cacheDirty;
int32 _cacheMemorySize; int32 _cacheMemorySize;
Common::List<Material *> _materials;
Common::List<Bitmap *> _bitmaps;
Common::List<Model *> _models;
Common::List<CMap *> _colormaps;
Common::List<KeyframeAnim *> _keyframeAnims;
Common::List<Font *> _fonts;
Common::List<Costume *> _costumes;
Common::List<LipSync *> _lipsyncs;
}; };
extern ResourceLoader *g_resourceloader; extern ResourceLoader *g_resourceloader;

View file

@ -26,7 +26,10 @@
#include "common/endian.h" #include "common/endian.h"
#include "common/system.h" #include "common/system.h"
#include "graphics/vector3d.h"
#include "engines/grim/savegame.h" #include "engines/grim/savegame.h"
#include "engines/grim/color.h"
namespace Grim { namespace Grim {
@ -228,4 +231,68 @@ void SaveGame::writeByte(byte data) {
_sectionSize++; _sectionSize++;
} }
void SaveGame::writeVector3d(const Graphics::Vector3d &vec) {
writeFloat(vec.x());
writeFloat(vec.y());
writeFloat(vec.z());
}
void SaveGame::writeColor(const Grim::Color &color) {
writeByte(color.red());
writeByte(color.green());
writeByte(color.blue());
}
void SaveGame::writeFloat(float data) {
write(reinterpret_cast<void *>(&data), sizeof(float));
}
void SaveGame::writeCharString(const char *string) {
int32 len = strlen(string);
writeLESint32(len);
write(string, len);
}
void SaveGame::writeString(const Common::String &string) {
writeCharString(string.c_str());
}
Graphics::Vector3d SaveGame::readVector3d() {
float x = readFloat();
float y = readFloat();
float z = readFloat();
return Graphics::Vector3d(x, y, z);
}
Grim::Color SaveGame::readColor() {
Color color;
color.red() = readByte();
color.green() = readByte();
color.blue() = readByte();
return color;
}
float SaveGame::readFloat() {
float f;
read(reinterpret_cast<void *>(&f), sizeof(float));
return f;
}
const char *SaveGame::readCharString() {
int32 len = readLESint32();
char *str = new char[len + 1];
read(str, len);
str[len] = '\0';
return str;
}
Common::String SaveGame::readString() {
const char *str = readCharString();
Common::String s = str;
delete[] str;
return s;
}
} // end of namespace Grim } // end of namespace Grim

View file

@ -28,8 +28,14 @@
#include "common/savefile.h" #include "common/savefile.h"
namespace Graphics {
class Vector3d;
}
namespace Grim { namespace Grim {
class Color;
class SaveGame { class SaveGame {
public: public:
SaveGame(const char *filename, bool saving); SaveGame(const char *filename, bool saving);
@ -48,6 +54,17 @@ public:
void writeLESint32(int32 data); void writeLESint32(int32 data);
void writeLEBool(bool data); void writeLEBool(bool data);
void writeByte(byte data); void writeByte(byte data);
void writeCharString(const char *string);
void writeString(const Common::String &string);
void writeVector3d(const Graphics::Vector3d &vec);
void writeColor(const Grim::Color &color);
void writeFloat(float data);
Graphics::Vector3d readVector3d();
Grim::Color readColor();
float readFloat();
const char *readCharString();
Common::String readString();
protected: protected:
bool _saving; bool _saving;

View file

@ -28,11 +28,14 @@
#include "engines/grim/colormap.h" #include "engines/grim/colormap.h"
#include "engines/grim/grim.h" #include "engines/grim/grim.h"
#include "engines/grim/savegame.h" #include "engines/grim/savegame.h"
#include "engines/grim/lua.h"
#include "engines/grim/imuse/imuse.h" #include "engines/grim/imuse/imuse.h"
namespace Grim { namespace Grim {
int Scene::s_id = 0;
Scene::Scene(const char *sceneName, const char *buf, int len) : Scene::Scene(const char *sceneName, const char *buf, int len) :
_locked(false), _name(sceneName), _enableLights(false) { _locked(false), _name(sceneName), _enableLights(false) {
TextSplitter ts(buf, len); TextSplitter ts(buf, len);
@ -40,15 +43,15 @@ Scene::Scene(const char *sceneName, const char *buf, int len) :
ts.expectString("section: colormaps"); ts.expectString("section: colormaps");
ts.scanString(" numcolormaps %d", 1, &_numCmaps); ts.scanString(" numcolormaps %d", 1, &_numCmaps);
_cmaps = new CMap*[_numCmaps]; _cmaps = new CMapPtr[_numCmaps];
char cmap_name[256]; char cmap_name[256];
for (int i = 0; i < _numCmaps; i++) { for (int i = 0; i < _numCmaps; i++) {
ts.scanString(" colormap %256s", 1, cmap_name); ts.scanString(" colormap %256s", 1, cmap_name);
_cmaps[i] = g_resourceloader->loadColormap(cmap_name); _cmaps[i] = g_resourceloader->getColormap(cmap_name);
} }
if (ts.checkString("section: objectstates")) { if (ts.checkString("section: object_states")) {
ts.expectString("section: objectstates"); ts.expectString("section: object_states");
ts.scanString(" tot_objects %d", 1, &_numObjectStates); ts.scanString(" tot_objects %d", 1, &_numObjectStates);
char object_name[256]; char object_name[256];
for (int l = 0; l < _numObjectStates; l++) { for (int l = 0; l < _numObjectStates; l++) {
@ -99,34 +102,199 @@ Scene::Scene(const char *sceneName, const char *buf, int len) :
_numSectors++; _numSectors++;
} }
// Allocate and fill an array of sector info // Allocate and fill an array of sector info
_sectors = new Sector[_numSectors]; _sectors = new Sector*[_numSectors];
ts.setLineNumber(sectorStart); ts.setLineNumber(sectorStart);
for (int i = 0; i < _numSectors; i++) for (int i = 0; i < _numSectors; i++) {
_sectors[i].load(ts); _sectors[i] = new Sector();
_sectors[i]->load(ts);
}
++s_id;
_id = s_id;
}
Scene::Scene() :
_cmaps(NULL) {
} }
Scene::~Scene() { Scene::~Scene() {
delete[] _cmaps; if (_cmaps) {
delete[] _setups; delete[] _cmaps;
delete[] _lights; delete[] _setups;
delete[] _sectors; delete[] _lights;
for (StateList::iterator i = _states.begin(); i != _states.end(); ++i) for (int i = 0; i < _numSectors; ++i) {
delete (*i); delete _sectors[i];
}
delete[] _sectors;
for (StateList::iterator i = _states.begin(); i != _states.end(); ++i)
delete (*i);
}
} }
void Scene::saveState(SaveGame *savedState) { void Scene::saveState(SaveGame *savedState) const {
savedState->writeLESint32(_name.size()); savedState->writeString(_name);
savedState->write(_name.c_str(), _name.size()); savedState->writeLESint32(_numCmaps);
for (int i = 0; i < _numCmaps; ++i) {
savedState->writeCharString(_cmaps[i]->filename());
}
savedState->writeLEUint32(_currSetup - _setups); // current setup id savedState->writeLEUint32(_currSetup - _setups); // current setup id
savedState->writeLEUint32(_locked); savedState->writeLEUint32(_locked);
savedState->writeLEUint32(_enableLights); savedState->writeLEUint32(_enableLights);
savedState->writeLEUint32(_minVolume); savedState->writeLEUint32(_minVolume);
savedState->writeLEUint32(_maxVolume); savedState->writeLEUint32(_maxVolume);
savedState->writeLEUint32(_numObjectStates); savedState->writeLEUint32(_states.size());
for (StateList::iterator i = _states.begin(); i != _states.end(); ++i) { for (StateList::const_iterator i = _states.begin(); i != _states.end(); ++i) {
// ObjectState *s = *i; savedState->writeLEUint32(g_grim->objectStateId(*i));
} }
//Setups
savedState->writeLEUint32(_numSetups);
for (int i = 0; i < _numSetups; ++i) {
Setup &set = _setups[i];
//name
savedState->writeString(set._name);
//bkgndBm
if (set._bkgndBm) {
savedState->writeLEUint32(1);
savedState->writeCharString(set._bkgndBm->filename());
} else {
savedState->writeLEUint32(0);
}
//bkgndZBm
if (set._bkgndZBm) {
savedState->writeLEUint32(1);
savedState->writeCharString(set._bkgndZBm->filename());
} else {
savedState->writeLEUint32(0);
}
savedState->writeVector3d(set._pos);
savedState->writeVector3d(set._interest);
savedState->writeFloat(set._roll);
savedState->writeFloat(set._fov);
savedState->writeFloat(set._nclip);
savedState->writeFloat(set._fclip);
}
//Sectors
savedState->writeLEUint32(_numSectors);
for (int i = 0; i < _numSectors; ++i) {
_sectors[i]->saveState(savedState);
}
//Lights
savedState->writeLEUint32(_numLights);
for (int i = 0; i < _numLights; ++i) {
Light &l = _lights[i];
//name
savedState->writeString(l._name);
//type
savedState->writeString(l._type);
savedState->writeVector3d(l._pos);
savedState->writeVector3d(l._dir);
savedState->writeColor(l._color);
savedState->writeFloat(l._intensity);
savedState->writeFloat(l._umbraangle);
savedState->writeFloat(l._penumbraangle);
}
}
bool Scene::restoreState(SaveGame *savedState) {
_name = savedState->readString();
_numCmaps = savedState->readLESint32();
_cmaps = new CMapPtr[_numCmaps];
for (int i = 0; i < _numCmaps; ++i) {
const char *str = savedState->readCharString();
_cmaps[i] = g_resourceloader->getColormap(str);
delete[] str;
}
int32 currSetupId = savedState->readLEUint32();
_locked = savedState->readLEUint32();
_enableLights = savedState->readLEUint32();
_minVolume = savedState->readLEUint32();
_maxVolume = savedState->readLEUint32();
_numObjectStates = savedState->readLEUint32();
_states.clear();
for (int i = 0; i < _numObjectStates; ++i) {
int32 id = savedState->readLEUint32();
ObjectState *o = g_grim->objectState(id);
_states.push_back(o);
}
//Setups
_numSetups = savedState->readLEUint32();
_setups = new Setup[_numSetups];
_currSetup = _setups + currSetupId;
for (int i = 0; i < _numSetups; ++i) {
Setup &set = _setups[i];
set._name = savedState->readString();
if (savedState->readLEUint32()) {
const char *fname = savedState->readCharString();
set._bkgndBm = g_resourceloader->getBitmap(fname);
} else {
set._bkgndBm = NULL;
}
if (savedState->readLEUint32()) {
const char *fname = savedState->readCharString();
set._bkgndZBm = g_resourceloader->getBitmap(fname);
} else {
set._bkgndZBm = NULL;
}
set._pos = savedState->readVector3d();
set._interest = savedState->readVector3d();
set._roll = savedState->readFloat();
set._fov = savedState->readFloat();
set._nclip = savedState->readFloat();
set._fclip = savedState->readFloat();
}
//Sectors
_numSectors = savedState->readLEUint32();
if (_numSectors > 0) {
_sectors = new Sector*[_numSectors];
for (int i = 0; i < _numSectors; ++i) {
_sectors[i] = new Sector();
_sectors[i]->restoreState(savedState);
}
} else {
_sectors = NULL;
}
_numLights = savedState->readLEUint32();
_lights = new Light[_numLights];
for (int i = 0; i < _numLights; ++i) {
Light &l = _lights[i];
l._name = savedState->readString();
l._type = savedState->readString();
l._pos = savedState->readVector3d();
l._dir = savedState->readVector3d();
l._color = savedState->readColor();
l._intensity = savedState->readFloat();
l._umbraangle = savedState->readFloat();
l._penumbraangle = savedState->readFloat();
}
return true;
} }
void Scene::Setup::load(TextSplitter &ts) { void Scene::Setup::load(TextSplitter &ts) {
@ -136,7 +304,7 @@ void Scene::Setup::load(TextSplitter &ts) {
_name = buf; _name = buf;
ts.scanString(" background %256s", 1, buf); ts.scanString(" background %256s", 1, buf);
_bkgndBm = g_resourceloader->loadBitmap(buf); _bkgndBm = g_resourceloader->getBitmap(buf);
if (!_bkgndBm) { if (!_bkgndBm) {
if (gDebugLevel == DEBUG_BITMAPS || gDebugLevel == DEBUG_ERROR || gDebugLevel == DEBUG_ALL) if (gDebugLevel == DEBUG_BITMAPS || gDebugLevel == DEBUG_ERROR || gDebugLevel == DEBUG_ALL)
printf("Unable to load scene bitmap: %s\n", buf); printf("Unable to load scene bitmap: %s\n", buf);
@ -152,7 +320,7 @@ void Scene::Setup::load(TextSplitter &ts) {
ts.scanString(" zbuffer %256s", 1, buf); ts.scanString(" zbuffer %256s", 1, buf);
// Don't even try to load if it's the "none" bitmap // Don't even try to load if it's the "none" bitmap
if (strcmp(buf, "<none>.lbm") != 0) { if (strcmp(buf, "<none>.lbm") != 0) {
_bkgndZBm = g_resourceloader->loadBitmap(buf); _bkgndZBm = g_resourceloader->getBitmap(buf);
if (gDebugLevel == DEBUG_BITMAPS || gDebugLevel == DEBUG_NORMAL || gDebugLevel == DEBUG_ALL) if (gDebugLevel == DEBUG_BITMAPS || gDebugLevel == DEBUG_NORMAL || gDebugLevel == DEBUG_ALL)
printf("Loading scene z-buffer bitmap: %s\n", buf); printf("Loading scene z-buffer bitmap: %s\n", buf);
} }
@ -237,6 +405,19 @@ void Scene::setSetup(int num) {
g_grim->flagRefreshShadowMask(true); g_grim->flagRefreshShadowMask(true);
} }
void Scene::drawBackground() const {
if (_currSetup->_bkgndZBm) // Some screens have no zbuffer mask (eg, Alley)
_currSetup->_bkgndZBm->draw();
if (!_currSetup->_bkgndBm) {
// This should fail softly, for some reason jumping to the signpost (sg) will load
// the scene in such a way that the background isn't immediately available
warning("Background hasn't loaded yet for setup %s in %s!", _currSetup->_name.c_str(), _name.c_str());
} else {
_currSetup->_bkgndBm->draw();
}
}
void Scene::drawBitmaps(ObjectState::Position stage) { void Scene::drawBitmaps(ObjectState::Position stage) {
for (StateList::iterator i = _states.begin(); i != _states.end(); ++i) { for (StateList::iterator i = _states.begin(); i != _states.end(); ++i) {
if ((*i)->pos() == stage && _currSetup == _setups + (*i)->setupID()) if ((*i)->pos() == stage && _currSetup == _setups + (*i)->setupID())
@ -246,8 +427,8 @@ void Scene::drawBitmaps(ObjectState::Position stage) {
Sector *Scene::findPointSector(Graphics::Vector3d p, int flags) { Sector *Scene::findPointSector(Graphics::Vector3d p, int flags) {
for (int i = 0; i < _numSectors; i++) { for (int i = 0; i < _numSectors; i++) {
Sector *sector = _sectors + i; Sector *sector = _sectors[i];
if ((sector->type() & flags) && sector->visible() && sector->isPointInSector(p)) if (sector && (sector->type() & flags) && sector->visible() && sector->isPointInSector(p))
return sector; return sector;
} }
return NULL; return NULL;
@ -259,7 +440,7 @@ void Scene::findClosestSector(Graphics::Vector3d p, Sector **sect, Graphics::Vec
float minDist = 0.0; float minDist = 0.0;
for (int i = 0; i < _numSectors; i++) { for (int i = 0; i < _numSectors; i++) {
Sector *sector = _sectors + i; Sector *sector = _sectors[i];
if ((sector->type() & 0x1000) == 0 || !sector->visible()) if ((sector->type() & 0x1000) == 0 || !sector->visible())
continue; continue;
Graphics::Vector3d closestPt = sector->closestPoint(p); Graphics::Vector3d closestPt = sector->closestPoint(p);

View file

@ -37,25 +37,16 @@ class SaveGame;
class Scene { class Scene {
public: public:
Scene(const char *name, const char *buf, int len); Scene(const char *name, const char *buf, int len);
Scene();
~Scene(); ~Scene();
void saveState(SaveGame *savedState); void saveState(SaveGame *savedState) const;
bool restoreState(SaveGame *savedState);
int _minVolume; int _minVolume;
int _maxVolume; int _maxVolume;
void drawBackground() const { void drawBackground() const;
if (_currSetup->_bkgndZBm) // Some screens have no zbuffer mask (eg, Alley)
_currSetup->_bkgndZBm->draw();
if (!_currSetup->_bkgndBm) {
// This should fail softly, for some reason jumping to the signpost (sg) will load
// the scene in such a way that the background isn't immediately available
warning("Background hasn't loaded yet for setup %s in %s!", _currSetup->_name.c_str(), _name.c_str());
} else {
_currSetup->_bkgndBm->draw();
}
}
void drawBitmaps(ObjectState::Position stage); void drawBitmaps(ObjectState::Position stage);
void setupCamera() { void setupCamera() {
_currSetup->setupCamera(); _currSetup->setupCamera();
@ -82,7 +73,7 @@ public:
} }
Sector *getSectorBase(int id) { Sector *getSectorBase(int id) {
if ((_numSectors >= 0) && (id < _numSectors)) if ((_numSectors >= 0) && (id < _numSectors))
return &_sectors[id]; return _sectors[id];
else else
return NULL; return NULL;
} }
@ -106,7 +97,7 @@ public:
void load(TextSplitter &ts); void load(TextSplitter &ts);
void setupCamera() const; void setupCamera() const;
Common::String _name; Common::String _name;
Bitmap *_bkgndBm, *_bkgndZBm; BitmapPtr _bkgndBm, _bkgndZBm;
Graphics::Vector3d _pos, _interest; Graphics::Vector3d _pos, _interest;
float _roll, _fov, _nclip, _fclip; float _roll, _fov, _nclip, _fclip;
}; };
@ -126,10 +117,10 @@ private:
Common::String _name; Common::String _name;
int _numCmaps; int _numCmaps;
CMap **_cmaps; CMapPtr *_cmaps;
int _numSetups, _numLights, _numSectors, _numObjectStates; int _numSetups, _numLights, _numSectors, _numObjectStates;
bool _enableLights; bool _enableLights;
Sector *_sectors; Sector **_sectors;
Light *_lights; Light *_lights;
Setup *_setups; Setup *_setups;
public: public:
@ -137,6 +128,11 @@ public:
private: private:
typedef Common::List<ObjectState*> StateList; typedef Common::List<ObjectState*> StateList;
StateList _states; StateList _states;
int _id;
static int s_id;
friend class GrimEngine;
}; };
} // end of namespace Grim } // end of namespace Grim

View file

@ -30,6 +30,8 @@
namespace Grim { namespace Grim {
int TextObject::s_id = 0;
Common::String parseMsgText(const char *msg, char *msgId); Common::String parseMsgText(const char *msg, char *msgId);
TextObjectDefaults sayLineDefaults; TextObjectDefaults sayLineDefaults;
@ -37,7 +39,7 @@ TextObjectDefaults printLineDefaults;
TextObjectDefaults blastTextDefaults; TextObjectDefaults blastTextDefaults;
TextObject::TextObject(bool blastDraw, bool isSpeech) : TextObject::TextObject(bool blastDraw, bool isSpeech) :
_created(false), _x(0), _y(0), _width(0), _height(0), _justify(0), Object(), _created(false), _x(0), _y(0), _width(0), _height(0), _justify(0),
_numberLines(1), _disabled(false), _font(NULL), _textBitmap(NULL), _numberLines(1), _disabled(false), _font(NULL), _textBitmap(NULL),
_bitmapWidthPtr(NULL), _textObjectHandle(NULL) { _bitmapWidthPtr(NULL), _textObjectHandle(NULL) {
memset(_textID, 0, sizeof(_textID)); memset(_textID, 0, sizeof(_textID));
@ -46,6 +48,14 @@ TextObject::TextObject(bool blastDraw, bool isSpeech) :
_fgColor._vals[2] = 0; _fgColor._vals[2] = 0;
_blastDraw = blastDraw; _blastDraw = blastDraw;
_isSpeech = isSpeech; _isSpeech = isSpeech;
++s_id;
_id = s_id;
}
TextObject::TextObject() :
Object(), _textObjectHandle(NULL), _bitmapWidthPtr(NULL) {
} }
void TextObject::setText(const char *text) { void TextObject::setText(const char *text) {
@ -64,26 +74,53 @@ TextObject::~TextObject() {
destroyBitmap(); destroyBitmap();
} }
void TextObject::saveState(SaveGame *savedState) { void TextObject::saveState(SaveGame *state) const {
int32 size; // state->writeLESint32(_created);
PointerId ptr;
size = strlen(_textID); state->writeColor(_fgColor);
savedState->writeLESint32(size);
savedState->write(_textID, size); state->writeLESint32(_x);
ptr = makeIdFromPointer(_font); state->writeLESint32(_y);
savedState->writeLEUint32(ptr.low); state->writeLESint32(_width);
savedState->writeLEUint32(ptr.hi); state->writeLESint32(_height);
savedState->writeLEUint32(_blastDraw); state->writeLESint32(_justify);
savedState->writeLEUint32(_disabled); state->writeLESint32(_numberLines);
savedState->writeLEUint32(_justify);
savedState->writeLEUint32(_width); state->writeLESint32(_disabled);
savedState->writeLEUint32(_height); state->writeLESint32(_blastDraw);
savedState->writeLEUint32(_x); state->writeLESint32(_isSpeech);
savedState->writeLEUint32(_y);
savedState->writeLEUint32(_fgColor.red()); state->writeString(_font->getFilename());
savedState->writeLEUint32(_fgColor.green());
savedState->writeLEUint32(_fgColor.blue()); state->write(_textID, 256);
}
bool TextObject::restoreState(SaveGame *state) {
// _created = state->readLESint32();
_fgColor = state->readColor();
_x = state->readLESint32();
_y = state->readLESint32();
_width = state->readLESint32();
_height = state->readLESint32();
_justify = state->readLESint32();
_numberLines = state->readLESint32();
_disabled = state->readLESint32();
_blastDraw = state->readLESint32();
_isSpeech = state->readLESint32();
_font = g_resourceloader->getFont(state->readString().c_str());
state->read(_textID, 256);
_created = false;
_textBitmap = NULL;
_textObjectHandle = NULL;
_bitmapWidthPtr = NULL;
return true;
} }
void TextObject::setDefaults(TextObjectDefaults *defaults) { void TextObject::setDefaults(TextObjectDefaults *defaults) {
@ -178,7 +215,7 @@ void TextObject::createBitmap() {
lineWidth -= MAX(_font->getCharWidth(msg[i]), _font->getCharDataWidth(msg[i])); lineWidth -= MAX(_font->getCharWidth(msg[i]), _font->getCharDataWidth(msg[i]));
message.deleteLastChar(); message.deleteLastChar();
--i; --i;
} }
} else if (msg[i] != ' ') { // if it is a unique word } else if (msg[i] != ' ') { // if it is a unique word
int dashWidth = MAX(_font->getCharWidth('-'), _font->getCharDataWidth('-')); int dashWidth = MAX(_font->getCharWidth('-'), _font->getCharDataWidth('-'));
while (lineWidth + dashWidth > maxWidth) { while (lineWidth + dashWidth > maxWidth) {

View file

@ -39,7 +39,7 @@ struct TextObjectDefaults {
int width, height; int width, height;
int justify; int justify;
bool disabled; bool disabled;
Font *font; FontPtr font;
}; };
#define TEXT_NULL ' ' #define TEXT_NULL ' '
@ -48,9 +48,11 @@ extern TextObjectDefaults sayLineDefaults;
extern TextObjectDefaults printLineDefaults; extern TextObjectDefaults printLineDefaults;
extern TextObjectDefaults blastTextDefaults; extern TextObjectDefaults blastTextDefaults;
class TextObject { class TextObject : public Object {
GRIM_OBJECT(TextObject)
public: public:
TextObject(bool blastDraw, bool isSpeech = false); TextObject(bool blastDraw, bool isSpeech = false);
TextObject();
~TextObject(); ~TextObject();
void createBitmap(); void createBitmap();
void destroyBitmap(); void destroyBitmap();
@ -79,11 +81,13 @@ public:
int getBitmapWidth(); int getBitmapWidth();
int getBitmapHeight(); int getBitmapHeight();
int getTextCharPosition(int pos); int getTextCharPosition(int pos);
void saveState(SaveGame *savedState);
const char *name() const { return _textID; } const char *name() const { return _textID; }
void draw(); void draw();
void saveState(SaveGame *state) const;
bool restoreState(SaveGame *state);
enum Justify { enum Justify {
NONE, NONE,
CENTER, CENTER,
@ -100,11 +104,16 @@ protected:
bool _disabled; bool _disabled;
bool _blastDraw; bool _blastDraw;
bool _isSpeech; bool _isSpeech;
Font *_font; FontPtr _font;
char _textID[256]; char _textID[256];
uint8 *_textBitmap; uint8 *_textBitmap;
int *_bitmapWidthPtr; int *_bitmapWidthPtr;
GfxBase::TextObjectHandle **_textObjectHandle; GfxBase::TextObjectHandle **_textObjectHandle;
int _id;
static int s_id;
friend class GrimEngine;
}; };
} // end of namespace Grim } // end of namespace Grim

View file

@ -28,9 +28,53 @@
#include "engines/grim/grim.h" #include "engines/grim/grim.h"
#include "engines/grim/walkplane.h" #include "engines/grim/walkplane.h"
#include "engines/grim/textsplit.h" #include "engines/grim/textsplit.h"
#include "engines/grim/savegame.h"
namespace Grim { namespace Grim {
void Sector::saveState(SaveGame *savedState) const {
savedState->writeLESint32(_numVertices);
savedState->writeLESint32(_id);
savedState->writeLESint32(_type);
savedState->writeLESint32(_visible);
savedState->writeFloat(_height);
const char *str = _name.c_str();
int32 size = strlen(str);
savedState->writeLESint32(size);
savedState->write(str, size);
for (int i = 0; i < _numVertices + 1; ++i) {
savedState->writeVector3d(_vertices[i]);
}
savedState->writeVector3d(_normal);
}
bool Sector::restoreState(SaveGame *savedState) {
_numVertices = savedState->readLESint32();
_id = savedState->readLESint32();
_type = savedState->readLESint32();
_visible = savedState->readLESint32();
_height = savedState->readFloat();
int32 size = savedState->readLESint32();
char *str = new char[size+1];
savedState->read(str, size);
str[size]='\0';
_name = str;
delete[] str;
_vertices = new Graphics::Vector3d[_numVertices + 1];
for (int i = 0; i < _numVertices + 1; ++i) {
_vertices[i] = savedState->readVector3d();
}
_normal = savedState->readVector3d();
return true;
}
void Sector::load(TextSplitter &ts) { void Sector::load(TextSplitter &ts) {
char buf[256]; char buf[256];
int ident = 0, i = 0; int ident = 0, i = 0;
@ -108,7 +152,6 @@ bool Sector::isPointInSector(Graphics::Vector3d point) const {
// z-coordinates so the railing in Cafe Calavera works properly. // z-coordinates so the railing in Cafe Calavera works properly.
if (_height != 0.0f && _height != 9999.0f) { if (_height != 0.0f && _height != 9999.0f) {
bool heightOK = false; bool heightOK = false;
// Handle height above Z // Handle height above Z
if ((point.z() >= _vertices[0].z()) && (point.z() <= _vertices[0].z() + _height)) if ((point.z() >= _vertices[0].z()) && (point.z() <= _vertices[0].z() + _height))
heightOK = true; heightOK = true;

View file

@ -32,12 +32,16 @@
namespace Grim { namespace Grim {
class SaveGame;
class TextSplitter; class TextSplitter;
class Sector { class Sector {
public: public:
Sector() : _vertices(0) {} Sector() : _vertices(NULL) {}
~Sector() { if (_vertices) delete[] _vertices; } virtual ~Sector() { if (_vertices) delete[] _vertices; }
void saveState(SaveGame *savedState) const;
bool restoreState(SaveGame *savedState);
void load(TextSplitter &ts); void load(TextSplitter &ts);