diff options
Diffstat (limited to 'engines/saga')
48 files changed, 1509 insertions, 2051 deletions
diff --git a/engines/saga/actor.cpp b/engines/saga/actor.cpp index 8bc8025032..5111f1ae07 100644 --- a/engines/saga/actor.cpp +++ b/engines/saga/actor.cpp @@ -42,18 +42,42 @@ namespace Saga { ActorData::ActorData() { - memset(this, 0, sizeof(*this)); -} + _frames = NULL; + _frameListResourceId = 0; + _speechColor = 0; + _inScene = false; + + _actorFlags = 0; + _currentAction = 0; + _facingDirection = 0; + _actionDirection = 0; + _actionCycle = 0; + _targetObject = 0; + _lastZone = NULL; + + _cycleFrameSequence = 0; + _cycleDelay = 0; + _cycleTimeCount = 0; + _cycleFlags = 0; + + _fallVelocity = 0; + _fallAcceleration = 0; + _fallPosition = 0; -ActorData::~ActorData() { - if (!_shareFrames) - free(_frames); - free(_tileDirections); - free(_walkStepsPoints); - freeSpriteList(); + _dragonBaseFrame = 0; + _dragonStepCycle = 0; + _dragonMoveType = 0; + + _frameNumber = 0; + + _walkStepsCount = 0; + _walkStepIndex = 0; + + _walkFrameSequence = 0; } + void ActorData::saveState(Common::OutSaveFile *out) { - int i = 0; + uint i = 0; CommonObjectData::saveState(out); out->writeUint16LE(_actorFlags); out->writeSint32LE(_currentAction); @@ -74,13 +98,13 @@ void ActorData::saveState(Common::OutSaveFile *out) { out->writeByte(_dragonMoveType); out->writeSint32LE(_frameNumber); - out->writeSint32LE(_tileDirectionsAlloced); - for (i = 0; i < _tileDirectionsAlloced; i++) { + out->writeSint32LE(_tileDirections.size()); + for (i = 0; i < _tileDirections.size(); i++) { out->writeByte(_tileDirections[i]); } - out->writeSint32LE(_walkStepsAlloced); - for (i = 0; i < _walkStepsAlloced; i++) { + out->writeSint32LE(_walkStepsPoints.size()); + for (i = 0; i < _walkStepsPoints.size(); i++) { out->writeSint16LE(_walkStepsPoints[i].x); out->writeSint16LE(_walkStepsPoints[i].y); } @@ -93,7 +117,7 @@ void ActorData::saveState(Common::OutSaveFile *out) { } void ActorData::loadState(uint32 version, Common::InSaveFile *in) { - int i = 0; + uint i = 0; CommonObjectData::loadState(in); _actorFlags = in->readUint16LE(); _currentAction = in->readSint32LE(); @@ -125,13 +149,13 @@ void ActorData::loadState(uint32 version, Common::InSaveFile *in) { _frameNumber = in->readSint32LE(); - setTileDirectionsSize(in->readSint32LE(), true); - for (i = 0; i < _tileDirectionsAlloced; i++) { + _tileDirections.resize(in->readSint32LE()); + for (i = 0; i < _tileDirections.size(); i++) { _tileDirections[i] = in->readByte(); } - setWalkStepsPointsSize(in->readSint32LE(), true); - for (i = 0; i < _walkStepsAlloced; i++) { + _walkStepsPoints.resize(in->readSint32LE()); + for (i = 0; i < _walkStepsPoints.size(); i++) { _walkStepsPoints[i].x = in->readSint16LE(); _walkStepsPoints[i].y = in->readSint16LE(); } @@ -143,38 +167,16 @@ void ActorData::loadState(uint32 version, Common::InSaveFile *in) { _walkFrameSequence = in->readSint32LE(); } -void ActorData::setTileDirectionsSize(int size, bool forceRealloc) { - if ((size <= _tileDirectionsAlloced) && !forceRealloc) { - return; - } - _tileDirectionsAlloced = size; - _tileDirections = (byte*)realloc(_tileDirections, _tileDirectionsAlloced * sizeof(*_tileDirections)); -} - void ActorData::cycleWrap(int cycleLimit) { if (_actionCycle >= cycleLimit) _actionCycle = 0; } -void ActorData::setWalkStepsPointsSize(int size, bool forceRealloc) { - if ((size <= _walkStepsAlloced) && !forceRealloc) { - return; - } - _walkStepsAlloced = size; - _walkStepsPoints = (Point*)realloc(_walkStepsPoints, _walkStepsAlloced * sizeof(*_walkStepsPoints)); -} - void ActorData::addWalkStepPoint(const Point &point) { - setWalkStepsPointsSize(_walkStepsCount + 1, false); + _walkStepsPoints.resize(_walkStepsCount + 1); _walkStepsPoints[_walkStepsCount++] = point; } -void ActorData::freeSpriteList() { - _spriteList.freeMem(); -} - - - static int commonObjectCompare(const CommonObjectDataPointer& obj1, const CommonObjectDataPointer& obj2) { int p1 = obj1->_location.y - obj1->_location.z; int p2 = obj2->_location.y - obj2->_location.z; @@ -212,26 +214,14 @@ static int tileCommonObjectCompare(const CommonObjectDataPointer& obj1, const Co Actor::Actor(SagaEngine *vm) : _vm(vm) { int i; - byte *stringsPointer; - size_t stringsLength; - ActorData *actor; - ObjectData *obj; + ByteArray stringsData; debug(9, "Actor::Actor()"); _handleActionDiv = 15; - _actors = NULL; - _actorsCount = 0; - - _objs = NULL; - _objsCount = 0; - #ifdef ACTOR_DEBUG _debugPointsCount = 0; #endif - _protagStates = NULL; - _protagStatesCount = 0; - _pathList.resize(600); _pathListIndex = 0; @@ -242,7 +232,7 @@ Actor::Actor(SagaEngine *vm) : _vm(vm) { _yCellCount = _vm->_scene->getHeight(); _xCellCount = _vm->getDisplayInfo().width; - _pathCell = (int8 *)malloc(_yCellCount * _xCellCount * sizeof(*_pathCell)); + _pathCell.resize(_yCellCount * _xCellCount); _pathRect.left = 0; _pathRect.right = _vm->getDisplayInfo().width; @@ -260,19 +250,17 @@ Actor::Actor(SagaEngine *vm) : _vm(vm) { if (_vm->getGameId() == GID_ITE) { - _vm->_resource->loadResource(_actorContext, _vm->getResourceDescription()->actorsStringsResourceId, stringsPointer, stringsLength); + _vm->_resource->loadResource(_actorContext, _vm->getResourceDescription()->actorsStringsResourceId, stringsData); - _vm->loadStrings(_actorsStrings, stringsPointer, stringsLength); - free(stringsPointer); + _vm->loadStrings(_actorsStrings, stringsData); } if (_vm->getGameId() == GID_ITE) { - _actorsCount = ITE_ACTORCOUNT; - _actors = (ActorData **)malloc(_actorsCount * sizeof(*_actors)); - for (i = 0; i < _actorsCount; i++) { - actor = _actors[i] = new ActorData(); - actor->_id = actorIndexToId(i); + _actors.resize(ITE_ACTORCOUNT); + i = 0; + for (ActorDataArray::iterator actor = _actors.begin(); actor != _actors.end(); ++actor, i++) { actor->_index = i; + actor->_id = actorIndexToId(actor->_index); debug(9, "init actor id=%d index=%d", actor->_id, actor->_index); actor->_nameIndex = ITE_ActorTable[i].nameIndex; actor->_scriptEntrypointNumber = ITE_ActorTable[i].scriptEntrypointNumber; @@ -294,12 +282,11 @@ Actor::Actor(SagaEngine *vm) : _vm(vm) { warning("Disabling actor Id=%d index=%d", actor->_id, actor->_index); } } - _objsCount = ITE_OBJECTCOUNT; - _objs = (ObjectData **)malloc(_objsCount * sizeof(*_objs)); - for (i = 0; i < _objsCount; i++) { - obj = _objs[i] = new ObjectData(); - obj->_id = objIndexToId(i); + _objs.resize(ITE_OBJECTCOUNT); + i = 0; + for (ObjectDataArray::iterator obj = _objs.begin(); obj != _objs.end(); ++obj, i++) { obj->_index = i; + obj->_id = objIndexToId(obj->_index); debug(9, "init obj id=%d index=%d", obj->_id, obj->_index); obj->_nameIndex = ITE_ObjectTable[i].nameIndex; obj->_scriptEntrypointNumber = ITE_ObjectTable[i].scriptEntrypointNumber; @@ -318,69 +305,42 @@ Actor::Actor(SagaEngine *vm) : _vm(vm) { Actor::~Actor() { debug(9, "Actor::~Actor()"); - - free(_pathCell); - _actorsStrings.freeMem(); - //release resources - freeProtagStates(); - freeActorList(); - freeObjList(); -} - -void Actor::freeProtagStates() { - int i; - for (i = 0; i < _protagStatesCount; i++) { - free(_protagStates[i]._frames); - } - free(_protagStates); - _protagStates = NULL; - _protagStatesCount = 0; } -void Actor::loadFrameList(int frameListResourceId, ActorFrameSequence *&framesPointer, int &framesCount) { - byte *resourcePointer; - size_t resourceLength; +void Actor::loadFrameList(int frameListResourceId, ActorFrameSequences &frames) { + ByteArray resourceData; debug(9, "Loading frame resource id %d", frameListResourceId); - _vm->_resource->loadResource(_actorContext, frameListResourceId, resourcePointer, resourceLength); - - framesCount = resourceLength / 16; - debug(9, "Frame resource contains %d frames (res length is %d)", framesCount, (int)resourceLength); + _vm->_resource->loadResource(_actorContext, frameListResourceId, resourceData); - framesPointer = (ActorFrameSequence *)malloc(sizeof(ActorFrameSequence) * framesCount); - if (framesPointer == NULL && framesCount != 0) { - memoryError("Actor::loadFrameList"); - } + frames.resize(resourceData.size() / 16); + debug(9, "Frame resource contains %d frames (res length is %d)", frames.size(), (int)resourceData.size()); - MemoryReadStreamEndian readS(resourcePointer, resourceLength, _actorContext->isBigEndian()); + ByteArrayReadStreamEndian readS(resourceData, _actorContext->isBigEndian()); - for (int i = 0; i < framesCount; i++) { - debug(9, "frameType %d", i); + for (ActorFrameSequences::iterator frame = frames.begin(); frame != frames.end(); ++frame) { for (int orient = 0; orient < ACTOR_DIRECTIONS_COUNT; orient++) { // Load all four orientations - framesPointer[i].directions[orient].frameIndex = readS.readUint16(); + frame->directions[orient].frameIndex = readS.readUint16(); if (_vm->getGameId() == GID_ITE) { - framesPointer[i].directions[orient].frameCount = readS.readSint16(); + frame->directions[orient].frameCount = readS.readSint16(); } else { - framesPointer[i].directions[orient].frameCount = readS.readByte(); + frame->directions[orient].frameCount = readS.readByte(); readS.readByte(); } - if (framesPointer[i].directions[orient].frameCount < 0) - warning("frameCount < 0 (%d)", framesPointer[i].directions[orient].frameCount); - debug(9, "frameIndex %d frameCount %d", framesPointer[i].directions[orient].frameIndex, framesPointer[i].directions[orient].frameCount); + if (frame->directions[orient].frameCount < 0) + warning("frameCount < 0 (%d)", frame->directions[orient].frameCount); + debug(9, "frameIndex %d frameCount %d", frame->directions[orient].frameIndex, frame->directions[orient].frameCount); } } - - free(resourcePointer); } bool Actor::loadActorResources(ActorData *actor) { bool gotSomething = false; if (actor->_frameListResourceId) { - loadFrameList(actor->_frameListResourceId, actor->_frames, actor->_framesCount); - - actor->_shareFrames = false; + loadFrameList(actor->_frameListResourceId, actor->_framesContainer); + actor->_frames = &actor->_framesContainer; gotSomething = true; } else { @@ -400,26 +360,18 @@ bool Actor::loadActorResources(ActorData *actor) { return gotSomething; } -void Actor::freeActorList() { - int i; - ActorData *actor; - for (i = 0; i < _actorsCount; i++) { - actor = _actors[i]; - delete actor; - } - free(_actors); - _actors = NULL; - _actorsCount = 0; -} - void Actor::loadActorSpriteList(ActorData *actor) { - int lastFrame = 0; + uint lastFrame = 0; + uint curFrameIndex; int resourceId = actor->_spriteListResourceId; - - for (int i = 0; i < actor->_framesCount; i++) { - for (int orient = 0; orient < ACTOR_DIRECTIONS_COUNT; orient++) { - if (actor->_frames[i].directions[orient].frameIndex > lastFrame) { - lastFrame = actor->_frames[i].directions[orient].frameIndex; + + if (actor->_frames != NULL) { + for (ActorFrameSequences::const_iterator i = actor->_frames->begin(); i != actor->_frames->end(); ++i) { + for (int orient = 0; orient < ACTOR_DIRECTIONS_COUNT; orient++) { + curFrameIndex = i->directions[orient].frameIndex; + if (curFrameIndex > lastFrame) { + lastFrame = curFrameIndex; + } } } } @@ -430,7 +382,7 @@ void Actor::loadActorSpriteList(ActorData *actor) { if (_vm->getGameId() == GID_ITE) { if (actor->_flags & kExtended) { - while ((lastFrame >= actor->_spriteList.spriteCount)) { + while ((lastFrame >= actor->_spriteList.size())) { resourceId++; debug(9, "Appending to actor sprite list %d", resourceId); _vm->_sprite->loadList(resourceId, actor->_spriteList); @@ -441,9 +393,7 @@ void Actor::loadActorSpriteList(ActorData *actor) { void Actor::loadActorList(int protagonistIdx, int actorCount, int actorsResourceID, int protagStatesCount, int protagStatesResourceID) { int i, j; - ActorData *actor; - byte* actorListData; - size_t actorListLength; + ByteArray actorListData; byte walk[128]; byte acv[6]; int movementSpeed; @@ -451,24 +401,20 @@ void Actor::loadActorList(int protagonistIdx, int actorCount, int actorsResource int walkStepCount; int stateResourceId; - freeActorList(); - - _vm->_resource->loadResource(_actorContext, actorsResourceID, actorListData, actorListLength); + _vm->_resource->loadResource(_actorContext, actorsResourceID, actorListData); - _actorsCount = actorCount; - - if (actorListLength != (uint)_actorsCount * ACTOR_INHM_SIZE) { + if (actorListData.size() != (uint)actorCount * ACTOR_INHM_SIZE) { error("Actor::loadActorList wrong actorlist length"); } - MemoryReadStream actorS(actorListData, actorListLength); + ByteArrayReadStreamEndian actorS(actorListData); - _actors = (ActorData **)malloc(_actorsCount * sizeof(*_actors)); - for (i = 0; i < _actorsCount; i++) { - actor = _actors[i] = new ActorData(); - actor->_id = objectIndexToId(kGameObjectActor, i); //actorIndexToId(i); + _actors.resize(actorCount); + i = 0; + for (ActorDataArray::iterator actor = _actors.begin(); actor != _actors.end(); ++actor, i++) { actor->_index = i; - debug(4, "init actor id=0x%x index=%d", actor->_id, actor->_index); + actor->_id = objectIndexToId(kGameObjectActor, actor->_index); //actorIndexToId(i); + debug(4, "init actor id=0x%X index=%d", actor->_id, actor->_index); actorS.readUint32LE(); //next displayed actorS.readByte(); //type actor->_flags = actorS.readByte(); @@ -531,86 +477,58 @@ void Actor::loadActorList(int protagonistIdx, int actorCount, int actorsResource } // actorS.seek(6, SEEK_CUR); //action vars } - free(actorListData); - _actors[protagonistIdx]->_flags |= kProtagonist | kExtended; + _actors[protagonistIdx]._flags |= kProtagonist | kExtended; - for (i = 0; i < _actorsCount; i++) { - actor = _actors[i]; + for (ActorDataArray::iterator actor = _actors.begin(); actor != _actors.end(); ++actor) { //if (actor->_flags & kProtagonist) { loadActorResources(actor); //break; //} } - _centerActor = _protagonist = _actors[protagonistIdx]; + _centerActor = _protagonist = &_actors[protagonistIdx]; _protagState = 0; if (protagStatesResourceID) { - if (!_protagonist->_shareFrames) - free(_protagonist->_frames); - freeProtagStates(); - - _protagStates = (ProtagStateData *)malloc(sizeof(ProtagStateData) * protagStatesCount); + _protagStates.resize(protagStatesCount); - byte *idsResourcePointer; - size_t idsResourceLength; + ByteArray idsResourceData; - _vm->_resource->loadResource(_actorContext, protagStatesResourceID, - idsResourcePointer, idsResourceLength); + _vm->_resource->loadResource(_actorContext, protagStatesResourceID, idsResourceData); - if (idsResourceLength < (size_t)protagStatesCount * 4) { + if (idsResourceData.size() < (size_t)protagStatesCount * 4) { error("Wrong protagonist states resource"); } - MemoryReadStream statesIds(idsResourcePointer, idsResourceLength); + ByteArrayReadStreamEndian statesIds(idsResourceData); for (i = 0; i < protagStatesCount; i++) { stateResourceId = statesIds.readUint32LE(); - loadFrameList(stateResourceId, _protagStates[i]._frames, _protagStates[i]._framesCount); + loadFrameList(stateResourceId, _protagStates[i]._frames); } - free(idsResourcePointer); - _protagonist->_frames = _protagStates[_protagState]._frames; - _protagonist->_framesCount = _protagStates[_protagState]._framesCount; - _protagonist->_shareFrames = true; + _protagonist->_frames = &_protagStates[_protagState]._frames; } - _protagStatesCount = protagStatesCount; -} - -void Actor::freeObjList() { - int i; - ObjectData *object; - for (i = 0; i < _objsCount; i++) { - object = _objs[i]; - delete object; - } - free(_objs); - _objs = NULL; - _objsCount = 0; } void Actor::loadObjList(int objectCount, int objectsResourceID) { - int i; + uint i; int frameListResourceId; - ObjectData *object; - byte* objectListData; - size_t objectListLength; - freeObjList(); + ByteArray objectListData; - _vm->_resource->loadResource(_actorContext, objectsResourceID, objectListData, objectListLength); + _vm->_resource->loadResource(_actorContext, objectsResourceID, objectListData); - _objsCount = objectCount; + _objs.resize(objectCount); - MemoryReadStream objectS(objectListData, objectListLength); + ByteArrayReadStreamEndian objectS(objectListData); - _objs = (ObjectData **)malloc(_objsCount * sizeof(*_objs)); - for (i = 0; i < _objsCount; i++) { - object = _objs[i] = new ObjectData(); - object->_id = objectIndexToId(kGameObjectObject, i); + i = 0; + for (ObjectDataArray::iterator object = _objs.begin(); object != _objs.end(); ++object, i++) { object->_index = i; + object->_id = objectIndexToId(kGameObjectObject, object->_index); debug(9, "init object id=%d index=%d", object->_id, object->_index); objectS.readUint32LE(); //next displayed objectS.readByte(); //type @@ -635,7 +553,6 @@ void Actor::loadObjList(int objectCount, int objectsResourceID) { objectS.readUint16LE(); //BOTTOM object->_interactBits = objectS.readUint16LE(); } - free(objectListData); } void Actor::takeExit(uint16 actorId, const HitZone *hitZone) { @@ -683,7 +600,7 @@ void Actor::stepZoneAction(ActorData *actor, const HitZone *hitZone, bool exit, event.param5 = ID_NOTHING; // With Object event.param6 = ID_PROTAG; // Actor - _vm->_events->queue(&event); + _vm->_events->queue(event); } } @@ -693,7 +610,7 @@ ObjectData *Actor::getObj(uint16 objId) { if (!validObjId(objId)) error("Actor::getObj Wrong objId 0x%X", objId); - obj = _objs[objIdToIndex(objId)]; + obj = &_objs[objIdToIndex(objId)]; if (obj->_disabled) error("Actor::getObj disabled objId 0x%X", objId); @@ -716,7 +633,7 @@ ActorData *Actor::getActor(uint16 actorId) { return _protagonist; } - actor = _actors[actorIdToIndex(actorId)]; + actor = &_actors[actorIdToIndex(actorId)]; if (actor->_disabled) error("Actor::getActor disabled actorId 0x%X", actorId); @@ -729,12 +646,8 @@ void Actor::setProtagState(int state) { #ifdef ENABLE_IHNM if (_vm->getGameId() == GID_IHNM) { - if (!_protagonist->_shareFrames) - free(_protagonist->_frames); - _protagonist->_frames = _protagStates[state]._frames; - _protagonist->_framesCount = _protagStates[state]._framesCount; - _protagonist->_shareFrames = true; + _protagonist->_frames = &_protagStates[state]._frames; } #endif @@ -797,15 +710,18 @@ ActorFrameRange *Actor::getActorFrameRange(uint16 actorId, int frameType) { if ((actor->_facingDirection < kDirUp) || (actor->_facingDirection > kDirUpLeft)) error("Actor::getActorFrameRange Wrong direction 0x%X actorId 0x%X", actor->_facingDirection, actorId); + ActorFrameSequences *frames; + frames = actor->_frames; + if (_vm->getGameId() == GID_ITE) { - if (frameType >= actor->_framesCount) { - warning("Actor::getActorFrameRange Wrong frameType 0x%X (%d) actorId 0x%X", frameType, actor->_framesCount, actorId); + if (uint(frameType) >= frames->size()) { + warning("Actor::getActorFrameRange Wrong frameType 0x%X (%d) actorId 0x%X", frameType, frames->size(), actorId); return &def; } fourDirection = actorDirectionsLUT[actor->_facingDirection]; - return &actor->_frames[frameType].directions[fourDirection]; + return &(*frames)[frameType].directions[fourDirection]; } #ifdef ENABLE_IHNM @@ -816,12 +732,12 @@ ActorFrameRange *Actor::getActorFrameRange(uint16 actorId, int frameType) { // Both of them are invisible and immovable // There is no point to keep throwing warnings about this, the original checks for // a valid framecount too - if (actor->_framesCount == 0) { + if ((frames == NULL) || (frames->empty())) { return &def; } - frameType = CLIP(frameType, 0, actor->_framesCount - 1); + frameType = CLIP(frameType, 0, int(frames->size() - 1)); fourDirection = actorDirectionsLUT[actor->_facingDirection]; - return &actor->_frames[frameType].directions[fourDirection]; + return &(*frames)[frameType].directions[fourDirection]; } #endif @@ -1085,9 +1001,6 @@ void Actor::drawOrderListAdd(const CommonObjectDataPointer& element, CompareFunc } void Actor::createDrawOrderList() { - int i; - ActorData *actor; - ObjectData *obj; CompareFunction compareFunction = 0; if (_vm->_scene->getFlags() & kSceneFlagISO) { @@ -1102,8 +1015,7 @@ void Actor::createDrawOrderList() { } _drawOrderList.clear(); - for (i = 0; i < _actorsCount; i++) { - actor = _actors[i]; + for (ActorDataArray::iterator actor = _actors.begin(); actor != _actors.end(); ++actor) { if (!actor->_inScene) continue; @@ -1113,8 +1025,7 @@ void Actor::createDrawOrderList() { } } - for (i = 0; i < _objsCount; i++) { - obj = _objs[i]; + for (ObjectDataArray::iterator obj = _objs.begin(); obj != _objs.end(); ++obj) { if (obj->_disabled) continue; @@ -1146,19 +1057,20 @@ bool Actor::getSpriteParams(CommonObjectData *commonObjectData, int &frameNumber ActorData *actor = (ActorData *)commonObjectData; spriteList = &(actor->_spriteList); frameNumber = actor->_frameNumber; - if (spriteList->infoList == NULL) + if (spriteList->empty()) { loadActorSpriteList(actor); + } } else if (validObjId(commonObjectData->_id)) { spriteList = &_vm->_sprite->_mainSprites; frameNumber = commonObjectData->_spriteListResourceId; } - if (spriteList->spriteCount == 0) { + if (spriteList->empty()) { return false; } - if ((frameNumber < 0) || (spriteList->spriteCount <= frameNumber)) { + if ((frameNumber < 0) || (spriteList->size() <= uint(frameNumber))) { debug(1, "Actor::getSpriteParams frameNumber invalid for %s id 0x%X (%d)", validObjId(commonObjectData->_id) ? "object" : "actor", commonObjectData->_id, frameNumber); @@ -1184,7 +1096,7 @@ void Actor::drawActors() { return; } - if (_vm->_scene->_entryList.entryListCount == 0) { + if (_vm->_scene->_entryList.empty()) { return; } @@ -1222,12 +1134,13 @@ void Actor::drawSpeech() { ActorData *actor; int width, height; int stringLength = strlen(_activeSpeech.strings[0]); - char *outputString = (char*)calloc(stringLength + 1, 1); + Common::Array<char> outputString; + outputString.resize(stringLength + 1); if (_activeSpeech.speechFlags & kSpeakSlow) - strncpy(outputString, _activeSpeech.strings[0], _activeSpeech.slowModeCharIndex + 1); + strncpy(&outputString.front(), _activeSpeech.strings[0], _activeSpeech.slowModeCharIndex + 1); else - strncpy(outputString, _activeSpeech.strings[0], stringLength); + strncpy(&outputString.front(), _activeSpeech.strings[0], stringLength); if (_activeSpeech.actorsCount > 1) { height = _vm->_font->getHeight(kKnownFontScript); @@ -1244,15 +1157,13 @@ void Actor::drawSpeech() { else if (_vm->getGameId() == GID_IHNM) textPoint.y = 10; // CLIP(actor->_screenPosition.y - 160, 10, _vm->_scene->getHeight(true) - 10 - height); - _vm->_font->textDraw(kKnownFontScript, outputString, textPoint, + _vm->_font->textDraw(kKnownFontScript, &outputString.front(), textPoint, _activeSpeech.speechColor[i], _activeSpeech.outlineColor[i], _activeSpeech.getFontFlags(i)); } } else { - _vm->_font->textDrawRect(kKnownFontScript, outputString, _activeSpeech.drawRect, _activeSpeech.speechColor[0], + _vm->_font->textDrawRect(kKnownFontScript, &outputString.front(), _activeSpeech.drawRect, _activeSpeech.speechColor[0], _activeSpeech.outlineColor[0], _activeSpeech.getFontFlags(0)); } - - free(outputString); } void Actor::actorSpeech(uint16 actorId, const char **strings, int stringsCount, int sampleResourceId, int speechFlags) { @@ -1302,9 +1213,9 @@ void Actor::actorSpeech(uint16 actorId, const char **strings, int stringsCount, // Check Script::sfDropObject for the other part of this hack if (_vm->getGameId() == GID_IHNM && _vm->_scene->currentChapterNumber() == 3 && _vm->_scene->currentSceneNumber() == 59 && _activeSpeech.sampleResourceId == 286) { - for (i = 0; i < _objsCount; i++) { - if (_objs[i]->_id == 16385) { // the compact disk - _objs[i]->_sceneNumber = 59; + for (ObjectDataArray::iterator obj = _objs.begin(); obj != _objs.end(); ++obj) { + if (obj->_id == 16385) { // the compact disk + obj->_sceneNumber = 59; break; } } @@ -1376,36 +1287,31 @@ void Actor::abortSpeech() { } void Actor::saveState(Common::OutSaveFile *out) { - uint16 i; out->writeSint16LE(getProtagState()); - for (i = 0; i < _actorsCount; i++) { - ActorData *a = _actors[i]; - a->saveState(out); + for (ActorDataArray::iterator actor = _actors.begin(); actor != _actors.end(); ++actor) { + actor->saveState(out); } - for (i = 0; i < _objsCount; i++) { - ObjectData *o = _objs[i]; - o->saveState(out); + for (ObjectDataArray::iterator obj = _objs.begin(); obj != _objs.end(); ++obj) { + obj->saveState(out); } } void Actor::loadState(Common::InSaveFile *in) { - int32 i; int16 protagState = in->readSint16LE(); - if (protagState != 0 || _protagonist->_shareFrames) + if (protagState != 0 || (_protagonist->shareFrames())) { setProtagState(protagState); + } - for (i = 0; i < _actorsCount; i++) { - ActorData *a = _actors[i]; - a->loadState(_vm->getCurrentLoadVersion(), in); + for (ActorDataArray::iterator actor = _actors.begin(); actor != _actors.end(); ++actor) { + actor->loadState(_vm->getCurrentLoadVersion(), in); } - for (i = 0; i < _objsCount; i++) { - ObjectData *o = _objs[i]; - o->loadState(in); + for (ObjectDataArray::iterator obj = _objs.begin(); obj != _objs.end(); ++obj) { + obj->loadState(in); } } diff --git a/engines/saga/actor.h b/engines/saga/actor.h index 2f8fdea8ec..2b6b5c2a3b 100644 --- a/engines/saga/actor.h +++ b/engines/saga/actor.h @@ -196,6 +196,8 @@ struct ActorFrameSequence { ActorFrameRange directions[ACTOR_DIRECTIONS_COUNT]; }; +typedef Common::Array<ActorFrameSequence> ActorFrameSequences; + uint pathLine(PointList &pointList, uint idx, const Point &point1, const Point &point2); struct Location { @@ -323,6 +325,21 @@ public: _screenDepth = in->readSint32LE(); _screenScale = in->readSint32LE(); } + + CommonObjectData() { + _disabled = false; + _index = 0; + _id = 0; + _scriptEntrypointNumber = 0; + + _flags = 0; + _nameIndex = 0; + _sceneNumber = 0; + _spriteListResourceId = 0; + + _screenDepth = 0; + _screenScale = 0; + } }; typedef CommonObjectData *CommonObjectDataPointer; @@ -333,19 +350,21 @@ class ObjectData: public CommonObjectData { public: //constant uint16 _interactBits; + ObjectData() { - memset(this, 0, sizeof(*this)); + _interactBits = 0; } }; +typedef Common::Array<ObjectData> ObjectDataArray; + class ActorData: public CommonObjectData { public: //constant SpriteList _spriteList; // sprite list data - bool _shareFrames; - ActorFrameSequence *_frames; // Actor's frames - int _framesCount; // Actor's frames count + ActorFrameSequences *_frames; // Actor's frames + ActorFrameSequences _framesContainer; // Actor's frames int _frameListResourceId; // Actor's frame list resource id byte _speechColor; // Actor dialogue color @@ -376,11 +395,9 @@ public: int32 _frameNumber; // current frame number - int32 _tileDirectionsAlloced; - byte *_tileDirections; + ByteArray _tileDirections; - int32 _walkStepsAlloced; - Point *_walkStepsPoints; + Common::Array<Point> _walkStepsPoints; int32 _walkStepsCount; int32 _walkStepIndex; @@ -391,21 +408,21 @@ public: public: ActorData(); - ~ActorData(); void saveState(Common::OutSaveFile *out); void loadState(uint32 version, Common::InSaveFile *in); - void setTileDirectionsSize(int size, bool forceRealloc); void cycleWrap(int cycleLimit); - void setWalkStepsPointsSize(int size, bool forceRealloc); void addWalkStepPoint(const Point &point); - void freeSpriteList(); + bool shareFrames() { + return ((_frames != NULL) && (_frames != &_framesContainer)); + } }; +typedef Common::Array<ActorData> ActorDataArray; + struct ProtagStateData { - ActorFrameSequence *_frames; // Actor's frames - int _framesCount; // Actor's frames count + ActorFrameSequences _frames; // Actor's frames }; @@ -450,15 +467,17 @@ public: void cmdActorWalkTo(int argc, const char **argv); - bool validActorId(uint16 id) { return (id == ID_PROTAG) || ((id >= objectIndexToId(kGameObjectActor, 0)) && (id < objectIndexToId(kGameObjectActor, _actorsCount))); } + bool validActorId(uint16 id) { + return (id == ID_PROTAG) || ((id >= objectIndexToId(kGameObjectActor, 0)) && (id < objectIndexToId(kGameObjectActor, _actors.size()))); + } int actorIdToIndex(uint16 id) { return (id == ID_PROTAG) ? 0 : objectIdToIndex(id); } uint16 actorIndexToId(int index) { return (index == 0) ? ID_PROTAG : objectIndexToId(kGameObjectActor, index); } ActorData *getActor(uint16 actorId); - ActorData *getFirstActor() { return _actors[0]; } + ActorData *getFirstActor() { return &_actors.front(); } // clarification: Obj - means game object, such Hat, Spoon etc, Object - means Actor,Obj,HitZone,StepZone - bool validObjId(uint16 id) { return (id >= objectIndexToId(kGameObjectObject, 0)) && (id < objectIndexToId(kGameObjectObject, _objsCount)); } + bool validObjId(uint16 id) { return (id >= objectIndexToId(kGameObjectObject, 0)) && (id < objectIndexToId(kGameObjectObject, _objs.size())); } int objIdToIndex(uint16 id) { return objectIdToIndex(id); } uint16 objIndexToId(int index) { return objectIndexToId(kGameObjectObject, index); } ObjectData *getObj(uint16 objId); @@ -525,18 +544,14 @@ public: void setProtagState(int state); int getProtagState() { return _protagState; } - void freeProtagStates(); - - void freeActorList(); void loadActorList(int protagonistIdx, int actorCount, int actorsResourceID, int protagStatesCount, int protagStatesResourceID); - void freeObjList(); void loadObjList(int objectCount, int objectsResourceID); protected: friend class Script; bool loadActorResources(ActorData *actor); - void loadFrameList(int frameListResourceId, ActorFrameSequence *&framesPointer, int &framesCount); + void loadFrameList(int frameListResourceId, ActorFrameSequences &frames); private: void stepZoneAction(ActorData *actor, const HitZone *hitZone, bool exit, bool stopped); void loadActorSpriteList(ActorData *actor); @@ -584,11 +599,9 @@ private: protected: //constants - int _actorsCount; - ActorData **_actors; + ActorDataArray _actors; - int _objsCount; - ObjectData **_objs; + ObjectDataArray _objs; SagaEngine *_vm; ResourceContext *_actorContext; @@ -613,8 +626,7 @@ protected: bool _dragonHunt; private: - ProtagStateData *_protagStates; - int _protagStatesCount; + Common::Array<ProtagStateData> _protagStates; //path stuff struct PathNode { @@ -629,7 +641,7 @@ private: Rect _barrierList[ACTOR_BARRIERS_MAX]; int _barrierCount; - int8 *_pathCell; + Common::Array<int8> _pathCell; int _xCellCount; int _yCellCount; diff --git a/engines/saga/actor_walk.cpp b/engines/saga/actor_walk.cpp index 21643ac1de..5a8ea0c856 100644 --- a/engines/saga/actor_walk.cpp +++ b/engines/saga/actor_walk.cpp @@ -179,9 +179,8 @@ void Actor::actorFaceTowardsPoint(uint16 actorId, const Location &toLocation) { } void Actor::updateActorsScene(int actorsEntrance) { - int i, j; + int j; int followerDirection; - ActorData *actor; Location tempLocation; Location possibleLocation; Point delta; @@ -196,14 +195,13 @@ void Actor::updateActorsScene(int actorsEntrance) { _activeSpeech.playing = false; _protagonist = NULL; - for (i = 0; i < _actorsCount; i++) { - actor = _actors[i]; + for (ActorDataArray::iterator actor = _actors.begin(); actor != _actors.end(); ++actor) { actor->_inScene = false; - actor->_spriteList.freeMem(); + actor->_spriteList.clear(); if (actor->_disabled) { continue; } - if ((actor->_flags & (kProtagonist | kFollower)) || (i == 0)) { + if ((actor->_flags & (kProtagonist | kFollower)) || (actor->_index == 0)) { if (actor->_flags & kProtagonist) { actor->_finalTarget = actor->_location; _centerActor = _protagonist = actor; @@ -227,12 +225,12 @@ void Actor::updateActorsScene(int actorsEntrance) { if (_protagonist == NULL) return; - if ((actorsEntrance >= 0) && (_vm->_scene->_entryList.entryListCount > 0)) { - if (_vm->_scene->_entryList.entryListCount <= actorsEntrance) { + if ((actorsEntrance >= 0) && (!_vm->_scene->_entryList.empty())) { + if (_vm->_scene->_entryList.size() <= uint(actorsEntrance)) { actorsEntrance = 0; //OCEAN bug } - sceneEntry = _vm->_scene->_entryList.getEntry(actorsEntrance); + sceneEntry = &_vm->_scene->_entryList[actorsEntrance]; if (_vm->_scene->getFlags() & kSceneFlagISO) { _protagonist->_location = sceneEntry->location; } else { @@ -266,8 +264,7 @@ void Actor::updateActorsScene(int actorsEntrance) { followerDirection = _protagonist->_facingDirection + 3; calcScreenPosition(_protagonist); - for (i = 0; i < _actorsCount; i++) { - actor = _actors[i]; + for (ActorDataArray::iterator actor = _actors.begin(); actor != _actors.end(); ++actor) { if (actor->_flags & (kFollower)) { actor->_facingDirection = actor->_actionDirection = _protagonist->_facingDirection; actor->_currentAction = kActionWait; @@ -323,8 +320,6 @@ void Actor::updateActorsScene(int actorsEntrance) { } void Actor::handleActions(int msec, bool setup) { - int i; - ActorData *actor; ActorFrameRange *frameRange; int state; int speed; @@ -336,12 +331,11 @@ void Actor::handleActions(int msec, bool setup) { Point hitPoint; Location pickLocation; - for (i = 0; i < _actorsCount; i++) { - actor = _actors[i]; + for (ActorDataArray::iterator actor = _actors.begin(); actor != _actors.end(); ++actor) { if (!actor->_inScene) continue; - if ((_vm->getGameId() == GID_ITE) && (i == ACTOR_DRAGON_INDEX)) { + if ((_vm->getGameId() == GID_ITE) && (actor->_index == ACTOR_DRAGON_INDEX)) { moveDragon(actor); continue; } @@ -722,7 +716,7 @@ void Actor::handleActions(int msec, bool setup) { void Actor::direct(int msec) { - if (_vm->_scene->_entryList.entryListCount == 0) { + if (_vm->_scene->_entryList.empty()) { return; } @@ -866,8 +860,6 @@ bool Actor::followProtagonist(ActorData *actor) { bool Actor::actorWalkTo(uint16 actorId, const Location &toLocation) { ActorData *actor; - ActorData *anotherActor; - int i; Rect testBox; Rect testBox2; @@ -943,7 +935,7 @@ bool Actor::actorWalkTo(uint16 actorId, const Location &toLocation) { int max = _vm->getGameId() == GID_ITE ? 8 : 4; - for (i = 1; i < max; i++) { + for (int i = 1; i < max; i++) { pointAdd = pointFrom; pointAdd.y += i; if (_vm->_scene->canWalk(pointAdd)) { @@ -978,9 +970,7 @@ bool Actor::actorWalkTo(uint16 actorId, const Location &toLocation) { collision.x = ACTOR_COLLISION_WIDTH * actor->_screenScale / (256 * 2); collision.y = ACTOR_COLLISION_HEIGHT * actor->_screenScale / (256 * 2); - - for (i = 0; (i < _actorsCount) && (_barrierCount < ACTOR_BARRIERS_MAX); i++) { - anotherActor = _actors[i]; + for (ActorDataArray::iterator anotherActor = _actors.begin(); (anotherActor != _actors.end()) && (_barrierCount < ACTOR_BARRIERS_MAX); ++anotherActor) { if (!anotherActor->_inScene) continue; if (anotherActor == actor) @@ -1067,8 +1057,8 @@ bool Actor::actorWalkTo(uint16 actorId, const Location &toLocation) { return false; } else { if (actor->_flags & kProtagonist) { - _actors[1]->_actorFlags &= ~kActorNoFollow; // TODO: mark all actors with kFollower flag, not only 1 and 2 - _actors[2]->_actorFlags &= ~kActorNoFollow; + _actors[1]._actorFlags &= ~kActorNoFollow; // TODO: mark all actors with kFollower flag, not only 1 and 2 + _actors[2]._actorFlags &= ~kActorNoFollow; } actor->_currentAction = (actor->_walkStepsCount >= ACTOR_MAX_STEPS_COUNT) ? kActionWalkToLink : kActionWalkToPoint; actor->_walkFrameSequence = getFrameType(kFrameWalk); @@ -1153,7 +1143,7 @@ void Actor::moveDragon(ActorData *actor) { event.param4 = -1; // Object event.param5 = -1; // With Object event.param6 = -1; // Actor - _vm->_events->queue(&event); + _vm->_events->queue(event); _dragonHunt = false; } diff --git a/engines/saga/animation.cpp b/engines/saga/animation.cpp index 0d65d2f191..aca29ed82e 100644 --- a/engines/saga/animation.cpp +++ b/engines/saga/animation.cpp @@ -42,8 +42,6 @@ namespace Saga { Anim::Anim(SagaEngine *vm) : _vm(vm) { uint16 i; - _cutawayList = NULL; - _cutawayListLength = 0; _cutawayActive = false; for (i = 0; i < MAX_ANIMATIONS; i++) @@ -55,21 +53,16 @@ Anim::Anim(SagaEngine *vm) : _vm(vm) { Anim::~Anim() { reset(); -#ifdef ENABLE_IHNM - freeCutawayList(); -#endif } #ifdef ENABLE_IHNM -void Anim::loadCutawayList(const byte *resourcePointer, size_t resourceLength) { - free(_cutawayList); - _cutawayListLength = resourceLength / 8; - _cutawayList = (Cutaway *)malloc(_cutawayListLength * sizeof(Cutaway)); +void Anim::loadCutawayList(const ByteArray &resourceData) { + _cutawayList.resize(resourceData.size() / 8); - MemoryReadStream cutawayS(resourcePointer, resourceLength); + ByteArrayReadStreamEndian cutawayS(resourceData); - for (int i = 0; i < _cutawayListLength; i++) { + for (uint i = 0; i < _cutawayList.size(); i++) { _cutawayList[i].backgroundResourceId = cutawayS.readUint16LE(); _cutawayList[i].animResourceId = cutawayS.readUint16LE(); _cutawayList[i].cycles = cutawayS.readSint16LE(); @@ -77,20 +70,16 @@ void Anim::loadCutawayList(const byte *resourcePointer, size_t resourceLength) { } } -void Anim::freeCutawayList() { - free(_cutawayList); - _cutawayList = NULL; - _cutawayListLength = 0; +void Anim::clearCutawayList() { + _cutawayList.clear(); } int Anim::playCutaway(int cut, bool fade) { debug(0, "playCutaway(%d, %d)", cut, fade); Event event; - Event *q_event = NULL; + EventColumns *eventColumns = NULL; bool startImmediately = false; - byte *resourceData; - size_t resourceDataLength; ResourceContext *context = _vm->_resource->getContext(GAME_RESOURCEFILE); _cutAwayFade = fade; @@ -111,7 +100,7 @@ int Anim::playCutaway(int cut, bool fade) { event.time = 0; event.duration = kNormalFadeDuration; event.data = cur_pal; - q_event = _vm->_events->queue(&event); + eventColumns = _vm->_events->queue(event); // set fade mode event.type = kEvTImmediate; @@ -120,7 +109,7 @@ int Anim::playCutaway(int cut, bool fade) { event.param = kNoFade; event.time = 0; event.duration = 0; - q_event = _vm->_events->chain(q_event, &event); + _vm->_events->chain(eventColumns, event); } // Prepare cutaway @@ -148,7 +137,7 @@ int Anim::playCutaway(int cut, bool fade) { event.time = 0; event.duration = 0; event.param = _cutawayList[cut].backgroundResourceId; - q_event = _vm->_events->chain(q_event, &event); + eventColumns = _vm->_events->chain(eventColumns, event); } else { showCutawayBg(_cutawayList[cut].backgroundResourceId); } @@ -180,9 +169,10 @@ int Anim::playCutaway(int cut, bool fade) { // for the second from the left monitor in Ellen's chapter etc // Therefore, skip the animation bit if animResourceId is 0 and only show the background if (_cutawayList[cut].animResourceId != 0) { - _vm->_resource->loadResource(context, _cutawayList[cut].animResourceId, resourceData, resourceDataLength); - load(MAX_ANIMATIONS + cutawaySlot, resourceData, resourceDataLength); - free(resourceData); + ByteArray resourceData; + _vm->_resource->loadResource(context, _cutawayList[cut].animResourceId, resourceData); + load(MAX_ANIMATIONS + cutawaySlot, resourceData); + setCycles(MAX_ANIMATIONS + cutawaySlot, _cutawayList[cut].cycles); setFrameTime(MAX_ANIMATIONS + cutawaySlot, 1000 / _cutawayList[cut].frameRate); @@ -198,9 +188,9 @@ int Anim::playCutaway(int cut, bool fade) { event.time = (40 / 3) * 1000 / _cutawayList[cut].frameRate; if (fade) - q_event = _vm->_events->chain(q_event, &event); + eventColumns = _vm->_events->chain(eventColumns, event); else - _vm->_events->queue(&event); + _vm->_events->queue(event); } return MAX_ANIMATIONS + cutawaySlot; @@ -222,7 +212,7 @@ void Anim::returnFromCutaway() { if (_cutawayActive) { Event event; - Event *q_event = NULL; + EventColumns *eventColumns = NULL; if (_cutAwayFade) { static PalEntry cur_pal[PAL_ENTRIES]; @@ -237,7 +227,7 @@ void Anim::returnFromCutaway() { event.time = 0; event.duration = kNormalFadeDuration; event.data = cur_pal; - q_event = _vm->_events->queue(&event); + eventColumns = _vm->_events->queue(event); // set fade mode event.type = kEvTImmediate; @@ -246,7 +236,7 @@ void Anim::returnFromCutaway() { event.param = kNoFade; event.time = 0; event.duration = 0; - q_event = _vm->_events->chain(q_event, &event); + _vm->_events->chain(eventColumns, event); } // Clear the cutaway. Note that this sets _cutawayActive to false @@ -257,9 +247,9 @@ void Anim::returnFromCutaway() { event.duration = 0; if (_cutAwayFade) - q_event = _vm->_events->chain(q_event, &event); // chain with the other events + eventColumns = _vm->_events->chain(eventColumns, event); // chain with the other events else - q_event = _vm->_events->queue(&event); + eventColumns = _vm->_events->queue(event); _vm->_scene->restoreScene(); @@ -279,7 +269,7 @@ void Anim::returnFromCutaway() { event.op = kEventResumeAll; event.time = 0; event.duration = 0; - q_event = _vm->_events->chain(q_event, &event); // chain with the other events + _vm->_events->chain(eventColumns, event); // chain with the other events // Draw the scene event.type = kEvTImmediate; @@ -287,7 +277,7 @@ void Anim::returnFromCutaway() { event.op = kEventDraw; event.time = 0; event.duration = 0; - q_event = _vm->_events->chain(q_event, &event); // chain with the other events + _vm->_events->chain(eventColumns, event); // chain with the other events // Handle fade up, if we previously faded down if (_cutAwayFade) { @@ -297,14 +287,14 @@ void Anim::returnFromCutaway() { event.time = 0; event.duration = kNormalFadeDuration; event.data = saved_pal; - q_event = _vm->_events->chain(q_event, &event); + _vm->_events->chain(eventColumns, event); } event.type = kEvTOneshot; event.code = kScriptEvent; event.op = kEventThreadWake; event.param = kWaitTypeWakeUp; - q_event = _vm->_events->chain(q_event, &event); + _vm->_events->chain(eventColumns, event); } } @@ -338,22 +328,20 @@ void Anim::clearCutaway() { void Anim::showCutawayBg(int bg) { ResourceContext *context = _vm->_resource->getContext(GAME_RESOURCEFILE); - byte *resourceData; - size_t resourceDataLength; - byte *buf; - size_t buflen; + ByteArray resourceData; + ByteArray image; int width; int height; Event event; static PalEntry pal[PAL_ENTRIES]; - _vm->_resource->loadResource(context, bg, resourceData, resourceDataLength); - _vm->decodeBGImage(resourceData, resourceDataLength, &buf, &buflen, &width, &height); + _vm->_resource->loadResource(context, bg, resourceData); + _vm->decodeBGImage(resourceData, image, &width, &height); - const byte *palPointer = _vm->getImagePal(resourceData, resourceDataLength); + const byte *palPointer = _vm->getImagePal(resourceData); memcpy(pal, palPointer, sizeof(pal)); const Rect rect(width, height); - _vm->_render->getBackGroundSurface()->blit(rect, buf); + _vm->_render->getBackGroundSurface()->blit(rect, image.getBuffer()); _vm->_render->setFullRefresh(true); _vm->_frameCount++; @@ -365,13 +353,10 @@ void Anim::showCutawayBg(int bg) { event.time = 0; event.duration = kNormalFadeDuration; event.data = pal; - _vm->_events->queue(&event); + _vm->_events->queue(event); } else { _vm->_gfx->setPalette(pal); } - - free(buf); - free(resourceData); } void Anim::startVideo(int vid, bool fade) { @@ -397,18 +382,18 @@ void Anim::returnFromVideo() { #endif -void Anim::load(uint16 animId, const byte *animResourceData, size_t animResourceLength) { +void Anim::load(uint16 animId, const ByteArray &resourceData) { AnimationData *anim; uint16 temp; if (animId >= MAX_ANIMATIONS) { if (animId >= MAX_ANIMATIONS + ARRAYSIZE(_cutawayAnimations)) error("Anim::load could not find unused animation slot"); - anim = _cutawayAnimations[animId - MAX_ANIMATIONS] = new AnimationData(animResourceData, animResourceLength); + anim = _cutawayAnimations[animId - MAX_ANIMATIONS] = new AnimationData(); } else - anim = _animations[animId] = new AnimationData(animResourceData, animResourceLength); + anim = _animations[animId] = new AnimationData(); - MemoryReadStreamEndian headerReadS(anim->resourceData, anim->resourceLength, _vm->isBigEndian()); + ByteArrayReadStreamEndian headerReadS(resourceData, _vm->isBigEndian()); anim->magic = headerReadS.readUint16LE(); // cause ALWAYS LE anim->screenWidth = headerReadS.readUint16(); anim->screenHeight = headerReadS.readUint16(); @@ -418,23 +403,30 @@ void Anim::load(uint16 animId, const byte *animResourceData, size_t animResource anim->maxFrame = headerReadS.readByte() - 1; anim->loopFrame = headerReadS.readByte() - 1; temp = headerReadS.readUint16BE(); - anim->start = headerReadS.pos(); + size_t start; + + start = headerReadS.pos(); if (temp == (uint16)(-1)) { temp = 0; } - anim->start += temp; + start += temp; + size_t dataOffset = headerReadS.pos(); + if (dataOffset != start) { + warning("Anim::load animId=%d start != dataOffset 0x%X 0x%X", animId, uint(start), uint(dataOffset)); + } + + anim->resourceData.resize(resourceData.size() - dataOffset); + + memcpy(anim->resourceData.getBuffer(), resourceData.getBuffer() + dataOffset, anim->resourceData.size()); // Cache frame offsets // WORKAROUND: Cutaway with background resource ID 37 (loaded as cutaway #4) is ending credits. // For some reason it has wrong number of frames specified in its header. So we calculate it here: - if (animId > MAX_ANIMATIONS && _cutawayListLength > 4 && _cutawayList[4].backgroundResourceId == 37 && anim->maxFrame == 143) + if (animId > MAX_ANIMATIONS && _cutawayList.size() > 4 && _cutawayList[4].backgroundResourceId == 37 && anim->maxFrame == 143) anim->maxFrame = fillFrameOffsets(anim, false); - anim->frameOffsets = (size_t *)malloc((anim->maxFrame + 1) * sizeof(*anim->frameOffsets)); - if (anim->frameOffsets == NULL) { - memoryError("Anim::load"); - } + anim->frameOffsets.resize(anim->maxFrame + 1); fillFrameOffsets(anim); @@ -504,7 +496,7 @@ void Anim::play(uint16 animId, int vectorTime, bool playing) { event.op = kEventFrame; event.param = animId; event.time = 10; - _vm->_events->queue(&event); + _vm->_events->queue(event); // Nothing to render here (apart from the background, which is already rendered), // so return @@ -534,7 +526,7 @@ void Anim::play(uint16 animId, int vectorTime, bool playing) { event.op = kEventFrame; event.param = animId; event.time = 0; - _vm->_events->queue(&event); + _vm->_events->queue(event); return; } @@ -575,7 +567,7 @@ void Anim::play(uint16 animId, int vectorTime, bool playing) { event.code = kSceneEvent; event.op = kEventEnd; event.time = anim->frameTime + vectorTime; - _vm->_events->queue(&event); + _vm->_events->queue(event); } return; } else { @@ -601,7 +593,7 @@ void Anim::play(uint16 animId, int vectorTime, bool playing) { event.op = kEventFrame; event.param = animId; event.time = frameTime; - _vm->_events->queue(&event); + _vm->_events->queue(event); } void Anim::stop(uint16 animId) { @@ -688,7 +680,7 @@ void Anim::decodeFrame(AnimationData *anim, size_t frameOffset, byte *buf, size_ error("decodeFrame() Buffer size inadequate"); } - MemoryReadStream readS(anim->resourceData + frameOffset, anim->resourceLength - frameOffset); + MemoryReadStream readS(&anim->resourceData[frameOffset], anim->resourceData.size() - frameOffset); // FIXME: This is thrown when the first video of the IHNM end sequence is shown (the "turn off screen" // video), however the video is played correctly and the rest of the end sequence continues normally @@ -825,9 +817,7 @@ int Anim::fillFrameOffsets(AnimationData *anim, bool reallyFill) { int i; bool longData = isLongData(); - MemoryReadStreamEndian readS(anim->resourceData, anim->resourceLength, !_vm->isBigEndian()); // RLE has inversion BE<>LE - - readS.seek(12); + MemoryReadStreamEndian readS(&anim->resourceData.front(), anim->resourceData.size(), !_vm->isBigEndian()); // RLE has inversion BE<>LE while (readS.pos() != readS.size()) { if (reallyFill) { @@ -843,7 +833,7 @@ int Anim::fillFrameOffsets(AnimationData *anim, bool reallyFill) { // including the frame header, is in big endian format do { markByte = readS.readByte(); -// debug(7, "_pos=%x currentFrame=%i markByte=%x", readS.pos(), currentFrame, markByte); +// debug(7, "_pos=%X currentFrame=%i markByte=%X", readS.pos(), currentFrame, markByte); switch (markByte) { case SAGA_FRAME_START: // Start of frame @@ -942,9 +932,9 @@ void Anim::animInfo() { void Anim::cutawayInfo() { uint16 i; - _vm->_console->DebugPrintf("There are %d cutaways loaded:\n", _cutawayListLength); + _vm->_console->DebugPrintf("There are %d cutaways loaded:\n", _cutawayList.size()); - for (i = 0; i < _cutawayListLength; i++) { + for (i = 0; i < _cutawayList.size(); i++) { _vm->_console->DebugPrintf("%02d: Bg res: %u Anim res: %u Cycles: %u Framerate: %u\n", i, _cutawayList[i].backgroundResourceId, _cutawayList[i].animResourceId, _cutawayList[i].cycles, _cutawayList[i].frameRate); diff --git a/engines/saga/animation.h b/engines/saga/animation.h index 72b145089c..c27909115e 100644 --- a/engines/saga/animation.h +++ b/engines/saga/animation.h @@ -66,8 +66,7 @@ struct Cutaway { // Animation info array member struct AnimationData { - byte *resourceData; - size_t resourceLength; + ByteArray resourceData; uint16 magic; @@ -80,10 +79,8 @@ struct AnimationData { int16 maxFrame; int16 loopFrame; - int16 start; - int16 currentFrame; - size_t *frameOffsets; + Common::Array<size_t> frameOffsets; uint16 completed; uint16 cycles; @@ -93,17 +90,6 @@ struct AnimationData { AnimationState state; int16 linkId; uint16 flags; - - AnimationData(const byte *animResourceData, size_t animResourceLength) { - memset(this, 0, sizeof(*this)); - resourceLength = animResourceLength; - resourceData = (byte*)malloc(animResourceLength); - memcpy(resourceData, animResourceData, animResourceLength); - } - ~AnimationData() { - free(frameOffsets); - free(resourceData); - } }; class Anim { @@ -111,8 +97,8 @@ public: Anim(SagaEngine *vm); ~Anim(); - void loadCutawayList(const byte *resourcePointer, size_t resourceLength); - void freeCutawayList(); + void loadCutawayList(const ByteArray &resourceData); + void clearCutawayList(); int playCutaway(int cut, bool fade); void endCutaway(); void returnFromCutaway(); @@ -123,7 +109,7 @@ public: void endVideo(); void returnFromVideo(); - void load(uint16 animId, const byte *animResourceData, size_t animResourceLength); + void load(uint16 animId, const ByteArray &resourceData); void freeId(uint16 animId); void play(uint16 animId, int vectorTime, bool playing = true); void link(int16 animId1, int16 animId2); @@ -154,9 +140,9 @@ public: bool hasCutaway() { return _cutawayActive; } void setCutAwayMode(int mode) { _cutAwayMode = mode; } - int cutawayListLength() { return _cutawayListLength; } - int cutawayBgResourceID(int cutaway) { return _cutawayList[cutaway].backgroundResourceId; } - int cutawayAnimResourceID(int cutaway) { return _cutawayList[cutaway].animResourceId; } +// int cutawayListLength() { return _cutawayListLength; } +// int cutawayBgResourceID(int cutaway) { return _cutawayList[cutaway].backgroundResourceId; } +// int cutawayAnimResourceID(int cutaway) { return _cutawayList[cutaway].animResourceId; } private: void decodeFrame(AnimationData *anim, size_t frameOffset, byte *buf, size_t bufLength); @@ -205,9 +191,8 @@ private: SagaEngine *_vm; AnimationData *_animations[MAX_ANIMATIONS]; AnimationData *_cutawayAnimations[2]; - Cutaway *_cutawayList; + Common::Array<Cutaway> _cutawayList; PalEntry saved_pal[PAL_ENTRIES]; - int _cutawayListLength; bool _cutawayActive; int _cutAwayMode; bool _cutAwayFade; diff --git a/engines/saga/detection.cpp b/engines/saga/detection.cpp index 7913291527..e43f1ee5c7 100644 --- a/engines/saga/detection.cpp +++ b/engines/saga/detection.cpp @@ -56,9 +56,9 @@ struct SAGAGameDescription { bool SagaEngine::isBigEndian() const { return isMacResources() && getGameId() == GID_ITE; } bool SagaEngine::isMacResources() const { return (getPlatform() == Common::kPlatformMacintosh); } -const GameResourceDescription *SagaEngine::getResourceDescription() { return _gameDescription->resourceDescription; } +const GameResourceDescription *SagaEngine::getResourceDescription() const { return _gameDescription->resourceDescription; } -const GameFontDescription *SagaEngine::getFontDescription(int index) { +const GameFontDescription *SagaEngine::getFontDescription(int index) const { assert(index < _gameDescription->fontsCount); return &_gameDescription->fontDescriptions[index]; } @@ -259,7 +259,7 @@ SaveStateDescriptor SagaMetaEngine::querySaveMetaInfos(const char *target, int s version = SWAP_BYTES_32(version); } - debug(2, "Save version: %x", version); + debug(2, "Save version: 0x%X", version); if (version < 4) warning("This savegame is not endian-safe. There may be problems"); diff --git a/engines/saga/events.cpp b/engines/saga/events.cpp index 1f4091d07c..cf27ad7559 100644 --- a/engines/saga/events.cpp +++ b/engines/saga/events.cpp @@ -49,13 +49,12 @@ Events::Events(SagaEngine *vm) : _vm(vm) { Events::~Events() { debug(8, "Shutting down event subsystem..."); - freeList(); } // Function to process event list once per frame. // First advances event times, then processes each event with the appropriate // handler depending on the type of event. -int Events::handleEvents(long msec) { +void Events::handleEvents(long msec) { long delta_time; int result; @@ -64,7 +63,7 @@ int Events::handleEvents(long msec) { // Process each event in list for (EventList::iterator eventi = _eventList.begin(); eventi != _eventList.end(); ++eventi) { - Event *event_p = &*eventi; + Event *event_p = &eventi->front(); // Call the appropriate event handler for the specific event type switch (event_p->type) { @@ -95,17 +94,15 @@ int Events::handleEvents(long msec) { // handler if ((result == kEvStDelete) || (result == kEvStInvalidCode)) { // If there is no event chain, delete the base event. - if (event_p->chain == NULL) { + if (eventi->size() < 2) { eventi = _eventList.reverse_erase(eventi); } else { // If there is an event chain present, move the next event // in the chain up, adjust it by the previous delta time, // and reprocess the event delta_time = event_p->time; - Event *from_chain = event_p->chain; - memcpy(event_p, from_chain, sizeof(*event_p)); - free(from_chain); - + eventi->pop_front(); + event_p = &eventi->front(); event_p->time += delta_time; --eventi; } @@ -113,8 +110,6 @@ int Events::handleEvents(long msec) { break; } } - - return SUCCESS; } int Events::handleContinuous(Event *event) { @@ -177,9 +172,8 @@ int Events::handleContinuous(Event *event) { // set flag of Dissolve to 1. It is a hack to simulate zero masking. int w, h; byte *maskBuffer; - size_t len; - _vm->_scene->getBGMaskInfo(w, h, maskBuffer, len); + _vm->_scene->getBGMaskInfo(w, h, maskBuffer); rect.left = (_vm->getDisplayInfo().width - w) / 2; rect.top = (_vm->getDisplayInfo().height - h) / 2; rect.setWidth(w); @@ -362,31 +356,26 @@ int Events::handleOneShot(Event *event) { { ResourceContext *context = _vm->_resource->getContext(GAME_RESOURCEFILE); - byte *resourceData; - size_t resourceDataLength; + ByteArray resourceData; - _vm->_resource->loadResource(context, _vm->getResourceDescription()->psychicProfileResourceId, resourceData, resourceDataLength); + _vm->_resource->loadResource(context, _vm->getResourceDescription()->psychicProfileResourceId, resourceData); - byte *buf; - size_t buflen; + ByteArray image; int width; int height; - _vm->decodeBGImage(resourceData, resourceDataLength, &buf, &buflen, &width, &height); + _vm->decodeBGImage(resourceData, image, &width, &height); - const PalEntry *palette = (const PalEntry *)_vm->getImagePal(resourceData, resourceDataLength); + const PalEntry *palette = (const PalEntry *)_vm->getImagePal(resourceData); const Rect profileRect(width, height); - _vm->_render->getBackGroundSurface()->blit(profileRect, buf); + _vm->_render->getBackGroundSurface()->blit(profileRect, image.getBuffer()); _vm->_render->addDirtyRect(profileRect); _vm->_frameCount++; _vm->_gfx->setPalette(palette); - free(buf); - free(resourceData); - // Draw the scene. It won't be drawn by Render::drawScene(), as a placard is up _vm->_scene->draw(); } @@ -570,122 +559,74 @@ int Events::handleInterval(Event *event) { return kEvStDelete; } -// Schedules an event in the event list; returns a pointer to the scheduled -// event suitable for chaining if desired. -Event *Events::queue(Event *event) { - Event *queuedEvent; - - _eventList.push_back(*event); - queuedEvent = &*--_eventList.end(); - initializeEvent(queuedEvent); - - return queuedEvent; -} - -// Places a 'add_event' on the end of an event chain given by 'head_event' -// (head_event may be in any position in the event chain) -Event *Events::chain(Event *headEvent, Event *addEvent) { - if (headEvent == NULL) { - return queue(addEvent); - } +EventColumns *Events::chain(EventColumns *eventColumns, const Event &event) { + + if (eventColumns == NULL) { + EventColumns tmp; - Event *walkEvent; - for (walkEvent = headEvent; walkEvent->chain != NULL; walkEvent = walkEvent->chain) { - continue; + _eventList.push_back(tmp); + eventColumns = &_eventList.back(); } - walkEvent->chain = (Event *)malloc(sizeof(*walkEvent->chain)); - *walkEvent->chain = *addEvent; - initializeEvent(walkEvent->chain); + eventColumns->push_back(event); + initializeEvent(eventColumns->back()); - return walkEvent->chain; + return eventColumns; } -int Events::initializeEvent(Event *event) { - event->chain = NULL; - switch (event->type) { +void Events::initializeEvent(Event &event) { + switch (event.type) { case kEvTOneshot: break; case kEvTContinuous: case kEvTImmediate: - event->time += event->duration; + event.time += event.duration; break; case kEvTInterval: break; - default: - return FAILURE; } - - return SUCCESS; } -int Events::clearList(bool playQueuedMusic) { - Event *chain_walk; - Event *next_chain; - +void Events::clearList(bool playQueuedMusic) { // Walk down event list for (EventList::iterator eventi = _eventList.begin(); eventi != _eventList.end(); ++eventi) { // Only remove events not marked kEvFNoDestory (engine events) - if (!(eventi->code & kEvFNoDestory)) { + if (!(eventi->front().code & kEvFNoDestory)) { // Handle queued music change events before deleting them // This can happen in IHNM by music events set by sfQueueMusic() // Fixes bug #2057987 - "IHNM: Music stops in Ellen's chapter" - if (playQueuedMusic && ((eventi->code & EVENT_MASK) == kMusicEvent)) { + if (playQueuedMusic && ((eventi->front().code & EVENT_MASK) == kMusicEvent)) { _vm->_music->stop(); - if (eventi->op == kEventPlay) - _vm->_music->play(eventi->param, (MusicFlags)eventi->param2); + if (eventi->front().op == kEventPlay) + _vm->_music->play(eventi->front().param, (MusicFlags)eventi->front().param2); } - // Remove any events chained off this one - for (chain_walk = eventi->chain; chain_walk != NULL; chain_walk = next_chain) { - next_chain = chain_walk->chain; - free(chain_walk); - } eventi = _eventList.reverse_erase(eventi); } } - - return SUCCESS; } // Removes all events from the list (even kEvFNoDestory) -int Events::freeList() { - Event *chain_walk; - Event *next_chain; - - // Walk down event list - EventList::iterator eventi = _eventList.begin(); - while (eventi != _eventList.end()) { - - // Remove any events chained off this one */ - for (chain_walk = eventi->chain; chain_walk != NULL; chain_walk = next_chain) { - next_chain = chain_walk->chain; - free(chain_walk); - } - eventi = _eventList.erase(eventi); - } - - return SUCCESS; +void Events::freeList() { + _eventList.clear(); } // Walks down the event list, updating event times by 'msec'. -int Events::processEventTime(long msec) { +void Events::processEventTime(long msec) { uint16 event_count = 0; for (EventList::iterator eventi = _eventList.begin(); eventi != _eventList.end(); ++eventi) { - eventi->time -= msec; + eventi->front().time -= msec; event_count++; - if (eventi->type == kEvTImmediate) + if (eventi->front().type == kEvTImmediate) break; if (event_count > EVENT_WARNINGCOUNT) { warning("Event list exceeds %u", EVENT_WARNINGCOUNT); } } - - return SUCCESS; } } // End of namespace Saga diff --git a/engines/saga/events.h b/engines/saga/events.h index d1530787c2..135c0beb55 100644 --- a/engines/saga/events.h +++ b/engines/saga/events.h @@ -142,13 +142,14 @@ struct Event { long duration; // Duration of event long d_reserved; - Event *chain; // Event chain (For consecutive events) Event() { memset(this, 0, sizeof(*this)); } }; -typedef Common::List<Event> EventList; +typedef Common::List<Event> EventColumns; + +typedef Common::List<EventColumns> EventList; #define EVENT_WARNINGCOUNT 1000 #define EVENT_MASK 0x00FF @@ -164,19 +165,26 @@ class Events { public: Events(SagaEngine *vm); ~Events(); - int handleEvents(long msec); - int clearList(bool playQueuedMusic = true); - int freeList(); - Event *queue(Event *event); - Event *chain(Event *headEvent, Event *addEvent); + void handleEvents(long msec); + void clearList(bool playQueuedMusic = true); + void freeList(); + + // Schedules an event in the event list; returns a pointer to the scheduled + // event columns suitable for chaining if desired. + EventColumns *queue(const Event &event) { + return chain(NULL, event); + } + + // Places a 'event' on the end of an event columns given by 'eventColumns' + EventColumns *chain(EventColumns *eventColumns, const Event &event); private: int handleContinuous(Event *event); int handleOneShot(Event *event); int handleInterval(Event *event); int handleImmediate(Event *event); - int processEventTime(long msec); - int initializeEvent(Event *event); + void processEventTime(long msec); + void initializeEvent(Event &event); private: SagaEngine *_vm; diff --git a/engines/saga/font.cpp b/engines/saga/font.cpp index 47f1a122c0..01e74d2984 100644 --- a/engines/saga/font.cpp +++ b/engines/saga/font.cpp @@ -41,11 +41,9 @@ Font::Font(SagaEngine *vm) : _vm(vm) { assert(_vm->getFontsCount() > 0); - _fonts = (FontData **)calloc(_vm->getFontsCount(), sizeof(*_fonts)); - _loadedFonts = 0; - + _fonts.resize(_vm->getFontsCount()); for (i = 0; i < _vm->getFontsCount(); i++) { - loadFont(_vm->getFontDescription(i)->fontResourceId); + loadFont(&_fonts[i], _vm->getFontDescription(i)->fontResourceId); } _fontMapping = 0; @@ -53,25 +51,11 @@ Font::Font(SagaEngine *vm) : _vm(vm) { Font::~Font() { debug(8, "Font::~Font(): Freeing fonts."); - int i; - - for (i = 0 ; i < _loadedFonts ; i++) { - if (_fonts[i] != NULL) { - free(_fonts[i]->normal.font); - free(_fonts[i]->outline.font); - } - - free(_fonts[i]); - } - - free(_fonts); } -void Font::loadFont(uint32 fontResourceId) { - FontData *font; - byte *fontResourcePointer; - size_t fontResourceLength; +void Font::loadFont(FontData *font, uint32 fontResourceId) { + ByteArray fontResourceData; int numBits; int c; ResourceContext *fontContext; @@ -84,16 +68,13 @@ void Font::loadFont(uint32 fontResourceId) { } // Load font resource - _vm->_resource->loadResource(fontContext, fontResourceId, fontResourcePointer, fontResourceLength); + _vm->_resource->loadResource(fontContext, fontResourceId, fontResourceData); - if (fontResourceLength < FONT_DESCSIZE) { - error("Font::loadFont() Invalid font length (%i < %i)", (int)fontResourceLength, FONT_DESCSIZE); + if (fontResourceData.size() < FONT_DESCSIZE) { + error("Font::loadFont() Invalid font length (%i < %i)", (int)fontResourceData.size(), FONT_DESCSIZE); } - MemoryReadStreamEndian readS(fontResourcePointer, fontResourceLength, fontContext->isBigEndian()); - - // Create new font structure - font = (FontData *)malloc(sizeof(*font)); + ByteArrayReadStreamEndian readS(fontResourceData, fontContext->isBigEndian()); // Read font header font->normal.header.charHeight = readS.readUint16(); @@ -126,17 +107,12 @@ void Font::loadFont(uint32 fontResourceId) { error("Invalid font resource size"); } - font->normal.font = (byte*)malloc(fontResourceLength - FONT_DESCSIZE); - memcpy(font->normal.font, fontResourcePointer + FONT_DESCSIZE, fontResourceLength - FONT_DESCSIZE); - - free(fontResourcePointer); + font->normal.font.resize(fontResourceData.size() - FONT_DESCSIZE); + memcpy(font->normal.font.getBuffer(), fontResourceData.getBuffer() + FONT_DESCSIZE, fontResourceData.size() - FONT_DESCSIZE); // Create outline font style createOutline(font); - - // Set font data - _fonts[_loadedFonts++] = font; } void Font::createOutline(FontData *font) { @@ -145,12 +121,12 @@ void Font::createOutline(FontData *font) { int newByteWidth; int newRowLength = 0; int currentByte; - unsigned char *basePointer; - unsigned char *srcPointer; - unsigned char *destPointer1; - unsigned char *destPointer2; - unsigned char *destPointer3; - unsigned char charRep; + byte *basePointer; + byte *srcPointer; + byte *destPointer1; + byte *destPointer2; + byte *destPointer3; + byte charRep; // Populate new font style character data for (i = 0; i < FONT_CHARCOUNT; i++) { @@ -177,20 +153,20 @@ void Font::createOutline(FontData *font) { font->outline.header.rowLength = newRowLength; // Allocate new font representation storage - font->outline.font = (unsigned char *)calloc(newRowLength, font->outline.header.charHeight); + font->outline.font.resize(newRowLength * font->outline.header.charHeight); // Generate outline font representation for (i = 0; i < FONT_CHARCOUNT; i++) { for (row = 0; row < font->normal.header.charHeight; row++) { for (currentByte = 0; currentByte < font->outline.fontCharEntry[i].byteWidth; currentByte++) { - basePointer = font->outline.font + font->outline.fontCharEntry[i].index + currentByte; + basePointer = &font->outline.font[font->outline.fontCharEntry[i].index + currentByte]; destPointer1 = basePointer + newRowLength * row; destPointer2 = basePointer + newRowLength * (row + 1); destPointer3 = basePointer + newRowLength * (row + 2); if (currentByte > 0) { // Get last two columns from previous byte - srcPointer = font->normal.font + font->normal.header.rowLength * row + font->normal.fontCharEntry[i].index + (currentByte - 1); + srcPointer = &font->normal.font[font->normal.header.rowLength * row + font->normal.fontCharEntry[i].index + (currentByte - 1)]; charRep = *srcPointer; *destPointer1 |= ((charRep << 6) | (charRep << 7)); *destPointer2 |= ((charRep << 6) | (charRep << 7)); @@ -198,7 +174,7 @@ void Font::createOutline(FontData *font) { } if (currentByte < font->normal.fontCharEntry[i].byteWidth) { - srcPointer = font->normal.font + font->normal.header.rowLength * row + font->normal.fontCharEntry[i].index + currentByte; + srcPointer = &font->normal.font[font->normal.header.rowLength * row + font->normal.fontCharEntry[i].index + currentByte]; charRep = *srcPointer; *destPointer1 |= charRep | (charRep >> 1) | (charRep >> 2); *destPointer2 |= charRep | (charRep >> 1) | (charRep >> 2); @@ -210,15 +186,15 @@ void Font::createOutline(FontData *font) { // "Hollow out" character to prevent overdraw for (row = 0; row < font->normal.header.charHeight; row++) { for (currentByte = 0; currentByte < font->outline.fontCharEntry[i].byteWidth; currentByte++) { - destPointer2 = font->outline.font + font->outline.header.rowLength * (row + 1) + font->outline.fontCharEntry[i].index + currentByte; + destPointer2 = &font->outline.font[font->outline.header.rowLength * (row + 1) + font->outline.fontCharEntry[i].index + currentByte]; if (currentByte > 0) { // Get last two columns from previous byte - srcPointer = font->normal.font + font->normal.header.rowLength * row + font->normal.fontCharEntry[i].index + (currentByte - 1); + srcPointer = &font->normal.font[font->normal.header.rowLength * row + font->normal.fontCharEntry[i].index + (currentByte - 1)]; *destPointer2 &= ((*srcPointer << 7) ^ 0xFFU); } if (currentByte < font->normal.fontCharEntry[i].byteWidth) { - srcPointer = font->normal.font + font->normal.header.rowLength * row + font->normal.fontCharEntry[i].index + currentByte; + srcPointer = &font->normal.font[font->normal.header.rowLength * row + font->normal.fontCharEntry[i].index + currentByte]; *destPointer2 &= ((*srcPointer >> 1) ^ 0xFFU); } } @@ -289,7 +265,7 @@ void Font::draw(FontId fontId, const char *text, size_t count, const Common::Poi void Font::outFont(const FontStyle &drawFont, const char *text, size_t count, const Common::Point &point, int color, FontEffectFlags flags) { const byte *textPointer; - byte *c_dataPointer; + const byte *c_dataPointer; int c_code; int charRow = 0; Point textPoint(point); @@ -384,7 +360,7 @@ void Font::outFont(const FontStyle &drawFont, const char *text, size_t count, co break; } - c_dataPointer = drawFont.font + charRow * drawFont.header.rowLength + drawFont.fontCharEntry[c_code].index; + c_dataPointer = &drawFont.font[charRow * drawFont.header.rowLength + drawFont.fontCharEntry[c_code].index]; for (c_byte = 0; c_byte < c_byte_len; c_byte++, c_dataPointer++) { // Check each bit, draw pixel if bit is set diff --git a/engines/saga/font.h b/engines/saga/font.h index 1b9f290a1b..6f66545756 100644 --- a/engines/saga/font.h +++ b/engines/saga/font.h @@ -120,7 +120,7 @@ struct FontCharEntry { struct FontStyle { FontHeader header; FontCharEntry fontCharEntry[256]; - byte *font; + ByteArray font; }; struct FontData { @@ -170,14 +170,14 @@ class Font { void textDrawRect(FontId fontId, const char *text, const Common::Rect &rect, int color, int effectColor, FontEffectFlags flags); void textDraw(FontId fontId, const char *string, const Common::Point &point, int color, int effectColor, FontEffectFlags flags); - void loadFont(uint32 fontResourceId); + void loadFont(FontData *font, uint32 fontResourceId); void createOutline(FontData *font); void draw(FontId fontId, const char *text, size_t count, const Common::Point &point, int color, int effectColor, FontEffectFlags flags); void outFont(const FontStyle &drawFont, const char *text, size_t count, const Common::Point &point, int color, FontEffectFlags flags); FontData *getFont(FontId fontId) { validate(fontId); - return _fonts[fontId]; + return &_fonts[fontId]; } int getHeight(FontId fontId) { @@ -190,7 +190,7 @@ class Font { } } bool valid(FontId fontId) { - return (fontId < _loadedFonts); + return (uint(fontId) < _fonts.size()); } int getByteLen(int numBits) const { int byteLength = numBits / 8; @@ -207,8 +207,7 @@ class Font { int _fontMapping; - int _loadedFonts; - FontData **_fonts; + Common::Array<FontData> _fonts; }; } // End of namespace Saga diff --git a/engines/saga/gfx.cpp b/engines/saga/gfx.cpp index 40a633ac5d..77842acc7b 100644 --- a/engines/saga/gfx.cpp +++ b/engines/saga/gfx.cpp @@ -173,13 +173,11 @@ void Gfx::initPalette() { error("Resource::loadGlobalResources() resource context not found"); } - byte *resourcePointer; - size_t resourceLength; + ByteArray resourceData; - _vm->_resource->loadResource(resourceContext, RID_IHNM_DEFAULT_PALETTE, - resourcePointer, resourceLength); + _vm->_resource->loadResource(resourceContext, RID_IHNM_DEFAULT_PALETTE, resourceData); - MemoryReadStream metaS(resourcePointer, resourceLength); + ByteArrayReadStreamEndian metaS(resourceData); for (int i = 0; i < 256; i++) { _globalPalette[i].red = metaS.readByte(); @@ -187,8 +185,6 @@ void Gfx::initPalette() { _globalPalette[i].blue = metaS.readByte(); } - free(resourcePointer); - setPalette(_globalPalette, true); } @@ -504,22 +500,19 @@ void Gfx::setCursor(CursorType cursorType) { break; } - byte *resource; - size_t resourceLength; - byte *image; - size_t imageLength; + ByteArray resourceData; + ByteArray image; int width, height; if (resourceId != (uint32)-1) { ResourceContext *context = _vm->_resource->getContext(GAME_RESOURCEFILE); - _vm->_resource->loadResource(context, resourceId, resource, resourceLength); + _vm->_resource->loadResource(context, resourceId, resourceData); - _vm->decodeBGImage(resource, resourceLength, &image, &imageLength, &width, &height); + _vm->decodeBGImage(resourceData, image, &width, &height); } else { - resource = NULL; width = height = 31; - image = (byte *)calloc(width, height); + image.resize(width * height); for (int i = 0; i < 14; i++) { image[15 * 31 + i] = 1; @@ -530,10 +523,7 @@ void Gfx::setCursor(CursorType cursorType) { } // Note: Hard-coded hotspot - CursorMan.replaceCursor(image, width, height, 15, 15, 0); - - free(image); - free(resource); + CursorMan.replaceCursor(image.getBuffer(), width, height, 15, 15, 0); } } @@ -564,8 +554,9 @@ bool hitTestPoly(const Point *points, unsigned int npoints, const Point& test_po // This method adds a dirty rectangle automatically void Gfx::drawFrame(const Common::Point &p1, const Common::Point &p2, int color) { - _backBuffer.drawFrame(p1, p2, color); - _vm->_render->addDirtyRect(Common::Rect(p1.x, p1.y, p2.x + 1, p2.y + 1)); + Common::Rect rect(MIN(p1.x, p2.x), MIN(p1.y, p2.y), MAX(p1.x, p2.x) + 1, MAX(p1.y, p2.y) + 1); + _backBuffer.frameRect(rect, color); + _vm->_render->addDirtyRect(rect); } // This method adds a dirty rectangle automatically diff --git a/engines/saga/gfx.h b/engines/saga/gfx.h index f3ccad469f..18d88503ce 100644 --- a/engines/saga/gfx.h +++ b/engines/saga/gfx.h @@ -108,10 +108,7 @@ struct Surface : Graphics::Surface { rect.right = w; rect.bottom = h; } - void drawFrame(const Common::Point &p1, const Common::Point &p2, int color) { - Common::Rect rect(MIN(p1.x, p2.x), MIN(p1.y, p2.y), MAX(p1.x, p2.x) + 1, MAX(p1.y, p2.y) + 1); - frameRect(rect, color); - } + void drawRect(const Common::Rect &destRect, int color) { Common::Rect rect(w , h); rect.clip(destRect); @@ -198,7 +195,7 @@ public: // WARNING: This method does not add a dirty rectangle automatically. // Whenever it gets called, the corresponding caller must take care // to add the corresponding dirty rectangle itself - void drawPolyLine(Common::Point *points, int count, int color) { + void drawPolyLine(const Common::Point *points, int count, int color) { _backBuffer.drawPolyLine(points, count, color); } diff --git a/engines/saga/image.cpp b/engines/saga/image.cpp index 7d8eb83550..87d9e514c8 100644 --- a/engines/saga/image.cpp +++ b/engines/saga/image.cpp @@ -47,22 +47,18 @@ static int granulate(int value, int granularity) { } } -int SagaEngine::decodeBGImage(const byte *image_data, size_t image_size, - byte **output_buf, size_t *output_buf_len, int *w, int *h, bool flip) { +bool SagaEngine::decodeBGImage(const ByteArray &imageData, ByteArray &outputBuffer, int *w, int *h, bool flip) { ImageHeader hdr; int modex_height; const byte *RLE_data_ptr; size_t RLE_data_len; - byte *decode_buf; - size_t decode_buf_len; - byte *out_buf; - size_t out_buf_len; + ByteArray decodeBuffer; - if (image_size <= SAGA_IMAGE_DATA_OFFSET) { - error("decodeBGImage() Image size is way too small (%d)", (int)image_size); + if (imageData.size() <= SAGA_IMAGE_DATA_OFFSET) { + error("decodeBGImage() Image size is way too small (%d)", (int)imageData.size()); } - MemoryReadStreamEndian readS(image_data, image_size, isBigEndian()); + ByteArrayReadStreamEndian readS(imageData, isBigEndian()); hdr.width = readS.readUint16(); hdr.height = readS.readUint16(); @@ -70,45 +66,36 @@ int SagaEngine::decodeBGImage(const byte *image_data, size_t image_size, readS.readUint16(); readS.readUint16(); - RLE_data_ptr = image_data + SAGA_IMAGE_DATA_OFFSET; - RLE_data_len = image_size - SAGA_IMAGE_DATA_OFFSET; + RLE_data_ptr = &imageData.front() + SAGA_IMAGE_DATA_OFFSET; + RLE_data_len = imageData.size() - SAGA_IMAGE_DATA_OFFSET; modex_height = granulate(hdr.height, 4); - decode_buf_len = hdr.width * modex_height; - decode_buf = (byte *)malloc(decode_buf_len); + decodeBuffer.resize(hdr.width * modex_height); - out_buf_len = hdr.width * hdr.height; - out_buf = (byte *)malloc(out_buf_len); + outputBuffer.resize(hdr.width * hdr.height); - if (decodeBGImageRLE(RLE_data_ptr, - RLE_data_len, decode_buf, decode_buf_len) != SUCCESS) { - free(decode_buf); - free(out_buf); - return FAILURE; + if (!decodeBGImageRLE(RLE_data_ptr, RLE_data_len, decodeBuffer)) { + return false; } - unbankBGImage(out_buf, decode_buf, hdr.width, hdr.height); + unbankBGImage(outputBuffer.getBuffer(), decodeBuffer.getBuffer(), hdr.width, hdr.height); // For some reason bg images in IHNM are upside down if (getGameId() == GID_IHNM && !flip) { - flipImage(out_buf, hdr.width, hdr.height); + flipImage(outputBuffer.getBuffer(), hdr.width, hdr.height); } - free(decode_buf); - - *output_buf_len = out_buf_len; - *output_buf = out_buf; - *w = hdr.width; *h = hdr.height; - return SUCCESS; + return true; } -int SagaEngine::decodeBGImageRLE(const byte *inbuf, size_t inbuf_len, byte *outbuf, size_t outbuf_len) { +bool SagaEngine::decodeBGImageRLE(const byte *inbuf, size_t inbuf_len, ByteArray &outbuf) { const byte *inbuf_ptr; byte *outbuf_ptr; + byte *outbuf_start; uint32 inbuf_remain; const byte *inbuf_end; @@ -134,18 +121,18 @@ int SagaEngine::decodeBGImageRLE(const byte *inbuf, size_t inbuf_len, byte *outb inbuf_ptr = inbuf; inbuf_remain = inbuf_len; - outbuf_ptr = outbuf; - outbuf_remain = outbuf_len; + outbuf_start = outbuf_ptr = outbuf.getBuffer(); + outbuf_remain = outbuf.size(); + outbuf_end = (outbuf_start + outbuf_remain) - 1; + memset(outbuf_start, 0, outbuf_remain); inbuf_end = (inbuf + inbuf_len) - 1; - outbuf_end = (outbuf + outbuf_len) - 1; - memset(outbuf, 0, outbuf_len); while ((inbuf_remain > 1) && (outbuf_remain > 0) && !decode_err) { if ((inbuf_ptr > inbuf_end) || (outbuf_ptr > outbuf_end)) { - return FAILURE; + return false; } mark_byte = *inbuf_ptr++; @@ -158,7 +145,7 @@ int SagaEngine::decodeBGImageRLE(const byte *inbuf, size_t inbuf_len, byte *outb // Uncompressed run follows: Max runlength 63 runcount = mark_byte & 0x3f; if ((inbuf_remain < runcount) || (outbuf_remain < runcount)) { - return FAILURE; + return false; } for (c = 0; c < runcount; c++) { @@ -173,7 +160,7 @@ int SagaEngine::decodeBGImageRLE(const byte *inbuf, size_t inbuf_len, byte *outb // Compressed run follows: Max runlength 63 runcount = (mark_byte & 0x3f) + 3; if (!inbuf_remain || (outbuf_remain < runcount)) { - return FAILURE; + return false; } for (c = 0; c < runcount; c++) { @@ -194,8 +181,8 @@ int SagaEngine::decodeBGImageRLE(const byte *inbuf, size_t inbuf_len, byte *outb runcount = ((mark_byte >> 3) & 0x07U) + 3; backtrack_amount = *inbuf_ptr; - if (!inbuf_remain || (backtrack_amount > (outbuf_ptr - outbuf)) || (runcount > outbuf_remain)) { - return FAILURE; + if (!inbuf_remain || (backtrack_amount > (outbuf_ptr - outbuf_start)) || (runcount > outbuf_remain)) { + return false; } inbuf_ptr++; @@ -224,7 +211,7 @@ int SagaEngine::decodeBGImageRLE(const byte *inbuf, size_t inbuf_len, byte *outb runcount = (mark_byte & 0x0F) + 1; if ((inbuf_remain < (runcount + 2)) || (outbuf_remain < (runcount * 8))) { - return FAILURE; + return false; } bitfield_byte1 = *inbuf_ptr++; @@ -252,7 +239,7 @@ int SagaEngine::decodeBGImageRLE(const byte *inbuf, size_t inbuf_len, byte *outb // Uncompressed run follows runcount = ((mark_byte & 0x0F) << 8) + *inbuf_ptr; if ((inbuf_remain < (runcount + 1)) || (outbuf_remain < runcount)) { - return FAILURE; + return false; } inbuf_ptr++; @@ -271,14 +258,14 @@ int SagaEngine::decodeBGImageRLE(const byte *inbuf, size_t inbuf_len, byte *outb // Repeat decoded sequence from output stream backtrack_amount = ((mark_byte & 0x0F) << 8) + *inbuf_ptr; if (inbuf_remain < 2) { - return FAILURE; + return false; } inbuf_ptr++; runcount = *inbuf_ptr++; - if ((backtrack_amount > (outbuf_ptr - outbuf)) || (outbuf_remain < runcount)) { - return FAILURE; + if ((backtrack_amount > (outbuf_ptr - outbuf_start)) || (outbuf_remain < runcount)) { + return false; } backtrack_ptr = outbuf_ptr - backtrack_amount; @@ -292,44 +279,42 @@ int SagaEngine::decodeBGImageRLE(const byte *inbuf, size_t inbuf_len, byte *outb continue; break; default: - return FAILURE; + return false; } } - return SUCCESS; + return true; } -int SagaEngine::flipImage(byte *img_buf, int columns, int scanlines) { +void SagaEngine::flipImage(byte *imageBuffer, int columns, int scanlines) { int line; - byte *tmp_scan; + ByteArray tmp_scan; byte *flip_p1; byte *flip_p2; + byte *flip_tmp; int flipcount = scanlines / 2; - tmp_scan = (byte *)malloc(columns); - if (tmp_scan == NULL) { - return FAILURE; + tmp_scan.resize(columns); + flip_tmp = tmp_scan.getBuffer(); + if (flip_tmp == NULL) { + return; } - flip_p1 = img_buf; - flip_p2 = img_buf + (columns * (scanlines - 1)); + flip_p1 = imageBuffer; + flip_p2 = imageBuffer + (columns * (scanlines - 1)); for (line = 0; line < flipcount; line++) { - memcpy(tmp_scan, flip_p1, columns); + memcpy(flip_tmp, flip_p1, columns); memcpy(flip_p1, flip_p2, columns); - memcpy(flip_p2, tmp_scan, columns); + memcpy(flip_p2, flip_tmp, columns); flip_p1 += columns; flip_p2 -= columns; } - - free(tmp_scan); - - return SUCCESS; } -int SagaEngine::unbankBGImage(byte *dst_buf, const byte *src_buf, int columns, int scanlines) { +void SagaEngine::unbankBGImage(byte *dst_buf, const byte *src_buf, int columns, int scanlines) { int x, y; int temp; int quadruple_rows; @@ -424,15 +409,6 @@ int SagaEngine::unbankBGImage(byte *dst_buf, const byte *src_buf, int columns, i default: break; } - return SUCCESS; -} - -const byte *SagaEngine::getImagePal(const byte *image_data, size_t image_size) { - if (image_size <= SAGA_IMAGE_HEADER_LEN) { - return NULL; - } - - return image_data + SAGA_IMAGE_HEADER_LEN; } } // End of namespace Saga diff --git a/engines/saga/interface.cpp b/engines/saga/interface.cpp index a77ec1c140..5b15fc9803 100644 --- a/engines/saga/interface.cpp +++ b/engines/saga/interface.cpp @@ -124,8 +124,7 @@ static const int IHNMTextStringIdsLUT[56] = { #define buttonRes1 0x42544E01 Interface::Interface(SagaEngine *vm) : _vm(vm) { - byte *resource; - size_t resourceLength; + ByteArray resourceData; int i; #if 0 @@ -170,34 +169,27 @@ Interface::Interface(SagaEngine *vm) : _vm(vm) { } } - _vm->_resource->loadResource(_interfaceContext, _vm->getResourceDescription()->mainPanelResourceId, resource, resourceLength); - _vm->decodeBGImage(resource, resourceLength, &_mainPanel.image, - &_mainPanel.imageLength, &_mainPanel.imageWidth, &_mainPanel.imageHeight); - - free(resource); + _vm->_resource->loadResource(_interfaceContext, _vm->getResourceDescription()->mainPanelResourceId, resourceData); + _vm->decodeBGImage(resourceData, _mainPanel.image, &_mainPanel.imageWidth, &_mainPanel.imageHeight); // Converse panel _conversePanel.buttons = _vm->getDisplayInfo().conversePanelButtons; _conversePanel.buttonsCount = _vm->getDisplayInfo().conversePanelButtonsCount; - _vm->_resource->loadResource(_interfaceContext, _vm->getResourceDescription()->conversePanelResourceId, resource, resourceLength); - _vm->decodeBGImage(resource, resourceLength, &_conversePanel.image, - &_conversePanel.imageLength, &_conversePanel.imageWidth, &_conversePanel.imageHeight); - free(resource); + _vm->_resource->loadResource(_interfaceContext, _vm->getResourceDescription()->conversePanelResourceId, resourceData); + _vm->decodeBGImage(resourceData, _conversePanel.image, &_conversePanel.imageWidth, &_conversePanel.imageHeight); // Option panel if (!_vm->_script->isNonInteractiveDemo()) { _optionPanel.buttons = _vm->getDisplayInfo().optionPanelButtons; _optionPanel.buttonsCount = _vm->getDisplayInfo().optionPanelButtonsCount; - _vm->_resource->loadResource(_interfaceContext, _vm->getResourceDescription()->optionPanelResourceId, resource, resourceLength); - _vm->decodeBGImage(resource, resourceLength, &_optionPanel.image, - &_optionPanel.imageLength, &_optionPanel.imageWidth, &_optionPanel.imageHeight); - free(resource); + _vm->_resource->loadResource(_interfaceContext, _vm->getResourceDescription()->optionPanelResourceId, resourceData); + _vm->decodeBGImage(resourceData, _optionPanel.image, &_optionPanel.imageWidth, &_optionPanel.imageHeight); } else { _optionPanel.buttons = NULL; _optionPanel.buttonsCount = 0; - _optionPanel.sprites.spriteCount = 0; + _optionPanel.sprites.clear(); } #ifdef ENABLE_IHNM @@ -206,10 +198,8 @@ Interface::Interface(SagaEngine *vm) : _vm(vm) { _quitPanel.buttons = _vm->getDisplayInfo().quitPanelButtons; _quitPanel.buttonsCount = _vm->getDisplayInfo().quitPanelButtonsCount; - _vm->_resource->loadResource(_interfaceContext, _vm->getResourceDescription()->warningPanelResourceId, resource, resourceLength); - _vm->decodeBGImage(resource, resourceLength, &_quitPanel.image, - &_quitPanel.imageLength, &_quitPanel.imageWidth, &_quitPanel.imageHeight); - free(resource); + _vm->_resource->loadResource(_interfaceContext, _vm->getResourceDescription()->warningPanelResourceId, resourceData); + _vm->decodeBGImage(resourceData, _quitPanel.image, &_quitPanel.imageWidth, &_quitPanel.imageHeight); } // Save panel @@ -217,10 +207,8 @@ Interface::Interface(SagaEngine *vm) : _vm(vm) { _savePanel.buttons = _vm->getDisplayInfo().savePanelButtons; _savePanel.buttonsCount = _vm->getDisplayInfo().savePanelButtonsCount; - _vm->_resource->loadResource(_interfaceContext, _vm->getResourceDescription()->warningPanelResourceId, resource, resourceLength); - _vm->decodeBGImage(resource, resourceLength, &_savePanel.image, - &_savePanel.imageLength, &_savePanel.imageWidth, &_savePanel.imageHeight); - free(resource); + _vm->_resource->loadResource(_interfaceContext, _vm->getResourceDescription()->warningPanelResourceId, resourceData); + _vm->decodeBGImage(resourceData, _savePanel.image, &_savePanel.imageWidth, &_savePanel.imageHeight); } // Load panel @@ -228,10 +216,8 @@ Interface::Interface(SagaEngine *vm) : _vm(vm) { _loadPanel.buttons = _vm->getDisplayInfo().loadPanelButtons; _loadPanel.buttonsCount = _vm->getDisplayInfo().loadPanelButtonsCount; - _vm->_resource->loadResource(_interfaceContext, _vm->getResourceDescription()->warningPanelResourceId, resource, resourceLength); - _vm->decodeBGImage(resource, resourceLength, &_loadPanel.image, - &_loadPanel.imageLength, &_loadPanel.imageWidth, &_loadPanel.imageHeight); - free(resource); + _vm->_resource->loadResource(_interfaceContext, _vm->getResourceDescription()->warningPanelResourceId, resourceData); + _vm->decodeBGImage(resourceData, _loadPanel.image, &_loadPanel.imageWidth, &_loadPanel.imageHeight); } #endif @@ -323,16 +309,12 @@ Interface::Interface(SagaEngine *vm) : _vm(vm) { _inventoryStart = 0; _inventoryEnd = 0; _inventoryBox = 0; - _inventorySize = ITE_INVENTORY_SIZE; _saveReminderState = 0; _optionSaveFileTop = 0; _optionSaveFileTitleNumber = 0; - _inventory = (uint16 *)calloc(_inventorySize, sizeof(uint16)); - if (_inventory == NULL) { - error("Interface::Interface(): not enough memory"); - } + _inventory.resize(ITE_INVENTORY_SIZE); _textInput = false; _statusTextInput = false; @@ -345,25 +327,6 @@ Interface::Interface(SagaEngine *vm) : _vm(vm) { } Interface::~Interface() { - free(_inventory); - - free(_mainPanel.image); - free(_conversePanel.image); - free(_optionPanel.image); - free(_quitPanel.image); - free(_loadPanel.image); - free(_savePanel.image); - - _mainPanel.sprites.freeMem(); - _conversePanel.sprites.freeMem(); - _optionPanel.sprites.freeMem(); - _quitPanel.sprites.freeMem(); - _loadPanel.sprites.freeMem(); - _savePanel.sprites.freeMem(); - _protectPanel.sprites.freeMem(); - - _defPortraits.freeMem(); - _scenePortraits.freeMem(); } void Interface::saveReminderCallback(void *refCon) { @@ -768,7 +731,7 @@ void Interface::setStatusText(const char *text, int statusColor) { } void Interface::loadScenePortraits(int resourceId) { - _scenePortraits.freeMem(); + _scenePortraits.clear(); _vm->_sprite->loadList(resourceId, _scenePortraits); } @@ -817,7 +780,7 @@ void Interface::draw() { if (_panelMode == kPanelMain || _panelMode == kPanelMap || (_panelMode == kPanelNull && _vm->isIHNMDemo())) { _mainPanel.getRect(rect); - _vm->_gfx->drawRegion(rect, _mainPanel.image); + _vm->_gfx->drawRegion(rect, _mainPanel.image.getBuffer()); for (int i = 0; i < kVerbTypeIdsMax; i++) { if (_verbTypeToPanelButton[i] != NULL) { @@ -826,7 +789,7 @@ void Interface::draw() { } } else if (_panelMode == kPanelConverse) { _conversePanel.getRect(rect); - _vm->_gfx->drawRegion(rect, _conversePanel.image); + _vm->_gfx->drawRegion(rect, _conversePanel.image.getBuffer()); converseDisplayTextLines(); } @@ -847,7 +810,7 @@ void Interface::draw() { // can tell this is what the original engine does. And it keeps // ITE from crashing when entering the Elk King's court. - if (_rightPortrait >= _scenePortraits.spriteCount) + if (_rightPortrait >= (int)_scenePortraits.size()) _rightPortrait = 0; _vm->_sprite->draw(_scenePortraits, _rightPortrait, rightPortraitPoint, 256); @@ -960,7 +923,7 @@ void Interface::drawOption() { int spritenum = 0; _optionPanel.getRect(rect); - _vm->_gfx->drawRegion(rect, _optionPanel.image); + _vm->_gfx->drawRegion(rect, _optionPanel.image.getBuffer()); for (int i = 0; i < _optionPanel.buttonsCount; i++) { panelButton = &_optionPanel.buttons[i]; @@ -1037,7 +1000,7 @@ void Interface::drawQuit() { if (_vm->getGameId() == GID_ITE) drawButtonBox(rect, kButton, false); else - _vm->_gfx->drawRegion(rect, _quitPanel.image); + _vm->_gfx->drawRegion(rect, _quitPanel.image.getBuffer()); for (i = 0; i < _quitPanel.buttonsCount; i++) { panelButton = &_quitPanel.buttons[i]; @@ -1103,7 +1066,7 @@ void Interface::drawLoad() { if (_vm->getGameId() == GID_ITE) drawButtonBox(rect, kButton, false); else - _vm->_gfx->drawRegion(rect, _loadPanel.image); + _vm->_gfx->drawRegion(rect, _loadPanel.image.getBuffer()); for (i = 0; i < _loadPanel.buttonsCount; i++) { panelButton = &_loadPanel.buttons[i]; @@ -1323,7 +1286,7 @@ void Interface::drawSave() { if (_vm->getGameId() == GID_ITE) drawButtonBox(rect, kButton, false); else - _vm->_gfx->drawRegion(rect, _savePanel.image); + _vm->_gfx->drawRegion(rect, _savePanel.image.getBuffer()); for (i = 0; i < _savePanel.buttonsCount; i++) { panelButton = &_savePanel.buttons[i]; @@ -1587,7 +1550,7 @@ void Interface::handleChapterSelectionClick(const Point& mousePoint) { event.param4 = obj; // Object event.param5 = 0; // With Object event.param6 = obj; // Actor - _vm->_events->queue(&event); + _vm->_events->queue(event); } } } @@ -2064,7 +2027,7 @@ void Interface::updateInventory(int pos) { } void Interface::addToInventory(int objectId) { - if (_inventoryCount >= _inventorySize) { + if (uint(_inventoryCount) >= _inventory.size()) { return; } @@ -2281,14 +2244,22 @@ void Interface::drawPanelButtonText(InterfacePanel *panel, PanelButton *panelBut } break; case kTextMusic: - if (_vm->_musicVolume) + if (_vm->_musicVolume) { textId = kText10Percent + _vm->_musicVolume / 25 - 1; + if (textId > kTextMax) { + textId = kTextMax; + } + } else textId = kTextOff; break; case kTextSound: - if (_vm->_soundVolume) + if (_vm->_soundVolume) { textId = kText10Percent + _vm->_soundVolume / 25 - 1; + if (textId > kTextMax) { + textId = kTextMax; + } + } else textId = kTextOff; break; @@ -2423,18 +2394,9 @@ void Interface::drawVerbPanelText(PanelButton *panelButton, KnownColor textKnown // Converse stuff -void Interface::converseInit() { - for (int i = 0; i < CONVERSE_MAX_TEXTS; i++) - _converseText[i].text = NULL; - converseClear(); -} - void Interface::converseClear() { for (int i = 0; i < CONVERSE_MAX_TEXTS; i++) { - if (_converseText[i].text != NULL) { - free(_converseText[i].text); - _converseText[i].text = NULL; - } + _converseText[i].text.clear(); _converseText[i].stringNum = -1; _converseText[i].replyId = 0; _converseText[i].replyFlags = 0; @@ -2480,8 +2442,8 @@ bool Interface::converseAddText(const char *text, int strId, int replyId, byte r return true; } - _converseText[_converseTextCount].text = (char *)malloc(i + 1); - strncpy(_converseText[_converseTextCount].text, _converseWorkString, i); + _converseText[_converseTextCount].text.resize(i + 1); + strncpy(&_converseText[_converseTextCount].text.front(), _converseWorkString, i); _converseText[_converseTextCount].strId = strId; _converseText[_converseTextCount].text[i] = 0; @@ -2591,7 +2553,7 @@ void Interface::converseDisplayTextLines() { rect.left += 8; _vm->_gfx->drawRect(rect, backgnd); - str = _converseText[relPos].text; + str = &_converseText[relPos].text.front(); if (_converseText[relPos].textNum == 0) { // first entry textPoint.x = rect.left - 6; @@ -2725,10 +2687,9 @@ void Interface::loadState(Common::InSaveFile *in) { void Interface::mapPanelShow() { int i; - byte *resource; - size_t resourceLength, imageLength; + ByteArray resourceData; Rect rect; - byte *image; + ByteArray image; int imageWidth, imageHeight; const byte *pal; PalEntry cPal[PAL_ENTRIES]; @@ -2737,9 +2698,8 @@ void Interface::mapPanelShow() { rect.left = rect.top = 0; - _vm->_resource->loadResource(_interfaceContext, - _vm->_resource->convertResourceId(RID_ITE_TYCHO_MAP), resource, resourceLength); - if (resourceLength == 0) { + _vm->_resource->loadResource(_interfaceContext, _vm->_resource->convertResourceId(RID_ITE_TYCHO_MAP), resourceData); + if (resourceData.empty()) { error("Interface::mapPanelShow() unable to load Tycho map resource"); } @@ -2753,8 +2713,8 @@ void Interface::mapPanelShow() { _vm->_render->setFlag(RF_MAP); - _vm->decodeBGImage(resource, resourceLength, &image, &imageLength, &imageWidth, &imageHeight); - pal = _vm->getImagePal(resource, resourceLength); + _vm->decodeBGImage(resourceData, image, &imageWidth, &imageHeight); + pal = _vm->getImagePal(resourceData); for (i = 0; i < PAL_ENTRIES; i++) { cPal[i].red = *pal++; @@ -2765,7 +2725,7 @@ void Interface::mapPanelShow() { rect.setWidth(imageWidth); rect.setHeight(imageHeight); - _vm->_gfx->drawRegion(rect, image); + _vm->_gfx->drawRegion(rect, image.getBuffer()); // Evil Evil for (i = 0; i < 6 ; i++) { @@ -2774,8 +2734,6 @@ void Interface::mapPanelShow() { _vm->_system->delayMillis(5); } - free(resource); - free(image); setSaveReminderState(false); @@ -2832,10 +2790,9 @@ void Interface::keyBoss() { _vm->_music->pause(); int i; - byte *resource; - size_t resourceLength, imageLength; + ByteArray resourceData; Rect rect; - byte *image; + ByteArray image; int imageWidth, imageHeight; const byte *pal; PalEntry cPal[PAL_ENTRIES]; @@ -2844,20 +2801,20 @@ void Interface::keyBoss() { rect.left = rect.top = 0; - _vm->_resource->loadResource(_interfaceContext, RID_IHNM_BOSS_SCREEN, resource, resourceLength); - if (resourceLength == 0) { + _vm->_resource->loadResource(_interfaceContext, RID_IHNM_BOSS_SCREEN, resourceData); + if (resourceData.empty()) { error("Interface::bossKey() unable to load Boss image resource"); } _bossMode = _panelMode; setMode(kPanelBoss); - _vm->decodeBGImage(resource, resourceLength, &image, &imageLength, &imageWidth, &imageHeight); + _vm->decodeBGImage(resourceData, image, &imageWidth, &imageHeight); rect.setWidth(imageWidth); rect.setHeight(imageHeight); _vm->_gfx->getCurrentPal(_mapSavedPal); - pal = _vm->getImagePal(resource, resourceLength); + pal = _vm->getImagePal(resourceData); cPal[0].red = 0; cPal[0].green = 0; @@ -2869,12 +2826,9 @@ void Interface::keyBoss() { cPal[i].blue = 128; } - _vm->_gfx->drawRegion(rect, image); + _vm->_gfx->drawRegion(rect, image.getBuffer()); _vm->_gfx->setPalette(cPal); - - free(resource); - free(image); } diff --git a/engines/saga/interface.h b/engines/saga/interface.h index 0fbe5bef20..b9a96653a7 100644 --- a/engines/saga/interface.h +++ b/engines/saga/interface.h @@ -94,8 +94,7 @@ enum FadeModes { struct InterfacePanel { int x; int y; - byte *image; - size_t imageLength; + ByteArray image; int imageWidth; int imageHeight; @@ -106,8 +105,6 @@ struct InterfacePanel { InterfacePanel() { x = y = 0; - image = NULL; - imageLength = 0; imageWidth = imageHeight = 0; currentButton = NULL; buttonsCount = 0; @@ -164,7 +161,7 @@ struct InterfacePanel { }; struct Converse { - char *text; + Common::Array<char> text; int strId; int stringNum; int textNum; @@ -356,7 +353,6 @@ private: void processStatusTextInput(Common::KeyState keystate); public: - void converseInit(); void converseClear(); bool converseAddText(const char *text, int strId, int replyId, byte replyFlags, int replyBit); void converseDisplayText(); @@ -431,8 +427,7 @@ private: Point _lastMousePoint; - uint16 *_inventory; - int _inventorySize; + Common::Array<uint16> _inventory; int _inventoryStart; int _inventoryEnd; int _inventoryPos; diff --git a/engines/saga/introproc_ihnm.cpp b/engines/saga/introproc_ihnm.cpp index e149753dfd..2053c7158f 100644 --- a/engines/saga/introproc_ihnm.cpp +++ b/engines/saga/introproc_ihnm.cpp @@ -83,19 +83,18 @@ int Scene::IHNMStartProc() { } _vm->_music->setVolume(0, 1000); - _vm->_anim->freeCutawayList(); + _vm->_anim->clearCutawayList(); // Queue first scene firstScene.loadFlag = kLoadBySceneNumber; firstScene.sceneDescriptor = -1; - firstScene.sceneDescription = NULL; firstScene.sceneSkipTarget = false; firstScene.sceneProc = NULL; firstScene.transitionType = kTransitionFade; firstScene.actorsEntrance = 0; firstScene.chapter = -1; - _vm->_scene->queueScene(&firstScene); + _vm->_scene->queueScene(firstScene); return SUCCESS; } @@ -114,7 +113,7 @@ int Scene::IHNMCreditsProc() { } _vm->_music->setVolume(0, 1000); - _vm->_anim->freeCutawayList(); + _vm->_anim->clearCutawayList(); return SUCCESS; } @@ -122,8 +121,7 @@ int Scene::IHNMCreditsProc() { void Scene::IHNMLoadCutaways() { ResourceContext *resourceContext; //ResourceContext *soundContext; - byte *resourcePointer; - size_t resourceLength; + ByteArray resourceData; resourceContext = _vm->_resource->getContext(GAME_RESOURCEFILE); if (resourceContext == NULL) { @@ -131,18 +129,16 @@ void Scene::IHNMLoadCutaways() { } if (!_vm->isIHNMDemo()) - _vm->_resource->loadResource(resourceContext, RID_IHNM_INTRO_CUTAWAYS, resourcePointer, resourceLength); + _vm->_resource->loadResource(resourceContext, RID_IHNM_INTRO_CUTAWAYS, resourceData); else - _vm->_resource->loadResource(resourceContext, RID_IHNMDEMO_INTRO_CUTAWAYS, resourcePointer, resourceLength); + _vm->_resource->loadResource(resourceContext, RID_IHNMDEMO_INTRO_CUTAWAYS, resourceData); - if (resourceLength == 0) { + if (resourceData.empty()) { error("Scene::IHNMStartProc() Can't load cutaway list"); } // Load the cutaways for the title screens - _vm->_anim->loadCutawayList(resourcePointer, resourceLength); - - free(resourcePointer); + _vm->_anim->loadCutawayList(resourceData); } bool Scene::checkKey() { diff --git a/engines/saga/introproc_ite.cpp b/engines/saga/introproc_ite.cpp index 83fdadf59e..ae7dedefa5 100644 --- a/engines/saga/introproc_ite.cpp +++ b/engines/saga/introproc_ite.cpp @@ -61,15 +61,15 @@ using Common::IT_ITA; #define MUSIC_2 10 LoadSceneParams ITE_IntroList[] = { - {RID_ITE_INTRO_ANIM_SCENE, kLoadByResourceId, NULL, Scene::SC_ITEIntroAnimProc, false, kTransitionNoFade, 0, NO_CHAPTER_CHANGE}, - {RID_ITE_CAVE_SCENE_1, kLoadByResourceId, NULL, Scene::SC_ITEIntroCave1Proc, false, kTransitionFade, 0, NO_CHAPTER_CHANGE}, - {RID_ITE_CAVE_SCENE_2, kLoadByResourceId, NULL, Scene::SC_ITEIntroCave2Proc, false, kTransitionNoFade, 0, NO_CHAPTER_CHANGE}, - {RID_ITE_CAVE_SCENE_3, kLoadByResourceId, NULL, Scene::SC_ITEIntroCave3Proc, false, kTransitionNoFade, 0, NO_CHAPTER_CHANGE}, - {RID_ITE_CAVE_SCENE_4, kLoadByResourceId, NULL, Scene::SC_ITEIntroCave4Proc, false, kTransitionNoFade, 0, NO_CHAPTER_CHANGE}, - {RID_ITE_VALLEY_SCENE, kLoadByResourceId, NULL, Scene::SC_ITEIntroValleyProc, false, kTransitionFade, 0, NO_CHAPTER_CHANGE}, - {RID_ITE_TREEHOUSE_SCENE, kLoadByResourceId, NULL, Scene::SC_ITEIntroTreeHouseProc, false, kTransitionNoFade, 0, NO_CHAPTER_CHANGE}, - {RID_ITE_FAIREPATH_SCENE, kLoadByResourceId, NULL, Scene::SC_ITEIntroFairePathProc, false, kTransitionNoFade, 0, NO_CHAPTER_CHANGE}, - {RID_ITE_FAIRETENT_SCENE, kLoadByResourceId, NULL, Scene::SC_ITEIntroFaireTentProc, false, kTransitionNoFade, 0, NO_CHAPTER_CHANGE} + {RID_ITE_INTRO_ANIM_SCENE, kLoadByResourceId, Scene::SC_ITEIntroAnimProc, false, kTransitionNoFade, 0, NO_CHAPTER_CHANGE}, + {RID_ITE_CAVE_SCENE_1, kLoadByResourceId, Scene::SC_ITEIntroCave1Proc, false, kTransitionFade, 0, NO_CHAPTER_CHANGE}, + {RID_ITE_CAVE_SCENE_2, kLoadByResourceId, Scene::SC_ITEIntroCave2Proc, false, kTransitionNoFade, 0, NO_CHAPTER_CHANGE}, + {RID_ITE_CAVE_SCENE_3, kLoadByResourceId, Scene::SC_ITEIntroCave3Proc, false, kTransitionNoFade, 0, NO_CHAPTER_CHANGE}, + {RID_ITE_CAVE_SCENE_4, kLoadByResourceId, Scene::SC_ITEIntroCave4Proc, false, kTransitionNoFade, 0, NO_CHAPTER_CHANGE}, + {RID_ITE_VALLEY_SCENE, kLoadByResourceId, Scene::SC_ITEIntroValleyProc, false, kTransitionFade, 0, NO_CHAPTER_CHANGE}, + {RID_ITE_TREEHOUSE_SCENE, kLoadByResourceId, Scene::SC_ITEIntroTreeHouseProc, false, kTransitionNoFade, 0, NO_CHAPTER_CHANGE}, + {RID_ITE_FAIREPATH_SCENE, kLoadByResourceId, Scene::SC_ITEIntroFairePathProc, false, kTransitionNoFade, 0, NO_CHAPTER_CHANGE}, + {RID_ITE_FAIRETENT_SCENE, kLoadByResourceId, Scene::SC_ITEIntroFaireTentProc, false, kTransitionNoFade, 0, NO_CHAPTER_CHANGE} }; int Scene::ITEStartProc() { @@ -84,25 +84,24 @@ int Scene::ITEStartProc() { for (i = 0; i < scenesCount; i++) { tempScene = ITE_IntroList[i]; tempScene.sceneDescriptor = _vm->_resource->convertResourceId(tempScene.sceneDescriptor); - _vm->_scene->queueScene(&tempScene); + _vm->_scene->queueScene(tempScene); } firstScene.loadFlag = kLoadBySceneNumber; firstScene.sceneDescriptor = _vm->getStartSceneNumber(); - firstScene.sceneDescription = NULL; firstScene.sceneSkipTarget = true; firstScene.sceneProc = NULL; firstScene.transitionType = kTransitionFade; firstScene.actorsEntrance = 0; firstScene.chapter = -1; - _vm->_scene->queueScene(&firstScene); + _vm->_scene->queueScene(firstScene); return SUCCESS; } -Event *Scene::ITEQueueDialogue(Event *q_event, int n_dialogues, const IntroDialogue dialogue[]) { +EventColumns *Scene::ITEQueueDialogue(EventColumns *eventColumns, int n_dialogues, const IntroDialogue dialogue[]) { TextListEntry textEntry; TextListEntry *entry; Event event; @@ -136,7 +135,7 @@ Event *Scene::ITEQueueDialogue(Event *q_event, int n_dialogues, const IntroDialo event.op = kEventDisplay; event.data = entry; event.time = (i == 0) ? 0 : VOICE_PAD; - q_event = _vm->_events->chain(q_event, &event); + eventColumns = _vm->_events->chain(eventColumns, event); // Play voice event.type = kEvTOneshot; @@ -144,7 +143,7 @@ Event *Scene::ITEQueueDialogue(Event *q_event, int n_dialogues, const IntroDialo event.op = kEventPlay; event.param = dialogue[i].i_voice_rn; event.time = 0; - q_event = _vm->_events->chain(q_event, &event); + _vm->_events->chain(eventColumns, event); voice_len = _vm->_sndRes->getVoiceLength(dialogue[i].i_voice_rn); if (voice_len < 0) { @@ -157,10 +156,10 @@ Event *Scene::ITEQueueDialogue(Event *q_event, int n_dialogues, const IntroDialo event.op = kEventRemove; event.data = entry; event.time = voice_len; - q_event = _vm->_events->chain(q_event, &event); + _vm->_events->chain(eventColumns, event); } - return q_event; + return eventColumns; } enum { @@ -180,7 +179,7 @@ enum { // Queue a page of credits text. The original interpreter did word-wrapping // automatically. We currently don't. -Event *Scene::ITEQueueCredits(int delta_time, int duration, int n_credits, const IntroCredit credits[]) { +EventColumns *Scene::ITEQueueCredits(int delta_time, int duration, int n_credits, const IntroCredit credits[]) { int game; Common::Language lang; @@ -241,7 +240,7 @@ Event *Scene::ITEQueueCredits(int delta_time, int duration, int n_credits, const TextListEntry textEntry; TextListEntry *entry; Event event; - Event *q_event = NULL; + EventColumns *eventColumns = NULL; textEntry.knownColor = kKnownColorSubtitleTextColor; textEntry.effectKnownColor = kKnownColorTransparent; @@ -283,7 +282,7 @@ Event *Scene::ITEQueueCredits(int delta_time, int duration, int n_credits, const event.op = kEventDisplay; event.data = entry; event.time = delta_time; - q_event = _vm->_events->queue(&event); + eventColumns = _vm->_events->queue(event); // Remove text event.type = kEvTOneshot; @@ -291,12 +290,12 @@ Event *Scene::ITEQueueCredits(int delta_time, int duration, int n_credits, const event.op = kEventRemove; event.data = entry; event.time = duration; - q_event = _vm->_events->chain(q_event, &event); + _vm->_events->chain(eventColumns, event); y += (_vm->_font->getHeight(font) + line_spacing); } - return q_event; + return eventColumns; } int Scene::SC_ITEIntroAnimProc(int param, void *refCon) { @@ -306,7 +305,7 @@ int Scene::SC_ITEIntroAnimProc(int param, void *refCon) { // Handles the introductory Dreamer's Guild / NWC logo animation scene. int Scene::ITEIntroAnimProc(int param) { Event event; - Event *q_event; + EventColumns *eventColumns; switch (param) { case SCENE_BEGIN:{ @@ -317,7 +316,7 @@ int Scene::ITEIntroAnimProc(int param) { event.op = kEventDisplay; event.param = kEvPSetPalette; event.time = 0; - q_event = _vm->_events->queue(&event); + eventColumns = _vm->_events->queue(event); debug(3, "Intro animation procedure started."); debug(3, "Linking animation resources..."); @@ -355,7 +354,7 @@ int Scene::ITEIntroAnimProc(int param) { event.op = kEventPlay; event.param = 0; event.time = 0; - q_event = _vm->_events->chain(q_event, &event); + _vm->_events->chain(eventColumns, event); // Queue intro music playback event.type = kEvTOneshot; @@ -364,7 +363,7 @@ int Scene::ITEIntroAnimProc(int param) { event.param2 = MUSIC_LOOP; event.op = kEventPlay; event.time = 0; - q_event = _vm->_events->chain(q_event, &event); + _vm->_events->chain(eventColumns, event); } break; case SCENE_END: @@ -384,7 +383,7 @@ int Scene::SC_ITEIntroCave1Proc(int param, void *refCon) { // Handles first introductory cave painting scene int Scene::ITEIntroCave1Proc(int param) { Event event; - Event *q_event; + EventColumns *eventColumns; int lang = 0; if (_vm->getLanguage() == Common::DE_DEU) @@ -468,24 +467,24 @@ int Scene::ITEIntroCave1Proc(int param) { event.code = kPalAnimEvent; event.op = kEventCycleStart; event.time = 0; - q_event = _vm->_events->queue(&event); + eventColumns = _vm->_events->queue(event); // Queue narrator dialogue list - q_event = ITEQueueDialogue(q_event, n_dialogues, dialogue[lang]); + ITEQueueDialogue(eventColumns, n_dialogues, dialogue[lang]); // End scene after last dialogue over event.type = kEvTOneshot; event.code = kSceneEvent; event.op = kEventEnd; event.time = VOICE_PAD; - q_event = _vm->_events->chain(q_event, &event); + _vm->_events->chain(eventColumns, event); break; case SCENE_END: break; default: - warning("Illegal scene procedure paramater"); + warning("Illegal scene procedure parameter"); break; } @@ -499,7 +498,7 @@ int Scene::SC_ITEIntroCave2Proc(int param, void *refCon) { // Handles second introductory cave painting scene int Scene::ITEIntroCave2Proc(int param) { Event event; - Event *q_event; + EventColumns *eventColumns; int lang = 0; if (_vm->getLanguage() == Common::DE_DEU) @@ -566,30 +565,30 @@ int Scene::ITEIntroCave2Proc(int param) { event.op = kEventDissolve; event.time = 0; event.duration = DISSOLVE_DURATION; - q_event = _vm->_events->queue(&event); + eventColumns = _vm->_events->queue(event); // Begin palette cycling animation for candles event.type = kEvTOneshot; event.code = kPalAnimEvent; event.op = kEventCycleStart; event.time = 0; - q_event = _vm->_events->chain(q_event, &event); + _vm->_events->chain(eventColumns, event); // Queue narrator dialogue list - q_event = ITEQueueDialogue(q_event, n_dialogues, dialogue[lang]); + ITEQueueDialogue(eventColumns, n_dialogues, dialogue[lang]); // End scene after last dialogue over event.type = kEvTOneshot; event.code = kSceneEvent; event.op = kEventEnd; event.time = VOICE_PAD; - q_event = _vm->_events->chain(q_event, &event); + _vm->_events->chain(eventColumns, event); break; case SCENE_END: break; default: - warning("Illegal scene procedure paramater"); + warning("Illegal scene procedure parameter"); break; } @@ -603,7 +602,7 @@ int Scene::SC_ITEIntroCave3Proc(int param, void *refCon) { // Handles third introductory cave painting scene int Scene::ITEIntroCave3Proc(int param) { Event event; - Event *q_event; + EventColumns *eventColumns; int lang = 0; if (_vm->getLanguage() == Common::DE_DEU) @@ -671,30 +670,30 @@ int Scene::ITEIntroCave3Proc(int param) { event.op = kEventDissolve; event.time = 0; event.duration = DISSOLVE_DURATION; - q_event = _vm->_events->queue(&event); + eventColumns = _vm->_events->queue(event); // Begin palette cycling animation for candles event.type = kEvTOneshot; event.code = kPalAnimEvent; event.op = kEventCycleStart; event.time = 0; - q_event = _vm->_events->chain(q_event, &event); + _vm->_events->chain(eventColumns, event); // Queue narrator dialogue list - q_event = ITEQueueDialogue(q_event, n_dialogues, dialogue[lang]); + ITEQueueDialogue(eventColumns, n_dialogues, dialogue[lang]); // End scene after last dialogue over event.type = kEvTOneshot; event.code = kSceneEvent; event.op = kEventEnd; event.time = VOICE_PAD; - q_event = _vm->_events->chain(q_event, &event); + _vm->_events->chain(eventColumns, event); break; case SCENE_END: break; default: - warning("Illegal scene procedure paramater"); + warning("Illegal scene procedure parameter"); break; } @@ -708,7 +707,7 @@ int Scene::SC_ITEIntroCave4Proc(int param, void *refCon) { // Handles fourth introductory cave painting scene int Scene::ITEIntroCave4Proc(int param) { Event event; - Event *q_event; + EventColumns *eventColumns; int lang = 0; if (_vm->getLanguage() == Common::DE_DEU) @@ -789,30 +788,30 @@ int Scene::ITEIntroCave4Proc(int param) { event.op = kEventDissolve; event.time = 0; event.duration = DISSOLVE_DURATION; - q_event = _vm->_events->queue(&event); + eventColumns = _vm->_events->queue(event); // Begin palette cycling animation for candles event.type = kEvTOneshot; event.code = kPalAnimEvent; event.op = kEventCycleStart; event.time = 0; - q_event = _vm->_events->chain(q_event, &event); + _vm->_events->chain(eventColumns, event); // Queue narrator dialogue list - q_event = ITEQueueDialogue(q_event, n_dialogues, dialogue[lang]); + ITEQueueDialogue(eventColumns, n_dialogues, dialogue[lang]); // End scene after last dialogue over event.type = kEvTOneshot; event.code = kSceneEvent; event.op = kEventEnd; event.time = VOICE_PAD; - q_event = _vm->_events->chain(q_event, &event); + _vm->_events->chain(eventColumns, event); break; case SCENE_END: break; default: - warning("Illegal scene procedure paramater"); + warning("Illegal scene procedure parameter"); break; } @@ -826,7 +825,7 @@ int Scene::SC_ITEIntroValleyProc(int param, void *refCon) { // Handles intro title scene (valley overlook) int Scene::ITEIntroValleyProc(int param) { Event event; - Event *q_event; + EventColumns *eventColumns; static const IntroCredit credits[] = { {EN_ANY, kITEAny, kCHeader, "Producer"}, @@ -856,7 +855,7 @@ int Scene::ITEIntroValleyProc(int param) { event.op = kEventPlay; event.param = 0; event.time = 0; - q_event = _vm->_events->queue(&event); + eventColumns = _vm->_events->queue(event); // Begin ITE title theme music _vm->_music->stop(); @@ -867,7 +866,7 @@ int Scene::ITEIntroValleyProc(int param) { event.param2 = MUSIC_NORMAL; event.op = kEventPlay; event.time = 0; - q_event = _vm->_events->chain(q_event, &event); + _vm->_events->chain(eventColumns, event); // Pause animation before logo event.type = kEvTOneshot; @@ -875,7 +874,7 @@ int Scene::ITEIntroValleyProc(int param) { event.op = kEventStop; event.param = 0; event.time = 3000; - q_event = _vm->_events->chain(q_event, &event); + _vm->_events->chain(eventColumns, event); // Display logo event.type = kEvTContinuous; @@ -883,7 +882,7 @@ int Scene::ITEIntroValleyProc(int param) { event.op = kEventDissolveBGMask; event.time = 0; event.duration = LOGO_DISSOLVE_DURATION; - q_event = _vm->_events->chain(q_event, &event); + _vm->_events->chain(eventColumns, event); // Remove logo event.type = kEvTContinuous; @@ -891,7 +890,7 @@ int Scene::ITEIntroValleyProc(int param) { event.op = kEventDissolve; event.time = 3000; event.duration = LOGO_DISSOLVE_DURATION; - q_event = _vm->_events->chain(q_event, &event); + _vm->_events->chain(eventColumns, event); // Unpause animation before logo event.type = kEvTOneshot; @@ -899,17 +898,17 @@ int Scene::ITEIntroValleyProc(int param) { event.op = kEventPlay; event.time = 0; event.param = 0; - q_event = _vm->_events->chain(q_event, &event); + _vm->_events->chain(eventColumns, event); // Queue game credits list - q_event = ITEQueueCredits(9000, CREDIT_DURATION1, n_credits, credits); + eventColumns = ITEQueueCredits(9000, CREDIT_DURATION1, n_credits, credits); // End scene after credit display event.type = kEvTOneshot; event.code = kSceneEvent; event.op = kEventEnd; event.time = 1000; - q_event = _vm->_events->chain(q_event, &event); + _vm->_events->chain(eventColumns, event); break; case SCENE_END: @@ -929,7 +928,7 @@ int Scene::SC_ITEIntroTreeHouseProc(int param, void *refCon) { // Handles second intro credit screen (treehouse view) int Scene::ITEIntroTreeHouseProc(int param) { Event event; - Event *q_event; + EventColumns *eventColumns; static const IntroCredit credits1[] = { {EN_ANY, kITEAny, kCHeader, "Game Design"}, @@ -981,7 +980,7 @@ int Scene::ITEIntroTreeHouseProc(int param) { event.op = kEventDissolve; event.time = 0; event.duration = DISSOLVE_DURATION; - q_event = _vm->_events->queue(&event); + eventColumns = _vm->_events->queue(event); if (_vm->_anim->hasAnimation(0)) { // Begin title screen background animation @@ -992,19 +991,19 @@ int Scene::ITEIntroTreeHouseProc(int param) { event.op = kEventPlay; event.param = 0; event.time = 0; - q_event = _vm->_events->chain(q_event, &event); + _vm->_events->chain(eventColumns, event); } // Queue game credits list - q_event = ITEQueueCredits(DISSOLVE_DURATION + 2000, CREDIT_DURATION1, n_credits1, credits1); - q_event = ITEQueueCredits(DISSOLVE_DURATION + 7000, CREDIT_DURATION1, n_credits2, credits2); + eventColumns = ITEQueueCredits(DISSOLVE_DURATION + 2000, CREDIT_DURATION1, n_credits1, credits1); + eventColumns = ITEQueueCredits(DISSOLVE_DURATION + 7000, CREDIT_DURATION1, n_credits2, credits2); // End scene after credit display event.type = kEvTOneshot; event.code = kSceneEvent; event.op = kEventEnd; event.time = 1000; - q_event = _vm->_events->chain(q_event, &event); + _vm->_events->chain(eventColumns, event); break; case SCENE_END: @@ -1024,7 +1023,7 @@ int Scene::SC_ITEIntroFairePathProc(int param, void *refCon) { // Handles third intro credit screen (path to puzzle tent) int Scene::ITEIntroFairePathProc(int param) { Event event; - Event *q_event; + EventColumns *eventColumns; static const IntroCredit credits1[] = { {EN_ANY, kITEAny, kCHeader, "Programming"}, @@ -1063,7 +1062,7 @@ int Scene::ITEIntroFairePathProc(int param) { event.op = kEventDissolve; event.time = 0; event.duration = DISSOLVE_DURATION; - q_event = _vm->_events->queue(&event); + eventColumns = _vm->_events->queue(event); // Begin title screen background animation _vm->_anim->setCycles(0, -1); @@ -1073,18 +1072,18 @@ int Scene::ITEIntroFairePathProc(int param) { event.op = kEventPlay; event.param = 0; event.time = 0; - q_event = _vm->_events->chain(q_event, &event); + _vm->_events->chain(eventColumns, event); // Queue game credits list - q_event = ITEQueueCredits(DISSOLVE_DURATION + 2000, CREDIT_DURATION1, n_credits1, credits1); - q_event = ITEQueueCredits(DISSOLVE_DURATION + 7000, CREDIT_DURATION1, n_credits2, credits2); + eventColumns = ITEQueueCredits(DISSOLVE_DURATION + 2000, CREDIT_DURATION1, n_credits1, credits1); + eventColumns = ITEQueueCredits(DISSOLVE_DURATION + 7000, CREDIT_DURATION1, n_credits2, credits2); // End scene after credit display event.type = kEvTOneshot; event.code = kSceneEvent; event.op = kEventEnd; event.time = 1000; - q_event = _vm->_events->chain(q_event, &event); + _vm->_events->chain(eventColumns, event); break; case SCENE_END: @@ -1104,8 +1103,7 @@ int Scene::SC_ITEIntroFaireTentProc(int param, void *refCon) { // Handles fourth intro credit screen (treehouse view) int Scene::ITEIntroFaireTentProc(int param) { Event event; - Event *q_event; - Event *q_event_start; + EventColumns *eventColumns; switch (param) { case SCENE_BEGIN: @@ -1116,14 +1114,14 @@ int Scene::ITEIntroFaireTentProc(int param) { event.op = kEventDissolve; event.time = 0; event.duration = DISSOLVE_DURATION; - q_event_start = _vm->_events->queue(&event); + eventColumns = _vm->_events->queue(event); // End scene after momentary pause event.type = kEvTOneshot; event.code = kSceneEvent; event.op = kEventEnd; event.time = 5000; - q_event = _vm->_events->chain(q_event_start, &event); + _vm->_events->chain(eventColumns, event); break; case SCENE_END: diff --git a/engines/saga/isomap.cpp b/engines/saga/isomap.cpp index f0ad9bbd5e..6450af268a 100644 --- a/engines/saga/isomap.cpp +++ b/engines/saga/isomap.cpp @@ -85,34 +85,40 @@ static const IsoMap::TilePoint hardDirTable[8] = { { 0, 1, 0, SAGA_STRAIGHT_HARD_COST}, }; -IsoMap::IsoMap(SagaEngine *vm) : _vm(vm) { - _tileData = NULL; - _tileDataLength = 0; +static const int16 directions[8][2] = { + { 16, 16}, + { 16, 0}, + { 16, -16}, + { 0, -16}, + { -16, -16}, + { -16, 0}, + { -16, 16}, + { 0, 16} +}; - _multiTableData = NULL; - _multiDataCount = 0; +IsoMap::IsoMap(SagaEngine *vm) : _vm(vm) { _viewScroll.x = (128 - 8) * 16; _viewScroll.x = (128 - 8) * 16 - 64; _viewDiff = 1; - } -void IsoMap::loadImages(const byte *resourcePointer, size_t resourceLength) { +void IsoMap::loadImages(const ByteArray &resourceData) { IsoTileData *tileData; uint16 i; size_t offsetDiff; - if (resourceLength == 0) { + if (resourceData.empty()) { error("IsoMap::loadImages wrong resourceLength"); } - MemoryReadStreamEndian readS(resourcePointer, resourceLength, _vm->isBigEndian()); + ByteArrayReadStreamEndian readS(resourceData, _vm->isBigEndian()); readS.readUint16(); // skip i = readS.readUint16(); i = i / SAGA_ISOTILEDATA_LEN; _tilesTable.resize(i); - + Common::Array<size_t> tempOffsets; + tempOffsets.resize(_tilesTable.size()); readS.seek(0); @@ -120,7 +126,7 @@ void IsoMap::loadImages(const byte *resourcePointer, size_t resourceLength) { tileData = &_tilesTable[i]; tileData->height = readS.readByte(); tileData->attributes = readS.readSByte(); - tileData->offset = readS.readUint16(); + tempOffsets[i] = readS.readUint16(); tileData->terrainMask = readS.readUint16(); tileData->FGDBGDAttr = readS.readByte(); readS.readByte(); //skip @@ -128,26 +134,25 @@ void IsoMap::loadImages(const byte *resourcePointer, size_t resourceLength) { offsetDiff = readS.pos(); - _tileDataLength = resourceLength - offsetDiff; - _tileData = (byte*)malloc(_tileDataLength); - memcpy(_tileData, resourcePointer + offsetDiff, _tileDataLength); + _tileData.resize(resourceData.size() - offsetDiff); + memcpy(_tileData.getBuffer(), resourceData.getBuffer() + offsetDiff, _tileData.size()); for (i = 0; i < _tilesTable.size(); i++) { - _tilesTable[i].offset -= offsetDiff; + _tilesTable[i].tilePointer = _tileData.getBuffer() + tempOffsets[i] - offsetDiff; } } -void IsoMap::loadPlatforms(const byte * resourcePointer, size_t resourceLength) { +void IsoMap::loadPlatforms(const ByteArray &resourceData) { TilePlatformData *tilePlatformData; uint16 i, x, y; - if (resourceLength == 0) { + if (resourceData.empty()) { error("IsoMap::loadPlatforms wrong resourceLength"); } - MemoryReadStreamEndian readS(resourcePointer, resourceLength, _vm->isBigEndian()); + ByteArrayReadStreamEndian readS(resourceData, _vm->isBigEndian()); - i = resourceLength / SAGA_TILEPLATFORMDATA_LEN; + i = resourceData.size() / SAGA_TILEPLATFORMDATA_LEN; _tilePlatformList.resize(i); for (i = 0; i < _tilePlatformList.size(); i++) { @@ -166,14 +171,14 @@ void IsoMap::loadPlatforms(const byte * resourcePointer, size_t resourceLength) } -void IsoMap::loadMap(const byte * resourcePointer, size_t resourceLength) { +void IsoMap::loadMap(const ByteArray &resourceData) { uint16 x, y; - if (resourceLength != SAGA_TILEMAP_LEN) { - error("IsoMap::loadMap wrong resourceLength"); + if (resourceData.size() != SAGA_TILEMAP_LEN) { + error("IsoMap::loadMap wrong resource length %d", resourceData.size()); } - MemoryReadStreamEndian readS(resourcePointer, resourceLength, _vm->isBigEndian()); + ByteArrayReadStreamEndian readS(resourceData, _vm->isBigEndian()); _tileMap.edgeType = readS.readByte(); readS.readByte(); //skip @@ -185,16 +190,16 @@ void IsoMap::loadMap(const byte * resourcePointer, size_t resourceLength) { } -void IsoMap::loadMetaTiles(const byte * resourcePointer, size_t resourceLength) { +void IsoMap::loadMetaTiles(const ByteArray &resourceData) { MetaTileData *metaTileData; uint16 i, j; - if (resourceLength == 0) { + if (resourceData.empty()) { error("IsoMap::loadMetaTiles wrong resourceLength"); } - MemoryReadStreamEndian readS(resourcePointer, resourceLength, _vm->isBigEndian()); - i = resourceLength / SAGA_METATILEDATA_LEN; + ByteArrayReadStreamEndian readS(resourceData, _vm->isBigEndian()); + i = resourceData.size() / SAGA_METATILEDATA_LEN; _metaTileList.resize(i); for (i = 0; i < _metaTileList.size(); i++) { @@ -207,16 +212,16 @@ void IsoMap::loadMetaTiles(const byte * resourcePointer, size_t resourceLength) } } -void IsoMap::loadMulti(const byte * resourcePointer, size_t resourceLength) { +void IsoMap::loadMulti(const ByteArray &resourceData) { MultiTileEntryData *multiTileEntryData; uint16 i; int16 offsetDiff; - if (resourceLength < 2) { + if (resourceData.size() < 2) { error("IsoMap::loadMetaTiles wrong resourceLength"); } - MemoryReadStreamEndian readS(resourcePointer, resourceLength, _vm->isBigEndian()); + ByteArrayReadStreamEndian readS(resourceData, _vm->isBigEndian()); i = readS.readUint16(); _multiTable.resize(i); @@ -240,26 +245,21 @@ void IsoMap::loadMulti(const byte * resourcePointer, size_t resourceLength) { _multiTable[i].offset -= offsetDiff; } - _multiDataCount = (readS.size() - readS.pos()) / 2; + uint16 multiDataCount = (readS.size() - readS.pos()) / 2; - _multiTableData = (int16 *)malloc(_multiDataCount * sizeof(*_multiTableData)); - for (i = 0; i < _multiDataCount; i++) { + _multiTableData.resize(multiDataCount); + for (i = 0; i < _multiTableData.size(); i++) { _multiTableData[i] = readS.readSint16(); } } -void IsoMap::freeMem() { +void IsoMap::clear() { _tilesTable.clear(); _tilePlatformList.clear(); _metaTileList.clear(); _multiTable.clear(); - - free(_tileData); - _tileData = NULL; - - free(_multiTableData); - _multiTableData = NULL; - _multiDataCount = 0; + _tileData.clear(); + _multiTableData.clear(); } void IsoMap::adjustScroll(bool jump) { @@ -344,12 +344,12 @@ int16 IsoMap::findMulti(int16 tileIndex, int16 absU, int16 absV, int16 absH) { state = multiTileEntryData->currentState; offset = (ru + state * multiTileEntryData->uSize) * multiTileEntryData->vSize + rv; - offset *= sizeof(*_multiTableData); + offset *= sizeof(int16); offset += multiTileEntryData->offset; - if (offset + sizeof(*_multiTableData) - 1 >= _multiDataCount * sizeof(*_multiTableData)) { + if (offset + sizeof(int16) > _multiTableData.size() * sizeof(int16)) { error("wrong multiTileEntryData->offset"); } - tiles = (int16*)((byte*)_multiTableData + offset); + tiles = (int16*)((byte*)&_multiTableData.front() + offset); tileIndex = *tiles; if (tileIndex >= 256) { warning("something terrible happened"); @@ -707,7 +707,7 @@ void IsoMap::drawTile(uint16 tileIndex, const Point &point, const Location *loca return; } - tilePointer = _tileData + _tilesTable[tileIndex].offset; + tilePointer = _tilesTable[tileIndex].tilePointer; height = _tilesTable[tileIndex].height; if ((height <= 8) || (height > 64)) { @@ -831,18 +831,30 @@ void IsoMap::drawTile(uint16 tileIndex, const Point &point, const Location *loca widthCount += fgRunCount; count = 0; - while ((col < _tileClip.left) && (count < fgRunCount)) { - count++; - col++; + int colDiff = _tileClip.left - col; + if (colDiff > 0) { + if (colDiff > fgRunCount) { + colDiff = fgRunCount; + } + count = colDiff; + col += colDiff; } - while ((col < _tileClip.right) && (count < fgRunCount)) { - assert(_vm->_gfx->getBackBufferPixels() <= (byte *)(drawPointer + count)); - assert((_vm->_gfx->getBackBufferPixels() + (_vm->getDisplayInfo().width * - _vm->getDisplayInfo().height)) > (byte *)(drawPointer + count)); - drawPointer[count] = readPointer[count]; - count++; - col++; + + colDiff = _tileClip.right - col; + if (colDiff > 0) { + int countDiff = fgRunCount - count; + if (colDiff > countDiff) { + colDiff = countDiff; + } + if (colDiff > 0) { + byte *dst = (byte *)(drawPointer + count); + assert(_vm->_gfx->getBackBufferPixels() <= dst); + assert((_vm->_gfx->getBackBufferPixels() + (_vm->getDisplayInfo().width * _vm->getDisplayInfo().height)) >= (byte *)(dst + colDiff)); + memcpy(dst, (readPointer + count), colDiff); + col += colDiff; + } } + readPointer += fgRunCount; drawPointer += fgRunCount; } @@ -1149,8 +1161,6 @@ void IsoMap::placeOnTileMap(const Location &start, Location &result, int16 dista int16 vBase; int16 u; int16 v; - int i; - ActorData *actor; TilePoint tilePoint; uint16 dir; int16 dist; @@ -1171,8 +1181,7 @@ void IsoMap::placeOnTileMap(const Location &start, Location &result, int16 dista memset( &_searchArray, 0, sizeof(_searchArray)); - for (i = 0; i < _vm->_actor->_actorsCount; i++) { - actor = _vm->_actor->_actors[i]; + for (ActorDataArray::const_iterator actor = _vm->_actor->_actors.begin(); actor != _vm->_actor->_actors.end(); ++actor) { if (!actor->_inScene) continue; u = (actor->_location.u() >> 4) - uBase; @@ -1452,14 +1461,13 @@ void IsoMap::findDragonTilePath(ActorData* actor,const Location &start, const Lo actor->_walkStepsCount = i; if (i) { - actor->setTileDirectionsSize(i, false); - memcpy(actor->_tileDirections, res, i); + actor->_tileDirections.resize(i); + memcpy(&actor->_tileDirections.front(), res, i); } } void IsoMap::findTilePath(ActorData* actor, const Location &start, const Location &end) { - ActorData *other; int i; int16 u; int16 v; @@ -1499,10 +1507,9 @@ void IsoMap::findTilePath(ActorData* actor, const Location &start, const Locatio if (!(actor->_actorFlags & kActorNoCollide) && (_vm->_scene->currentSceneResourceId() != ITE_SCENE_OVERMAP)) { - for (i = 0; i < _vm->_actor->_actorsCount; i++) { - other = _vm->_actor->_actors[i]; + for (ActorDataArray::const_iterator other = _vm->_actor->_actors.begin(); other != _vm->_actor->_actors.end(); ++other) { if (!other->_inScene) continue; - if (other == actor) continue; + if (other->_id == actor->_id) continue; u = (other->_location.u() >> 4) - uBase; v = (other->_location.v() >> 4) - vBase; @@ -1585,8 +1592,8 @@ void IsoMap::findTilePath(ActorData* actor, const Location &start, const Locatio actor->_walkStepsCount = i; if (i) { - actor->setTileDirectionsSize(i, false); - memcpy(actor->_tileDirections, res, i); + actor->_tileDirections.resize(i); + memcpy(&actor->_tileDirections.front(), res, i); } } @@ -1601,19 +1608,6 @@ void IsoMap::setTileDoorState(int doorNumber, int doorState) { multiTileEntryData->currentState = doorState; } -static const int16 directions[8][2] = { - { 16, 16}, - { 16, 0}, - { 16, -16}, - { 0, -16}, - { -16, -16}, - { -16, 0}, - { -16, 16}, - { 0, 16} -}; - - - bool IsoMap::nextTileTarget(ActorData* actor) { uint16 dir; diff --git a/engines/saga/isomap.h b/engines/saga/isomap.h index 46173e2b13..7dc7dff8cd 100644 --- a/engines/saga/isomap.h +++ b/engines/saga/isomap.h @@ -95,7 +95,7 @@ enum TileMapEdgeType { struct IsoTileData { byte height; int8 attributes; - size_t offset; + byte *tilePointer; uint16 terrainMask; byte FGDBGDAttr; int8 GetMaskRule() const { @@ -154,14 +154,13 @@ class IsoMap { public: IsoMap(SagaEngine *vm); ~IsoMap() { - freeMem(); } - void loadImages(const byte * resourcePointer, size_t resourceLength); - void loadMap(const byte * resourcePointer, size_t resourceLength); - void loadPlatforms(const byte * resourcePointer, size_t resourceLength); - void loadMetaTiles(const byte * resourcePointer, size_t resourceLength); - void loadMulti(const byte * resourcePointer, size_t resourceLength); - void freeMem(); + void loadImages(const ByteArray &resourceData); + void loadMap(const ByteArray &resourceData); + void loadPlatforms(const ByteArray &resourceData); + void loadMetaTiles(const ByteArray &resourceData); + void loadMulti(const ByteArray &resourceData); + void clear(); void draw(); void drawSprite(SpriteList &spriteList, int spriteNumber, const Location &location, const Point &screenPosition, int scale); void adjustScroll(bool jump); @@ -213,16 +212,14 @@ private: IsoTileData *getTile(int16 u, int16 v, int16 z); - byte *_tileData; - size_t _tileDataLength; + ByteArray _tileData; Common::Array<IsoTileData> _tilesTable; Common::Array<TilePlatformData> _tilePlatformList; Common::Array<MetaTileData> _metaTileList; Common::Array<MultiTileEntryData> _multiTable; - uint16 _multiDataCount; - int16 *_multiTableData; + Common::Array<int16> _multiTableData; TileMapData _tileMap; diff --git a/engines/saga/itedata.cpp b/engines/saga/itedata.cpp index 7503818319..ab0aa12d18 100644 --- a/engines/saga/itedata.cpp +++ b/engines/saga/itedata.cpp @@ -269,7 +269,7 @@ ObjectTableData ITE_ObjectTable[ITE_OBJECTCOUNT] = { { 54, 281, 620, 352, 0, 80, 46, 0 } // Orb of Storms in Dam Lab }; -FxTable ITE_SfxTable[ITE_SFXCOUNT] = { +IteFxTable ITE_SfxTable[ITE_SFXCOUNT] = { { 14, 127 }, // Door open { 15, 127 }, // Door close { 16, 63 }, // Rush water (floppy volume: 127) diff --git a/engines/saga/itedata.h b/engines/saga/itedata.h index 71041902bc..f0f626a51a 100644 --- a/engines/saga/itedata.h +++ b/engines/saga/itedata.h @@ -77,16 +77,16 @@ struct ObjectTableData { uint16 interactBits; }; -struct FxTable { - int res; - int vol; +struct IteFxTable { + byte res; + byte vol; }; #define ITE_OBJECTCOUNT 39 #define ITE_SFXCOUNT 63 extern ObjectTableData ITE_ObjectTable[ITE_OBJECTCOUNT]; -extern FxTable ITE_SfxTable[ITE_SFXCOUNT]; +extern IteFxTable ITE_SfxTable[ITE_SFXCOUNT]; extern const char *ITEinterfaceTextStrings[][53]; diff --git a/engines/saga/music.cpp b/engines/saga/music.cpp index 199b0dfd8a..f1cdcbce46 100644 --- a/engines/saga/music.cpp +++ b/engines/saga/music.cpp @@ -117,6 +117,7 @@ void MusicDriver::send(uint32 b) { Music::Music(SagaEngine *vm, Audio::Mixer *mixer) : _vm(vm), _mixer(mixer) { _currentVolume = 0; + _currentMusicBuffer = NULL; _driver = new MusicDriver(); _digitalMusicContext = _vm->_resource->getContext(GAME_DIGITALMUSICFILE); @@ -162,11 +163,13 @@ Music::Music(SagaEngine *vm, Audio::Mixer *mixer) : _vm(vm), _mixer(mixer) { // Just set an XMIDI parser for Mac IHNM for now _parser = MidiParser::createParser_XMIDI(); } else { - byte *resourceData; - size_t resourceSize; + ByteArray resourceData; int resourceId = (_vm->getGameId() == GID_ITE ? 9 : 0); - _vm->_resource->loadResource(_musicContext, resourceId, resourceData, resourceSize); - if (!memcmp(resourceData, "FORM", 4)) { + _vm->_resource->loadResource(_musicContext, resourceId, resourceData); + if (resourceData.size() < 4) { + error("Music::Music Unable to load midi resource data"); + } + if (!memcmp(resourceData.getBuffer(), "FORM", 4)) { _parser = MidiParser::createParser_XMIDI(); // ITE had MT32 mapped instruments _driver->setGM(_vm->getGameId() != GID_ITE); @@ -175,17 +178,12 @@ Music::Music(SagaEngine *vm, Audio::Mixer *mixer) : _vm(vm), _mixer(mixer) { // ITE with standalone MIDI files is General MIDI _driver->setGM(_vm->getGameId() == GID_ITE); } - free(resourceData); } - + _parser->setMidiDriver(_driver); _parser->setTimerRate(_driver->getBaseTempo()); _parser->property(MidiParser::mpCenterPitchWheelOnUnload, 1); - _songTableLen = 0; - _songTable = 0; - - _midiMusicData = NULL; _digitalMusic = false; } @@ -196,9 +194,6 @@ Music::~Music() { delete _driver; _parser->setMidiDriver(NULL); delete _parser; - - free(_songTable); - free(_midiMusicData); } void Music::musicVolumeGaugeCallback(void *refCon) { @@ -258,9 +253,7 @@ bool Music::isPlaying() { void Music::play(uint32 resourceId, MusicFlags flags) { Audio::SeekableAudioStream *audioStream = NULL; - byte *resourceData; - size_t resourceSize; - uint32 loopStart; + uint32 loopStart = 0; debug(2, "Music::play %d, %d", resourceId, flags); @@ -392,14 +385,19 @@ void Music::play(uint32 resourceId, MusicFlags flags) { #endif return; } else { - _vm->_resource->loadResource(_musicContext, resourceId, resourceData, resourceSize); + if (_currentMusicBuffer == &_musicBuffer[1]) { + _currentMusicBuffer = &_musicBuffer[0]; + } else { + _currentMusicBuffer = &_musicBuffer[1]; + } + _vm->_resource->loadResource(_musicContext, resourceId, *_currentMusicBuffer); } - if (resourceSize < 4) { + if (_currentMusicBuffer->size() < 4) { error("Music::play() wrong music resource size"); } - if (!_parser->loadMusic(resourceData, resourceSize)) + if (!_parser->loadMusic(_currentMusicBuffer->getBuffer(), _currentMusicBuffer->size())) error("Music::play() wrong music resource"); _parser->setTrack(0); @@ -409,9 +407,6 @@ void Music::play(uint32 resourceId, MusicFlags flags) { // Handle music looping _parser->property(MidiParser::mpAutoLoop, (flags & MUSIC_LOOP) ? 1 : 0); - - free(_midiMusicData); - _midiMusicData = resourceData; } void Music::pause() { diff --git a/engines/saga/music.h b/engines/saga/music.h index 470b6e18b3..c7fef7225b 100644 --- a/engines/saga/music.h +++ b/engines/saga/music.h @@ -28,9 +28,9 @@ #ifndef SAGA_MUSIC_H #define SAGA_MUSIC_H -#include "sound/mixer.h" #include "sound/mididrv.h" #include "sound/midiparser.h" +#include "sound/mixer.h" #include "sound/decoders/mp3.h" #include "sound/decoders/vorbis.h" #include "sound/decoders/flac.h" @@ -106,8 +106,7 @@ public: void setVolume(int volume, int time = 1); int getVolume() { return _currentVolume; } - int32 *_songTable; - int _songTableLen; + Common::Array<int32> _songTable; private: SagaEngine *_vm; @@ -126,11 +125,12 @@ private: ResourceContext *_digitalMusicContext; MidiParser *_parser; - byte *_midiMusicData; static void musicVolumeGaugeCallback(void *refCon); static void onTimer(void *refCon); void musicVolumeGauge(); + ByteArray *_currentMusicBuffer; + ByteArray _musicBuffer[2]; }; } // End of namespace Saga diff --git a/engines/saga/objectmap.cpp b/engines/saga/objectmap.cpp index 02179d1d49..61d90cda69 100644 --- a/engines/saga/objectmap.cpp +++ b/engines/saga/objectmap.cpp @@ -45,84 +45,58 @@ namespace Saga { -HitZone::HitZone(MemoryReadStreamEndian *readStream, int index, int sceneNumber): _index(index) { - int i, j; - HitZone::ClickArea *clickArea; - Point *point; - +void HitZone::load(SagaEngine *vm, MemoryReadStreamEndian *readStream, int index, int sceneNumber) { + _index = index; _flags = readStream->readByte(); - _clickAreasCount = readStream->readByte(); + _clickAreas.resize(readStream->readByte()); _rightButtonVerb = readStream->readByte(); readStream->readByte(); // pad _nameIndex = readStream->readUint16(); _scriptNumber = readStream->readUint16(); - _clickAreas = (HitZone::ClickArea *)malloc(_clickAreasCount * sizeof(*_clickAreas)); - - if (_clickAreas == NULL) { - memoryError("HitZone::HitZone"); - } - - for (i = 0; i < _clickAreasCount; i++) { - clickArea = &_clickAreas[i]; - clickArea->pointsCount = readStream->readUint16LE(); + for (ClickAreas::iterator i = _clickAreas.begin(); i != _clickAreas.end(); ++i) { + i->resize(readStream->readUint16LE()); - assert(clickArea->pointsCount); + assert(!i->empty()); - clickArea->points = (Point *)malloc(clickArea->pointsCount * sizeof(*(clickArea->points))); - if (clickArea->points == NULL) { - memoryError("HitZone::HitZone"); - } - - for (j = 0; j < clickArea->pointsCount; j++) { - point = &clickArea->points[j]; - point->x = readStream->readSint16(); - point->y = readStream->readSint16(); + for (ClickArea::iterator j = i->begin(); j != i->end(); ++j) { + j->x = readStream->readSint16(); + j->y = readStream->readSint16(); // WORKAROUND: bug #1259608: "ITE: Riff ignores command in Ferret merchant center" // Apparently ITE Mac version has bug in game data. Both ObjectMap and ActionMap // for exit area are little taller (y = 123) and thus Riff goes to exit // when clicked on barrel of nails. - if (sceneNumber == 18 && index == 0 && i == 0 && j == 0 && point->y == 123) - point->y = 129; + if (vm->getGameId() == GID_ITE) { + if (sceneNumber == 18 && index == 0 && (i == _clickAreas.begin()) && (j == i->begin()) && j->y == 123) { + j->y = 129; + } + } } } } -HitZone::~HitZone() { - for (int i = 0; i < _clickAreasCount; i++) { - free(_clickAreas[i].points); - } - free(_clickAreas); -} - bool HitZone::getSpecialPoint(Point &specialPoint) const { - int i, pointsCount; - HitZone::ClickArea *clickArea; - Point *points; - - for (i = 0; i < _clickAreasCount; i++) { - clickArea = &_clickAreas[i]; - pointsCount = clickArea->pointsCount; - points = clickArea->points; - if (pointsCount == 1) { - specialPoint = points[0]; + for (ClickAreas::const_iterator i = _clickAreas.begin(); i != _clickAreas.end(); ++i) { + if (i->size() == 1) { + specialPoint = (*i)[0]; return true; } } return false; } + bool HitZone::hitTest(const Point &testPoint) { - int i, pointsCount; - HitZone::ClickArea *clickArea; - Point *points; + const Point *points; + uint pointsCount; if (_flags & kHitZoneEnabled) { - for (i = 0; i < _clickAreasCount; i++) { - clickArea = &_clickAreas[i]; - pointsCount = clickArea->pointsCount; - points = clickArea->points; - + for (ClickAreas::const_iterator i = _clickAreas.begin(); i != _clickAreas.end(); ++i) { + pointsCount = i->size(); + if (pointsCount < 2) { + continue; + } + points = &i->front(); if (pointsCount == 2) { // Hit-test a box region if ((testPoint.x >= points[0].x) && @@ -132,11 +106,9 @@ bool HitZone::hitTest(const Point &testPoint) { return true; } } else { - if (pointsCount > 2) { - // Hit-test a polygon - if (hitTestPoly(points, pointsCount, testPoint)) { - return true; - } + // Hit-test a polygon + if (hitTestPoly(points, pointsCount, testPoint)) { + return true; } } } @@ -146,26 +118,25 @@ bool HitZone::hitTest(const Point &testPoint) { #ifdef SAGA_DEBUG void HitZone::draw(SagaEngine *vm, int color) { - int i, pointsCount, j; + int pointsCount, j; Location location; - HitZone::ClickArea *clickArea; - Point *points; + HitZone::ClickArea tmpPoints; + const Point *points; Point specialPoint1; Point specialPoint2; - for (i = 0; i < _clickAreasCount; i++) { - clickArea = &_clickAreas[i]; - pointsCount = clickArea->pointsCount; + for (ClickAreas::const_iterator i = _clickAreas.begin(); i != _clickAreas.end(); ++i) { + pointsCount = i->size(); + points = &i->front(); if (vm->_scene->getFlags() & kSceneFlagISO) { - points = (Point*)malloc(sizeof(Point) * pointsCount); + tmpPoints.resize(pointsCount); for (j = 0; j < pointsCount; j++) { - location.u() = clickArea->points[j].x; - location.v() = clickArea->points[j].y; + location.u() = points[j].x; + location.v() = points[j].y; location.z = 0; - vm->_isoMap->tileCoordsToScreenPoint(location, points[j]); + vm->_isoMap->tileCoordsToScreenPoint(location, tmpPoints[j]); } - } else { - points = clickArea->points; + points = &tmpPoints.front(); } if (pointsCount == 2) { @@ -179,10 +150,6 @@ void HitZone::draw(SagaEngine *vm, int color) { vm->_gfx->drawPolyLine(points, pointsCount, color); } } - if (vm->_scene->getFlags() & kSceneFlagISO) { - free(points); - } - } if (getSpecialPoint(specialPoint1)) { specialPoint2 = specialPoint1; @@ -196,55 +163,36 @@ void HitZone::draw(SagaEngine *vm, int color) { #endif // Loads an object map resource ( objects ( clickareas ( points ) ) ) -void ObjectMap::load(const byte *resourcePointer, size_t resourceLength) { - int i; +void ObjectMap::load(const ByteArray &resourceData) { - if (resourceLength == 0) { - return; + if (!_hitZoneList.empty()) { + error("ObjectMap::load _hitZoneList not empty"); } - if (resourceLength < 4) { - error("ObjectMap::load wrong resourceLength"); + if (resourceData.empty()) { + return; } - MemoryReadStreamEndian readS(resourcePointer, resourceLength, _vm->isBigEndian()); - - _hitZoneListCount = readS.readSint16(); - if (_hitZoneListCount < 0) { - error("ObjectMap::load _hitZoneListCount < 0"); + if (resourceData.size() < 4) { + error("ObjectMap::load wrong resourceLength"); } - if (_hitZoneList) - error("ObjectMap::load _hitZoneList != NULL"); + ByteArrayReadStreamEndian readS(resourceData, _vm->isBigEndian()); - _hitZoneList = (HitZone **) malloc(_hitZoneListCount * sizeof(HitZone *)); - if (_hitZoneList == NULL) { - memoryError("ObjectMap::load"); - } + _hitZoneList.resize(readS.readUint16()); - for (i = 0; i < _hitZoneListCount; i++) { - _hitZoneList[i] = new HitZone(&readS, i, _vm->_scene->currentSceneNumber()); + int idx = 0; + for (HitZoneArray::iterator i = _hitZoneList.begin(); i != _hitZoneList.end(); ++i) { + i->load(_vm, &readS, idx++, _vm->_scene->currentSceneNumber()); } } -void ObjectMap::freeMem() { - int i; - - if (_hitZoneList) { - for (i = 0; i < _hitZoneListCount; i++) { - delete _hitZoneList[i]; - } - - free(_hitZoneList); - _hitZoneList = NULL; - } - _hitZoneListCount = 0; +void ObjectMap::clear() { + _hitZoneList.clear(); } - #ifdef SAGA_DEBUG void ObjectMap::draw(const Point& testPoint, int color, int color2) { - int i; int hitZoneIndex; char txtBuf[32]; Point pickPoint; @@ -260,8 +208,8 @@ void ObjectMap::draw(const Point& testPoint, int color, int color2) { hitZoneIndex = hitTest(pickPoint); - for (i = 0; i < _hitZoneListCount; i++) { - _hitZoneList[i]->draw(_vm, (hitZoneIndex == i) ? color2 : color); + for (HitZoneArray::iterator i = _hitZoneList.begin(); i != _hitZoneList.end(); ++i) { + i->draw(_vm, (hitZoneIndex == i->getIndex()) ? color2 : color); } if (hitZoneIndex != -1) { @@ -274,12 +222,11 @@ void ObjectMap::draw(const Point& testPoint, int color, int color2) { #endif int ObjectMap::hitTest(const Point& testPoint) { - int i; // Loop through all scene objects - for (i = 0; i < _hitZoneListCount; i++) { - if (_hitZoneList[i]->hitTest(testPoint)) { - return i; + for (HitZoneArray::iterator i = _hitZoneList.begin(); i != _hitZoneList.end(); ++i) { + if (i->hitTest(testPoint)) { + return i->getIndex(); } } @@ -287,7 +234,7 @@ int ObjectMap::hitTest(const Point& testPoint) { } void ObjectMap::cmdInfo() { - _vm->_console->DebugPrintf("%d zone(s) loaded.\n\n", _hitZoneListCount); + _vm->_console->DebugPrintf("%d zone(s) loaded.\n\n", _hitZoneList.size()); } } // End of namespace Saga diff --git a/engines/saga/objectmap.h b/engines/saga/objectmap.h index df0dcffe57..446afd478e 100644 --- a/engines/saga/objectmap.h +++ b/engines/saga/objectmap.h @@ -33,15 +33,14 @@ namespace Saga { class HitZone { private: - struct ClickArea { - int pointsCount; - Point *points; - }; - + typedef Common::Array<Point> ClickArea; + typedef Common::Array<ClickArea> ClickAreas; public: - HitZone(MemoryReadStreamEndian *readStream, int index, int sceneNumber); - ~HitZone(); + void load(SagaEngine *vm, MemoryReadStreamEndian *readStream, int index, int sceneNumber); + int getIndex() const { + return _index; + } int getNameIndex() const { return _nameIndex; } @@ -76,40 +75,38 @@ public: return objectIndexToId(kGameObjectStepZone, _index); } bool getSpecialPoint(Point &specialPoint) const; +#ifdef SAGA_DEBUG void draw(SagaEngine *vm, int color); // for debugging +#endif bool hitTest(const Point &testPoint); private: int _flags; // Saga::HitZoneFlags - int _clickAreasCount; int _rightButtonVerb; int _nameIndex; int _scriptNumber; int _index; - ClickArea *_clickAreas; + ClickAreas _clickAreas; }; +typedef Common::Array<HitZone> HitZoneArray; class ObjectMap { public: ObjectMap(SagaEngine *vm) : _vm(vm) { - _hitZoneList = NULL; - _hitZoneListCount = 0; - - } - ~ObjectMap() { - freeMem(); } - void load(const byte *resourcePointer, size_t resourceLength); - void freeMem(); + void load(const ByteArray &resourceData); + void clear(); +#ifdef SAGA_DEBUG void draw(const Point& testPoint, int color, int color2); // for debugging +#endif int hitTest(const Point& testPoint); HitZone *getHitZone(int16 index) { - if ((index < 0) || (index >= _hitZoneListCount)) { + if (uint(index) >= _hitZoneList.size()) { return NULL; } - return _hitZoneList[index]; + return &_hitZoneList[index]; } void cmdInfo(); @@ -117,8 +114,7 @@ public: private: SagaEngine *_vm; - int _hitZoneListCount; - HitZone **_hitZoneList; + HitZoneArray _hitZoneList; }; } // End of namespace Saga diff --git a/engines/saga/palanim.cpp b/engines/saga/palanim.cpp index dc892b845a..b0b76fc947 100644 --- a/engines/saga/palanim.cpp +++ b/engines/saga/palanim.cpp @@ -35,126 +35,95 @@ namespace Saga { PalAnim::PalAnim(SagaEngine *vm) : _vm(vm) { - _loaded = false; - _entryCount = 0; - _entries = NULL; } -PalAnim::~PalAnim() { -} - -int PalAnim::loadPalAnim(const byte *resdata, size_t resdata_len) { - void *test_p; +void PalAnim::loadPalAnim(const ByteArray &resourceData) { - uint16 i; + clear(); - if (_loaded) { - freePalAnim(); + if (resourceData.empty()) { + return; } - if (resdata == NULL) { - return FAILURE; - } - - MemoryReadStreamEndian readS(resdata, resdata_len, _vm->isBigEndian()); + ByteArrayReadStreamEndian readS(resourceData, _vm->isBigEndian()); if (_vm->getGameId() == GID_IHNM) { - return SUCCESS; + return; } - _entryCount = readS.readUint16(); - - debug(3, "PalAnim::loadPalAnim(): Loading %d PALANIM entries.", _entryCount); + _entries.resize(readS.readUint16()); - test_p = malloc(_entryCount * sizeof(PalanimEntry)); - _entries = (PalanimEntry *)test_p; + debug(3, "PalAnim::loadPalAnim(): Loading %d PALANIM entries.", _entries.size()); - for (i = 0; i < _entryCount; i++) { - int color_count; - int pal_count; - int p, c; + for (Common::Array<PalanimEntry>::iterator i = _entries.begin(); i != _entries.end(); ++i) { + + i->cycle = 0; - _entries[i].cycle = 0; + i->colors.resize(readS.readUint16()); + debug(2, "PalAnim::loadPalAnim(): Loading %d SAGA_COLOR structures.", i->colors.size()); - color_count = readS.readUint16(); - pal_count = readS.readUint16(); + i->palIndex.resize(readS.readUint16()); + debug(2, "PalAnim::loadPalAnim(): Loading %d palette indices.\n", i->palIndex.size()); - _entries[i].pal_count = pal_count; - _entries[i].color_count = color_count; - debug(2, "PalAnim::loadPalAnim(): Entry %d: Loading %d palette indices.\n", i, pal_count); - - test_p = malloc(sizeof(char) * pal_count); - _entries[i].pal_index = (byte *)test_p; - - debug(2, "PalAnim::loadPalAnim(): Entry %d: Loading %d SAGA_COLOR structures.", i, color_count); - - test_p = malloc(sizeof(Color) * color_count); - _entries[i].colors = (Color *)test_p; - - for (p = 0; p < pal_count; p++) { - _entries[i].pal_index[p] = readS.readByte(); + for (uint j = 0; j < i->palIndex.size(); j++) { + i->palIndex[j] = readS.readByte(); } - for (c = 0; c < color_count; c++) { - _entries[i].colors[c].red = readS.readByte(); - _entries[i].colors[c].green = readS.readByte(); - _entries[i].colors[c].blue = readS.readByte(); + for (Common::Array<Color>::iterator j = i->colors.begin(); j != i->colors.end(); ++j) { + j->red = readS.readByte(); + j->green = readS.readByte(); + j->blue = readS.readByte(); } } - - _loaded = true; - return SUCCESS; } -int PalAnim::cycleStart() { +void PalAnim::cycleStart() { Event event; - if (!_loaded) { - return FAILURE; + if (_entries.empty()) { + return; } event.type = kEvTOneshot; event.code = kPalAnimEvent; event.op = kEventCycleStep; event.time = PALANIM_CYCLETIME; - _vm->_events->queue(&event); - - return SUCCESS; + _vm->_events->queue(event); } -int PalAnim::cycleStep(int vectortime) { +void PalAnim::cycleStep(int vectortime) { static PalEntry pal[256]; - uint16 pal_index; - uint16 col_index; + uint16 palIndex; + uint16 colIndex; - uint16 i, j; + uint16 j; uint16 cycle; - uint16 cycle_limit; + uint16 cycleLimit; Event event; - if (!_loaded) { - return FAILURE; + if (_entries.empty()) { + return; } _vm->_gfx->getCurrentPal(pal); - for (i = 0; i < _entryCount; i++) { - cycle = _entries[i].cycle; - cycle_limit = _entries[i].color_count; - for (j = 0; j < _entries[i].pal_count; j++) { - pal_index = (unsigned char)_entries[i].pal_index[j]; - col_index = (cycle + j) % cycle_limit; - pal[pal_index].red = (byte) _entries[i].colors[col_index].red; - pal[pal_index].green = (byte) _entries[i].colors[col_index].green; - pal[pal_index].blue = (byte) _entries[i].colors[col_index].blue; + for (Common::Array<PalanimEntry>::iterator i = _entries.begin(); i != _entries.end(); ++i) { + cycle = i->cycle; + cycleLimit = i->colors.size(); + for (j = 0; j < i->palIndex.size(); j++) { + palIndex = i->palIndex[j]; + colIndex = (cycle + j) % cycleLimit; + pal[palIndex].red = (byte) i->colors[colIndex].red; + pal[palIndex].green = (byte) i->colors[colIndex].green; + pal[palIndex].blue = (byte) i->colors[colIndex].blue; } - _entries[i].cycle++; + i->cycle++; - if (_entries[i].cycle == cycle_limit) { - _entries[i].cycle = 0; + if (i->cycle == cycleLimit) { + i->cycle = 0; } } @@ -167,32 +136,14 @@ int PalAnim::cycleStep(int vectortime) { event.code = kPalAnimEvent; event.op = kEventCycleStep; event.time = vectortime + PALANIM_CYCLETIME; - _vm->_events->queue(&event); + _vm->_events->queue(event); - return SUCCESS; } -int PalAnim::freePalAnim() { - uint16 i; - - if (!_loaded) { - return FAILURE; - } - - for (i = 0; i < _entryCount; i++) { - debug(2, "PalAnim::freePalAnim(): Entry %d: Freeing colors.", i); - free(_entries[i].colors); - debug(2, "PalAnim::freePalAnim(): Entry %d: Freeing indices.", i); - free(_entries[i].pal_index); - } - - debug(3, "PalAnim::freePalAnim(): Freeing entries."); - - free(_entries); - - _loaded = false; - - return SUCCESS; +void PalAnim::clear() { + debug(3, "PalAnim::clear()"); + + _entries.clear(); } } // End of namespace Saga diff --git a/engines/saga/palanim.h b/engines/saga/palanim.h index 52002e01c3..2d2c3f1399 100644 --- a/engines/saga/palanim.h +++ b/engines/saga/palanim.h @@ -33,29 +33,24 @@ namespace Saga { #define PALANIM_CYCLETIME 100 struct PalanimEntry { - uint16 pal_count; - uint16 color_count; uint16 cycle; - byte *pal_index; - Color *colors; + ByteArray palIndex; + Common::Array<Color> colors; }; class PalAnim { public: PalAnim(SagaEngine *vm); - ~PalAnim(); - int loadPalAnim(const byte *, size_t); - int cycleStart(); - int cycleStep(int vectortime); - int freePalAnim(); + void loadPalAnim(const ByteArray &resourceData); + void cycleStart(); + void cycleStep(int vectortime); + void clear(); private: SagaEngine *_vm; - bool _loaded; - uint16 _entryCount; - PalanimEntry *_entries; + Common::Array<PalanimEntry> _entries; }; } // End of namespace Saga diff --git a/engines/saga/puzzle.cpp b/engines/saga/puzzle.cpp index 73839eb6ea..af81c3c670 100644 --- a/engines/saga/puzzle.cpp +++ b/engines/saga/puzzle.cpp @@ -172,7 +172,7 @@ void Puzzle::initPieces() { _vm->_actor->getSpriteParams(puzzle, frameNumber, spriteList); for (int i = 0; i < PUZZLE_PIECES; i++) { - spI = &(spriteList->infoList[i]); + spI = &((*spriteList)[i]); _pieceInfo[i].offX = (byte)(spI->width >> 1); _pieceInfo[i].offY = (byte)(spI->height >> 1); @@ -347,7 +347,7 @@ void Puzzle::dropPiece(Point mousePt) { if (newy < boxy) newy = PUZZLE_Y_OFFSET; - spI = &(spriteList->infoList[_puzzlePiece]); + spI = &((*spriteList)[_puzzlePiece]); if (newx + spI->width > boxw) newx = boxw - spI->width ; diff --git a/engines/saga/resource.cpp b/engines/saga/resource.cpp index 7d82aa4bda..0fb7327f0d 100644 --- a/engines/saga/resource.cpp +++ b/engines/saga/resource.cpp @@ -43,8 +43,7 @@ bool ResourceContext::loadResV1(uint32 contextOffset, uint32 contextSize) { size_t i; bool result; byte tableInfo[RSC_TABLEINFO_SIZE]; - byte *tableBuffer; - size_t tableSize; + ByteArray tableBuffer; uint32 count; uint32 resourceTableOffset; ResourceData *resourceData; @@ -70,17 +69,15 @@ bool ResourceContext::loadResV1(uint32 contextOffset, uint32 contextSize) { } // Load resource table - tableSize = RSC_TABLEENTRY_SIZE * count; - - tableBuffer = (byte *)malloc(tableSize); + tableBuffer.resize(RSC_TABLEENTRY_SIZE * count); _file.seek(resourceTableOffset + contextOffset, SEEK_SET); - result = (_file.read(tableBuffer, tableSize) == tableSize); + result = (_file.read(tableBuffer.getBuffer(), tableBuffer.size()) == tableBuffer.size()); if (result) { _table.resize(count); - MemoryReadStreamEndian readS1(tableBuffer, tableSize, _isBigEndian); + MemoryReadStreamEndian readS1(tableBuffer.getBuffer(), tableBuffer.size(), _isBigEndian); for (i = 0; i < count; i++) { resourceData = &_table[i]; @@ -94,7 +91,6 @@ bool ResourceContext::loadResV1(uint32 contextOffset, uint32 contextSize) { } } - free(tableBuffer); return result; } @@ -107,8 +103,6 @@ bool ResourceContext::load(SagaEngine *vm, Resource *resource) { uint32 subjectResourceId; uint32 patchResourceId; ResourceData *subjectResourceData; - byte *tableBuffer; - size_t tableSize; bool isMacBinary; if (_fileName == NULL) { // IHNM special case @@ -145,10 +139,12 @@ bool ResourceContext::load(SagaEngine *vm, Resource *resource) { if (subjectContext == NULL) { error("ResourceContext::load() Subject context not found"); } - resource->loadResource(this, _table.size() - 1, tableBuffer, tableSize); + ByteArray tableBuffer; + + resource->loadResource(this, _table.size() - 1, tableBuffer); - MemoryReadStreamEndian readS2(tableBuffer, tableSize, _isBigEndian); - for (i = 0; i < tableSize / 8; i++) { + ByteArrayReadStreamEndian readS2(tableBuffer, _isBigEndian); + for (i = 0; i < tableBuffer.size() / 8; i++) { subjectResourceId = readS2.readUint32(); patchResourceId = readS2.readUint32(); subjectResourceData = subjectContext->getResourceData(subjectResourceId); @@ -157,7 +153,6 @@ bool ResourceContext::load(SagaEngine *vm, Resource *resource) { subjectResourceData->offset = resourceData->offset; subjectResourceData->size = resourceData->size; } - free(tableBuffer); } //process external patch files @@ -370,25 +365,25 @@ void Resource::clearContexts() { } } -void Resource::loadResource(ResourceContext *context, uint32 resourceId, byte*&resourceBuffer, size_t &resourceSize) { +void Resource::loadResource(ResourceContext *context, uint32 resourceId, ByteArray &resourceBuffer) { Common::File *file; uint32 resourceOffset; ResourceData *resourceData; - debug(8, "loadResource %d", resourceId); resourceData = context->getResourceData(resourceId); file = context->getFile(resourceData); resourceOffset = resourceData->offset; - resourceSize = resourceData->size; - resourceBuffer = (byte*)malloc(resourceSize); + debug(8, "loadResource %d 0x%X:0x%X", resourceId, resourceOffset, uint(resourceData->size)); + resourceBuffer.resize(resourceData->size); + file->seek((long)resourceOffset, SEEK_SET); - if (file->read(resourceBuffer, resourceSize) != resourceSize) { + if (file->read(resourceBuffer.getBuffer(), resourceBuffer.size()) != resourceBuffer.size()) { error("Resource::loadResource() failed to read"); } diff --git a/engines/saga/resource.h b/engines/saga/resource.h index e32d16c469..5009c862f4 100644 --- a/engines/saga/resource.h +++ b/engines/saga/resource.h @@ -206,7 +206,7 @@ public: virtual ~Resource(); bool createContexts(); void clearContexts(); - void loadResource(ResourceContext *context, uint32 resourceId, byte*&resourceBuffer, size_t &resourceSize); + void loadResource(ResourceContext *context, uint32 resourceId, ByteArray &resourceBuffer); virtual uint32 convertResourceId(uint32 resourceId) = 0; virtual void loadGlobalResources(int chapter, int actorsEntrance) = 0; diff --git a/engines/saga/resource_res.cpp b/engines/saga/resource_res.cpp index 8546030241..646de8667b 100644 --- a/engines/saga/resource_res.cpp +++ b/engines/saga/resource_res.cpp @@ -48,13 +48,13 @@ void Resource_RES::loadGlobalResources(int chapter, int actorsEntrance) { if (chapter < 0) chapter = !_vm->isIHNMDemo() ? 8 : 7; - _vm->_script->_globalVoiceLUT.freeMem(); + _vm->_script->_globalVoiceLUT.clear(); // TODO: close chapter context, or rather reassign it in our case ResourceContext *resourceContext; ResourceContext *soundContext; - int i; + uint i; resourceContext = _vm->_resource->getContext(GAME_RESOURCEFILE); if (resourceContext == NULL) { @@ -66,41 +66,38 @@ void Resource_RES::loadGlobalResources(int chapter, int actorsEntrance) { error("Resource::loadGlobalResources() sound context not found"); } - byte *resourcePointer; - size_t resourceLength; + ByteArray resourceData; if (!_vm->isIHNMDemo()) { - _vm->_resource->loadResource(resourceContext, metaResourceTable[chapter], - resourcePointer, resourceLength); + _vm->_resource->loadResource(resourceContext, metaResourceTable[chapter], resourceData); } else { - _vm->_resource->loadResource(resourceContext, metaResourceTableDemo[chapter], - resourcePointer, resourceLength); + _vm->_resource->loadResource(resourceContext, metaResourceTableDemo[chapter], resourceData); } - if (resourceLength == 0) { + if (resourceData.empty()) { error("Resource::loadGlobalResources wrong metaResource"); } - MemoryReadStream metaS(resourcePointer, resourceLength); - - _metaResource.sceneIndex = metaS.readSint16LE(); - _metaResource.objectCount = metaS.readSint16LE(); - _metaResource.objectsStringsResourceID = metaS.readSint32LE(); - _metaResource.inventorySpritesID = metaS.readSint32LE(); - _metaResource.mainSpritesID = metaS.readSint32LE(); - _metaResource.objectsResourceID = metaS.readSint32LE(); - _metaResource.actorCount = metaS.readSint16LE(); - _metaResource.actorsStringsResourceID = metaS.readSint32LE(); - _metaResource.actorsResourceID = metaS.readSint32LE(); - _metaResource.protagFaceSpritesID = metaS.readSint32LE(); - _metaResource.field_22 = metaS.readSint32LE(); - _metaResource.field_26 = metaS.readSint16LE(); - _metaResource.protagStatesCount = metaS.readSint16LE(); - _metaResource.protagStatesResourceID = metaS.readSint32LE(); - _metaResource.cutawayListResourceID = metaS.readSint32LE(); - _metaResource.songTableID = metaS.readSint32LE(); - - free(resourcePointer); + { + ByteArrayReadStreamEndian metaS(resourceData); + + _metaResource.sceneIndex = metaS.readSint16LE(); + _metaResource.objectCount = metaS.readSint16LE(); + _metaResource.objectsStringsResourceID = metaS.readSint32LE(); + _metaResource.inventorySpritesID = metaS.readSint32LE(); + _metaResource.mainSpritesID = metaS.readSint32LE(); + _metaResource.objectsResourceID = metaS.readSint32LE(); + _metaResource.actorCount = metaS.readSint16LE(); + _metaResource.actorsStringsResourceID = metaS.readSint32LE(); + _metaResource.actorsResourceID = metaS.readSint32LE(); + _metaResource.protagFaceSpritesID = metaS.readSint32LE(); + _metaResource.field_22 = metaS.readSint32LE(); + _metaResource.field_26 = metaS.readSint16LE(); + _metaResource.protagStatesCount = metaS.readSint16LE(); + _metaResource.protagStatesResourceID = metaS.readSint32LE(); + _metaResource.cutawayListResourceID = metaS.readSint32LE(); + _metaResource.songTableID = metaS.readSint32LE(); + } _vm->_actor->loadActorList(actorsEntrance, _metaResource.actorCount, _metaResource.actorsResourceID, _metaResource.protagStatesCount, @@ -108,90 +105,83 @@ void Resource_RES::loadGlobalResources(int chapter, int actorsEntrance) { _vm->_actor->_protagonist->_sceneNumber = _metaResource.sceneIndex; - _vm->_actor->_objectsStrings.freeMem(); + _vm->_actor->_objectsStrings.clear(); - _vm->_resource->loadResource(resourceContext, _metaResource.objectsStringsResourceID, resourcePointer, resourceLength); - _vm->loadStrings(_vm->_actor->_objectsStrings, resourcePointer, resourceLength); - free(resourcePointer); + _vm->_resource->loadResource(resourceContext, _metaResource.objectsStringsResourceID, resourceData); + _vm->loadStrings(_vm->_actor->_objectsStrings, resourceData); - if (chapter >= _vm->_sndRes->_fxTableIDsLen) { + if (uint(chapter) >= _vm->_sndRes->_fxTableIDs.size()) { error("Chapter ID exceeds fxTableIDs length"); } debug(0, "Going to read %d of %d", chapter, _vm->_sndRes->_fxTableIDs[chapter]); _vm->_resource->loadResource(soundContext, _vm->_sndRes->_fxTableIDs[chapter], - resourcePointer, resourceLength); + resourceData); - if (resourceLength == 0) { + if (resourceData.empty()) { error("Resource::loadGlobalResources Can't load sound effects for current track"); } - free(_vm->_sndRes->_fxTable); - - _vm->_sndRes->_fxTableLen = resourceLength / 4; - _vm->_sndRes->_fxTable = (FxTable *)malloc(sizeof(FxTable) * _vm->_sndRes->_fxTableLen); + _vm->_sndRes->_fxTable.resize(resourceData.size() / 4); - MemoryReadStream fxS(resourcePointer, resourceLength); + { + ByteArrayReadStreamEndian fxS(resourceData); - for (i = 0; i < _vm->_sndRes->_fxTableLen; i++) { - _vm->_sndRes->_fxTable[i].res = fxS.readSint16LE(); - _vm->_sndRes->_fxTable[i].vol = fxS.readSint16LE(); + for (i = 0; i < _vm->_sndRes->_fxTable.size(); i++) { + _vm->_sndRes->_fxTable[i].res = fxS.readSint16LE(); + _vm->_sndRes->_fxTable[i].vol = fxS.readSint16LE(); + } } - free(resourcePointer); - _vm->_interface->_defPortraits.freeMem(); + _vm->_interface->_defPortraits.clear(); _vm->_sprite->loadList(_metaResource.protagFaceSpritesID, _vm->_interface->_defPortraits); - _vm->_actor->_actorsStrings.freeMem(); + _vm->_actor->_actorsStrings.clear(); - _vm->_resource->loadResource(resourceContext, _metaResource.actorsStringsResourceID, resourcePointer, resourceLength); - _vm->loadStrings(_vm->_actor->_actorsStrings, resourcePointer, resourceLength); - free(resourcePointer); + _vm->_resource->loadResource(resourceContext, _metaResource.actorsStringsResourceID, resourceData); + _vm->loadStrings(_vm->_actor->_actorsStrings, resourceData); - _vm->_sprite->_inventorySprites.freeMem(); + _vm->_sprite->_inventorySprites.clear(); _vm->_sprite->loadList(_metaResource.inventorySpritesID, _vm->_sprite->_inventorySprites); - _vm->_sprite->_mainSprites.freeMem(); + _vm->_sprite->_mainSprites.clear(); _vm->_sprite->loadList(_metaResource.mainSpritesID, _vm->_sprite->_mainSprites); _vm->_actor->loadObjList(_metaResource.objectCount, _metaResource.objectsResourceID); - _vm->_resource->loadResource(resourceContext, _metaResource.cutawayListResourceID, resourcePointer, resourceLength); + _vm->_resource->loadResource(resourceContext, _metaResource.cutawayListResourceID, resourceData); - if (resourceLength == 0) { + if (resourceData.empty()) { error("Resource::loadGlobalResources Can't load cutaway list"); } - _vm->_anim->loadCutawayList(resourcePointer, resourceLength); + _vm->_anim->loadCutawayList(resourceData); if (_metaResource.songTableID > 0) { - _vm->_resource->loadResource(resourceContext, _metaResource.songTableID, resourcePointer, resourceLength); + _vm->_resource->loadResource(resourceContext, _metaResource.songTableID, resourceData); if (chapter == 6) { - int32 id = READ_LE_UINT32(&resourcePointer[actorsEntrance * 4]); - free(resourcePointer); - _vm->_resource->loadResource(resourceContext, id, resourcePointer, resourceLength); + if (resourceData.size() < (uint(actorsEntrance) * 4 + 4)) { + error("Resource::loadGlobalResources chapter 6 has wrong resource"); + } + int32 id = READ_LE_UINT32(&resourceData[actorsEntrance * 4]); + _vm->_resource->loadResource(resourceContext, id, resourceData); } - if (resourceLength == 0) { + if (resourceData.empty()) { error("Resource::loadGlobalResources Can't load songs list for current track"); } - free(_vm->_music->_songTable); - - _vm->_music->_songTableLen = resourceLength / 4; - _vm->_music->_songTable = (int32 *)malloc(sizeof(int32) * _vm->_music->_songTableLen); + _vm->_music->_songTable.resize(resourceData.size() / 4); - MemoryReadStream songS(resourcePointer, resourceLength); + ByteArrayReadStreamEndian songS(resourceData); - for (i = 0; i < _vm->_music->_songTableLen; i++) + for (i = 0; i < _vm->_music->_songTable.size(); i++) _vm->_music->_songTable[i] = songS.readSint32LE(); - free(resourcePointer); } else { // The IHNM demo has a fixed music track and doesn't load a song table _vm->_music->setVolume(_vm->_musicVolume, 1); _vm->_music->play(3, MUSIC_LOOP); - free(resourcePointer); } int voiceLUTResourceID = 0; @@ -207,9 +197,8 @@ void Resource_RES::loadGlobalResources(int chapter, int actorsEntrance) { } if (voiceLUTResourceID) { - _vm->_resource->loadResource(resourceContext, voiceLUTResourceID, resourcePointer, resourceLength); - _vm->_script->loadVoiceLUT(_vm->_script->_globalVoiceLUT, resourcePointer, resourceLength); - free(resourcePointer); + _vm->_resource->loadResource(resourceContext, voiceLUTResourceID, resourceData); + _vm->_script->loadVoiceLUT(_vm->_script->_globalVoiceLUT, resourceData); } _vm->_spiritualBarometer = 0; diff --git a/engines/saga/saga.cpp b/engines/saga/saga.cpp index 1b7fa97f8d..abd681ce87 100644 --- a/engines/saga/saga.cpp +++ b/engines/saga/saga.cpp @@ -291,7 +291,7 @@ Common::Error SagaEngine::run() { _sound = new Sound(this, _mixer); if (!isSaga2()) { - _interface->converseInit(); + _interface->converseClear(); _script->setVerb(_script->getVerbType(kVerbWalkTo)); } @@ -393,28 +393,26 @@ Common::Error SagaEngine::run() { return Common::kNoError; } -void SagaEngine::loadStrings(StringsTable &stringsTable, const byte *stringsPointer, size_t stringsLength) { +void SagaEngine::loadStrings(StringsTable &stringsTable, const ByteArray &stringsData) { uint16 stringsCount; size_t offset; size_t prevOffset = 0; - int i; + Common::Array<size_t> tempOffsets; + uint ui; - if (stringsLength == 0) { + if (stringsData.empty()) { error("SagaEngine::loadStrings() Error loading strings list resource"); } - stringsTable.stringsPointer = (byte*)malloc(stringsLength); - memcpy(stringsTable.stringsPointer, stringsPointer, stringsLength); - - MemoryReadStreamEndian scriptS(stringsTable.stringsPointer, stringsLength, isBigEndian()); //TODO: get endianess from context + ByteArrayReadStreamEndian scriptS(stringsData, isBigEndian()); //TODO: get endianess from context offset = scriptS.readUint16(); stringsCount = offset / 2; - stringsTable.strings = (const char **)malloc(stringsCount * sizeof(*stringsTable.strings)); - i = 0; + ui = 0; scriptS.seek(0); - while (i < stringsCount) { + tempOffsets.resize(stringsCount); + while (ui < stringsCount) { offset = scriptS.readUint16(); // In some rooms in IHNM, string offsets can be greater than the maximum value than a 16-bit integer can hold // We detect this by checking the previous offset, and if it was bigger than the current one, an overflow @@ -423,27 +421,47 @@ void SagaEngine::loadStrings(StringsTable &stringsTable, const byte *stringsPoin if (prevOffset > offset) offset += 65536; prevOffset = offset; - if (offset == stringsLength) { - stringsCount = i; - stringsTable.strings = (const char **)realloc(stringsTable.strings, stringsCount * sizeof(*stringsTable.strings)); + if (offset == stringsData.size()) { + stringsCount = ui; + tempOffsets.resize(stringsCount); break; } - if (offset > stringsLength) { + if (offset > stringsData.size()) { // This case should never occur, but apparently it does in the Italian fan // translation of IHNM warning("SagaEngine::loadStrings wrong strings table"); - stringsCount = i; - stringsTable.strings = (const char **)realloc(stringsTable.strings, stringsCount * sizeof(*stringsTable.strings)); + stringsCount = ui; + tempOffsets.resize(stringsCount); break; } - stringsTable.strings[i] = (const char *)stringsTable.stringsPointer + offset; - debug(9, "string[%i]=%s", i, stringsTable.strings[i]); - i++; + tempOffsets[ui] = offset; + ui++; + } + + prevOffset = scriptS.pos(); + int32 left = scriptS.size() - prevOffset; + if (left < 0) { + error("SagaEngine::loadStrings() Error loading strings buffer"); + } + + stringsTable.buffer.resize(left); + if (left > 0) { + scriptS.read(&stringsTable.buffer.front(), left); + } + + stringsTable.strings.resize(tempOffsets.size()); + for (ui = 0; ui < tempOffsets.size(); ui++) { + offset = tempOffsets[ui] - prevOffset; + if (offset >= stringsTable.buffer.size()) { + error("SagaEngine::loadStrings() Wrong offset"); + } + stringsTable.strings[ui] = &stringsTable.buffer[offset]; + + debug(9, "string[%i]=%s", ui, stringsTable.strings[ui]); } - stringsTable.stringsCount = stringsCount; } -const char *SagaEngine::getObjectName(uint16 objectId) { +const char *SagaEngine::getObjectName(uint16 objectId) const { ActorData *actor; ObjectData *obj; const HitZone *hitZone; @@ -598,7 +616,7 @@ void SagaEngine::setTalkspeed(int talkspeed) { ConfMan.setInt("talkspeed", (talkspeed * 255 + 3 / 2) / 3); } -int SagaEngine::getTalkspeed() { +int SagaEngine::getTalkspeed() const { return (ConfMan.getInt("talkspeed") * 3 + 255 / 2) / 255; } diff --git a/engines/saga/saga.h b/engines/saga/saga.h index 102d1e5c82..8eb4833278 100644 --- a/engines/saga/saga.h +++ b/engines/saga/saga.h @@ -49,7 +49,7 @@ struct ADGameFileDescription; * SAGA2 status: in early stages of development, no recent activity. Contact sev * if you want to work on it, since we have some original source codes. * - * Supported games: + * Games using this engine: * * SAGA: * - Inherit the Earth @@ -86,7 +86,7 @@ class ResourceContext; using Common::MemoryReadStream; using Common::MemoryReadStreamEndian; -//#define SAGA_DEBUG 1 // define for test functions +// #define SAGA_DEBUG 1 // define for test functions #define SAGA_IMAGE_DATA_OFFSET 776 #define SAGA_IMAGE_HEADER_LEN 8 @@ -155,40 +155,40 @@ enum GameFeatures { }; enum VerbTypeIds { - kVerbITENone = 0, - kVerbITEPickUp = 1, - kVerbITELookAt = 2, - kVerbITEWalkTo = 3, - kVerbITETalkTo = 4, - kVerbITEOpen = 5, - kVerbITEClose = 6, - kVerbITEGive = 7, - kVerbITEUse = 8, - kVerbITEOptions = 9, - kVerbITEEnter = 10, - kVerbITELeave = 11, - kVerbITEBegin = 12, - kVerbITEWalkOnly = 13, - kVerbITELookOnly = 14, - - - kVerbIHNMNone = 0, - kVerbIHNMWalk = 1, - kVerbIHNMLookAt = 2, - kVerbIHNMTake = 3, - kVerbIHNMUse = 4, - kVerbIHNMTalkTo = 5, - kVerbIHNMSwallow = 6, - kVerbIHNMGive = 7, - kVerbIHNMPush = 8, - kVerbIHNMOptions = 9, - kVerbIHNMEnter = 10, - kVerbIHNMLeave = 11, - kVerbIHNMBegin = 12, - kVerbIHNMWalkOnly = 13, - kVerbIHNMLookOnly = 14, - - kVerbTypeIdsMax = kVerbITELookOnly + 1 + kVerbITENone = 0, + kVerbITEPickUp = 1, + kVerbITELookAt = 2, + kVerbITEWalkTo = 3, + kVerbITETalkTo = 4, + kVerbITEOpen = 5, + kVerbITEClose = 6, + kVerbITEGive = 7, + kVerbITEUse = 8, + kVerbITEOptions = 9, + kVerbITEEnter = 10, + kVerbITELeave = 11, + kVerbITEBegin = 12, + kVerbITEWalkOnly = 13, + kVerbITELookOnly = 14, + + + kVerbIHNMNone = 0, + kVerbIHNMWalk = 1, + kVerbIHNMLookAt = 2, + kVerbIHNMTake = 3, + kVerbIHNMUse = 4, + kVerbIHNMTalkTo = 5, + kVerbIHNMSwallow = 6, + kVerbIHNMGive = 7, + kVerbIHNMPush = 8, + kVerbIHNMOptions = 9, + kVerbIHNMEnter = 10, + kVerbIHNMLeave = 11, + kVerbIHNMBegin = 12, + kVerbIHNMWalkOnly = 13, + kVerbIHNMLookOnly = 14, + + kVerbTypeIdsMax = kVerbITELookOnly + 1 }; enum PanelButtonType { @@ -381,30 +381,21 @@ struct ImageHeader { }; struct StringsTable { - byte *stringsPointer; - int stringsCount; - const char **strings; + Common::Array<char> buffer; + Common::Array<char *> strings; - const char *getString(int index) const { - if ((stringsCount <= index) || (index < 0)) { + const char *getString(uint index) const { + if (strings.size() <= index) { // This occurs at the end of Ted's chapter, right after the ending cutscene - warning("StringsTable::getString wrong index 0x%X (%d)", index, stringsCount); + warning("StringsTable::getString wrong index 0x%X (%d)", index, strings.size()); return ""; } return strings[index]; } - void freeMem() { - free(strings); - free(stringsPointer); - memset(this, 0, sizeof(*this)); - } - - StringsTable() { - memset(this, 0, sizeof(*this)); - } - ~StringsTable() { - freeMem(); + void clear() { + strings.clear(); + buffer.clear(); } }; @@ -467,6 +458,34 @@ inline uint16 objectIndexToId(int type, int index) { return (type << OBJECT_TYPE_SHIFT) | (OBJECT_TYPE_MASK & index); } +class ByteArray : public Common::Array<byte> { +public: + /** + * Return a pointer to the start of the buffer underlying this byte array, + * or NULL if the buffer is empty. + */ + byte *getBuffer() { + return empty() ? NULL : &front(); + } + + const byte *getBuffer() const { + return empty() ? NULL : &front(); + } + + void assign(const ByteArray &src) { + resize(src.size()); + if (!empty()) { + memcpy(&front(), &src.front(), size()); + } + } +}; + +class ByteArrayReadStreamEndian : public MemoryReadStreamEndian { +public: + ByteArrayReadStreamEndian(const ByteArray & byteArray, bool bigEndian = false) : MemoryReadStreamEndian(byteArray.getBuffer(), byteArray.size(), bigEndian) { + } +}; + class SagaEngine : public Engine { friend class Scene; @@ -484,15 +503,14 @@ public: void save(const char *fileName, const char *saveName); void load(const char *fileName); - uint32 getCurrentLoadVersion() { + uint32 getCurrentLoadVersion() const { return _saveHeader.version; } void fillSaveList(); char *calcSaveFileName(uint slotNumber); SaveFileData *getSaveFile(uint idx); - uint getSaveSlotNumber(uint idx); - uint getNewSaveSlotNumber(); + uint getNewSaveSlotNumber() const; bool locateSaveFile(char *saveName, uint &titleNumber); bool isSaveListFull() const { return _saveFilesCount == MAX_SAVES; @@ -501,7 +519,7 @@ public: return isSaveListFull() ? _saveFilesCount : _saveFilesCount + 1; } - bool isIHNMDemo() { return _isIHNMDemo; } + bool isIHNMDemo() const { return _isIHNMDemo; } int16 _framesEsc; @@ -546,23 +564,28 @@ public: Common::RandomSource _rnd; private: - int decodeBGImageRLE(const byte *inbuf, size_t inbuf_len, byte *outbuf, size_t outbuf_len); - int flipImage(byte *img_buf, int columns, int scanlines); - int unbankBGImage(byte *dest_buf, const byte *src_buf, int columns, int scanlines); + bool decodeBGImageRLE(const byte *inbuf, size_t inbuf_len, ByteArray &outbuf); + void flipImage(byte *imageBuffer, int columns, int scanlines); + void unbankBGImage(byte *dest_buf, const byte *src_buf, int columns, int scanlines); uint32 _previousTicks; public: - int decodeBGImage(const byte *image_data, size_t image_size, - byte **output_buf, size_t *output_buf_len, int *w, int *h, bool flip = false); - const byte *getImagePal(const byte *image_data, size_t image_size); - void loadStrings(StringsTable &stringsTable, const byte *stringsPointer, size_t stringsLength); + bool decodeBGImage(const ByteArray &imageData, ByteArray &outputBuffer, int *w, int *h, bool flip = false); + const byte *getImagePal(const ByteArray &imageData) { + if (imageData.size() <= SAGA_IMAGE_HEADER_LEN) { + return NULL; + } + + return &imageData.front() + SAGA_IMAGE_HEADER_LEN; + } + void loadStrings(StringsTable &stringsTable, const ByteArray &stringsData); - const char *getObjectName(uint16 objectId); + const char *getObjectName(uint16 objectId) const; public: int processInput(); Point mousePos() const; - int getMouseClickCount() { + int getMouseClickCount() const { return _mouseClickCount; } @@ -586,7 +609,7 @@ public: return _leftMouseButtonPressed || _rightMouseButtonPressed; } - inline int ticksToMSec(int tick) { + inline int ticksToMSec(int tick) const { if (getGameId() == GID_ITE) return tick * 1000 / kScriptTimeTicksPerSecond; else @@ -617,9 +640,9 @@ public: bool isBigEndian() const; bool isMacResources() const; bool isSaga2() const { return getGameId() == GID_DINO || getGameId() == GID_FTA2; } - const GameResourceDescription *getResourceDescription(); + const GameResourceDescription *getResourceDescription() const; - const GameFontDescription *getFontDescription(int index); + const GameFontDescription *getFontDescription(int index) const; int getFontsCount() const; int getGameId() const; @@ -648,7 +671,7 @@ private: public: ColorId KnownColor2ColorId(KnownColor knownColor); void setTalkspeed(int talkspeed); - int getTalkspeed(); + int getTalkspeed() const; }; } // End of namespace Saga diff --git a/engines/saga/saveload.cpp b/engines/saga/saveload.cpp index 2740462dab..c5388d6878 100644 --- a/engines/saga/saveload.cpp +++ b/engines/saga/saveload.cpp @@ -82,7 +82,7 @@ bool SagaEngine::locateSaveFile(char *saveName, uint &titleNumber) { return false; } -uint SagaEngine::getNewSaveSlotNumber() { +uint SagaEngine::getNewSaveSlotNumber() const { uint i, j; bool found; for (i = 0; i < MAX_SAVES; i++) { @@ -240,9 +240,9 @@ void SagaEngine::save(const char *fileName, const char *saveName) { _actor->saveState(out); - out->writeSint16LE(_script->_commonBufferSize); + out->writeSint16LE(_script->_commonBuffer.size()); - out->write(_script->_commonBuffer, _script->_commonBufferSize); + out->write(_script->_commonBuffer.getBuffer(), _script->_commonBuffer.size()); // ISO map x, y coordinates for ITE if (getGameId() == GID_ITE) { @@ -282,7 +282,7 @@ void SagaEngine::load(const char *fileName) { _saveHeader.version = SWAP_BYTES_32(_saveHeader.version); } - debug(2, "Save version: %x", _saveHeader.version); + debug(2, "Save version: 0x%X", _saveHeader.version); if (_saveHeader.version < 4) warning("This savegame is not endian-safe. There may be problems"); @@ -351,7 +351,8 @@ void SagaEngine::load(const char *fileName) { _actor->loadState(in); commonBufferSize = in->readSint16LE(); - in->read(_script->_commonBuffer, commonBufferSize); + _script->_commonBuffer.resize(commonBufferSize); + in->read(_script->_commonBuffer.getBuffer(), commonBufferSize); if (getGameId() == GID_ITE) { mapx = in->readSint16LE(); diff --git a/engines/saga/scene.cpp b/engines/saga/scene.cpp index 2887d79693..8e9e4463ba 100644 --- a/engines/saga/scene.cpp +++ b/engines/saga/scene.cpp @@ -137,10 +137,9 @@ const char *SAGAResourceTypesString[] = { }; Scene::Scene(SagaEngine *vm) : _vm(vm) { - byte *sceneLUTPointer; - size_t sceneLUTLength; + ByteArray sceneLUTData; uint32 resourceId; - int i; + uint i; // Do nothing for SAGA2 games for now if (_vm->isSaga2()) { @@ -158,74 +157,62 @@ Scene::Scene(SagaEngine *vm) : _vm(vm) { // Load scene lookup table resourceId = _vm->_resource->convertResourceId(_vm->getResourceDescription()->sceneLUTResourceId); debug(3, "Loading scene LUT from resource %i", resourceId); - _vm->_resource->loadResource(_sceneContext, resourceId, sceneLUTPointer, sceneLUTLength); - if (sceneLUTLength == 0) { - error("Scene::Scene() sceneLUTLength == 0"); - } - _sceneCount = sceneLUTLength / 2; - _sceneLUT = (int *)malloc(_sceneCount * sizeof(*_sceneLUT)); - if (_sceneLUT == NULL) { - memoryError("Scene::Scene()"); + _vm->_resource->loadResource(_sceneContext, resourceId, sceneLUTData); + if (sceneLUTData.empty()) { + error("Scene::Scene() sceneLUT is empty"); } + _sceneLUT.resize(sceneLUTData.size() / 2); - MemoryReadStreamEndian readS(sceneLUTPointer, sceneLUTLength, _sceneContext->isBigEndian()); + ByteArrayReadStreamEndian readS(sceneLUTData, _sceneContext->isBigEndian()); - for (i = 0; i < _sceneCount; i++) { + for (i = 0; i < _sceneLUT.size(); i++) { _sceneLUT[i] = readS.readUint16(); debug(8, "sceneNumber %i has resourceId %i", i, _sceneLUT[i]); } - free(sceneLUTPointer); - #ifdef SAGA_DEBUG #define DUMP_SCENES_LEVEL 10 if (DUMP_SCENES_LEVEL <= gDebugLevel) { - uint j; int backUpDebugLevel = gDebugLevel; SAGAResourceTypes *types; int typesCount; SAGAResourceTypes resType; + SceneResourceDataArray resourceList; getResourceTypes(types, typesCount); - for (i = 0; i < _sceneCount; i++) { + for (i = 0; i < _sceneLUT.size(); i++) { gDebugLevel = -1; loadSceneDescriptor(_sceneLUT[i]); - loadSceneResourceList(_sceneDescription.resourceListResourceId); + loadSceneResourceList(_sceneDescription.resourceListResourceId, resourceList); gDebugLevel = backUpDebugLevel; debug(DUMP_SCENES_LEVEL, "Dump Scene: number %i, descriptor resourceId %i, resourceList resourceId %i", i, _sceneLUT[i], _sceneDescription.resourceListResourceId); - debug(DUMP_SCENES_LEVEL, "\tresourceListCount %i", (int)_resourceListCount); - for (j = 0; j < _resourceListCount; j++) { - if (_resourceList[j].resourceType >= typesCount) { - error("wrong resource type %i", _resourceList[j].resourceType); + debug(DUMP_SCENES_LEVEL, "\tresourceListCount %i", (int)resourceList.size()); + for (SceneResourceDataArray::iterator j = resourceList.begin(); j != resourceList.end(); ++j) { + if (j->resourceType >= typesCount) { + error("wrong resource type %i", j->resourceType); } - resType = types[_resourceList[j].resourceType]; + resType = types[j->resourceType]; - debug(DUMP_SCENES_LEVEL, "\t%s resourceId %i", SAGAResourceTypesString[resType], _resourceList[j].resourceId); + debug(DUMP_SCENES_LEVEL, "\t%s resourceId %i", SAGAResourceTypesString[resType], j->resourceId); } - free(_resourceList); } } #endif - debug(3, "LUT has %d entries.", _sceneCount); + debug(3, "LUT has %d entries.", _sceneLUT.size()); _sceneLoaded = false; _sceneNumber = 0; _chapterNumber = 0; _sceneResourceId = 0; _inGame = false; - _loadDescription = false; - memset(&_sceneDescription, 0, sizeof(_sceneDescription)); - _resourceListCount = 0; - _resourceList = NULL; + _sceneDescription.reset(); _sceneProc = NULL; _objectMap = new ObjectMap(_vm); _actionMap = new ObjectMap(_vm); - memset(&_bg, 0, sizeof(_bg)); - memset(&_bgMask, 0, sizeof(_bgMask)); } Scene::~Scene() { @@ -236,7 +223,6 @@ Scene::~Scene() { delete _actionMap; delete _objectMap; - free(_sceneLUT); } void Scene::getResourceTypes(SAGAResourceTypes *&types, int &typesCount) { @@ -281,7 +267,7 @@ void Scene::startScene() { event.type = kEvTOneshot; event.code = kCursorEvent; event.op = kEventHide; - _vm->_events->queue(&event); + _vm->_events->queue(event); switch (_vm->getGameId()) { case GID_ITE: @@ -528,8 +514,7 @@ void Scene::getSlopes(int &beginSlope, int &endSlope) { } void Scene::getBGInfo(BGInfo &bgInfo) { - bgInfo.buffer = _bg.buf; - bgInfo.bufferLength = _bg.buf_len; + bgInfo.buffer = _bg.buffer.getBuffer(); bgInfo.bounds.left = 0; bgInfo.bounds.top = 0; @@ -581,15 +566,14 @@ bool Scene::offscreenPath(Point &testPoint) { } -void Scene::getBGMaskInfo(int &width, int &height, byte *&buffer, size_t &bufferLength) { +void Scene::getBGMaskInfo(int &width, int &height, byte *&buffer) { if (!_bgMask.loaded) { error("Scene::getBGMaskInfo _bgMask not loaded"); } width = _bgMask.w; height = _bgMask.h; - buffer = _bgMask.buf; - bufferLength = _bgMask.buf_len; + buffer = _bgMask.buffer.getBuffer(); } void Scene::initDoorsState() { @@ -597,9 +581,8 @@ void Scene::initDoorsState() { } void Scene::loadScene(LoadSceneParams &loadSceneParams) { - size_t i; Event event; - Event *q_event; + EventColumns *eventColumns; static PalEntry current_pal[PAL_ENTRIES]; if (loadSceneParams.transitionType == kTransitionFade) @@ -610,7 +593,7 @@ void Scene::loadScene(LoadSceneParams &loadSceneParams) { event.code = kCursorEvent; event.op = kEventSetBusyCursor; event.time = 0; - _vm->_events->queue(&event); + _vm->_events->queue(event); _chapterPointsChanged = false; @@ -623,8 +606,8 @@ void Scene::loadScene(LoadSceneParams &loadSceneParams) { if (loadSceneParams.chapter == 6 || loadSceneParams.chapter == 8) _vm->_interface->setLeftPortrait(0); - _vm->_anim->freeCutawayList(); - _vm->_script->freeModules(); + _vm->_anim->clearCutawayList(); + _vm->_script->clearModules(); // deleteAllScenes(); @@ -659,8 +642,6 @@ void Scene::loadScene(LoadSceneParams &loadSceneParams) { error("Scene::loadScene(): Error, a scene is already loaded"); } - _loadDescription = true; - #ifdef ENABLE_IHNM if (_vm->getGameId() == GID_IHNM) { if (loadSceneParams.loadFlag == kLoadBySceneNumber) // When will we get rid of it? @@ -678,16 +659,6 @@ void Scene::loadScene(LoadSceneParams &loadSceneParams) { _sceneNumber = loadSceneParams.sceneDescriptor; _sceneResourceId = getSceneResourceId(_sceneNumber); break; - case kLoadByDescription: - _sceneNumber = -1; - _sceneResourceId = -1; - assert(loadSceneParams.sceneDescription != NULL); - assert(loadSceneParams.sceneDescription->resourceList != NULL); - _loadDescription = false; - _sceneDescription = *loadSceneParams.sceneDescription; - _resourceList = loadSceneParams.sceneDescription->resourceList; - _resourceListCount = loadSceneParams.sceneDescription->resourceListCount; - break; } debug(3, "Loading scene number %d:", _sceneNumber); @@ -702,34 +673,15 @@ void Scene::loadScene(LoadSceneParams &loadSceneParams) { } // Load scene descriptor and resource list resources - if (_loadDescription) { - debug(3, "Loading scene resource %i", _sceneResourceId); - - loadSceneDescriptor(_sceneResourceId); - - loadSceneResourceList(_sceneDescription.resourceListResourceId); - } else { - debug(3, "Loading memory scene resource"); - } + debug(3, "Loading scene resource %i", _sceneResourceId); - // Load resources from scene resource list - for (i = 0; i < _resourceListCount; i++) { - if (!_resourceList[i].invalid) { - _vm->_resource->loadResource(_sceneContext, _resourceList[i].resourceId, - _resourceList[i].buffer, _resourceList[i].size); + loadSceneDescriptor(_sceneResourceId); - - if (_resourceList[i].size >= 6) { - if (!memcmp(_resourceList[i].buffer, "DUMMY!", 6)) { - _resourceList[i].invalid = true; - warning("DUMMY resource %i", _resourceList[i].resourceId); - } - } - } - } + SceneResourceDataArray resourceList; + loadSceneResourceList(_sceneDescription.resourceListResourceId, resourceList); // Process resources from scene resource list - processSceneResources(); + processSceneResources(resourceList); if (_sceneDescription.flags & kSceneFlagISO) { _outsetSceneNumber = _sceneNumber; @@ -748,7 +700,7 @@ void Scene::loadScene(LoadSceneParams &loadSceneParams) { _sceneLoaded = true; - q_event = NULL; + eventColumns = NULL; if (loadSceneParams.transitionType == kTransitionFade) { @@ -762,7 +714,7 @@ void Scene::loadScene(LoadSceneParams &loadSceneParams) { event.time = 0; event.duration = kNormalFadeDuration; event.data = current_pal; - q_event = _vm->_events->queue(&event); + eventColumns = _vm->_events->queue(event); // set fade mode event.type = kEvTImmediate; @@ -771,7 +723,7 @@ void Scene::loadScene(LoadSceneParams &loadSceneParams) { event.param = kNoFade; event.time = 0; event.duration = 0; - q_event = _vm->_events->chain(q_event, &event); + _vm->_events->chain(eventColumns, event); // Display scene background, but stay with black palette event.type = kEvTImmediate; @@ -780,7 +732,7 @@ void Scene::loadScene(LoadSceneParams &loadSceneParams) { event.param = kEvPNoSetPalette; event.time = 0; event.duration = 0; - q_event = _vm->_events->chain(q_event, &event); + _vm->_events->chain(eventColumns, event); } @@ -796,7 +748,7 @@ void Scene::loadScene(LoadSceneParams &loadSceneParams) { event.param4 = _sceneNumber; // Object event.param5 = loadSceneParams.actorsEntrance; // With Object event.param6 = 0; // Actor - q_event = _vm->_events->chain(q_event, &event); + eventColumns = _vm->_events->chain(eventColumns, event); } if (loadSceneParams.transitionType == kTransitionFade) { @@ -808,7 +760,7 @@ void Scene::loadScene(LoadSceneParams &loadSceneParams) { event.param = kFadeIn; event.time = 0; event.duration = 0; - q_event = _vm->_events->chain(q_event, &event); + eventColumns = _vm->_events->chain(eventColumns, event); // Fade in from black to the scene background palette event.type = kEvTImmediate; @@ -817,7 +769,7 @@ void Scene::loadScene(LoadSceneParams &loadSceneParams) { event.time = 0; event.duration = kNormalFadeDuration; event.data = _bg.pal; - q_event = _vm->_events->chain(q_event, &event); + _vm->_events->chain(eventColumns, event); // set fade mode event.type = kEvTImmediate; @@ -826,7 +778,7 @@ void Scene::loadScene(LoadSceneParams &loadSceneParams) { event.param = kNoFade; event.time = 0; event.duration = 0; - q_event = _vm->_events->chain(q_event, &event); + _vm->_events->chain(eventColumns, event); } if (loadSceneParams.sceneProc == NULL) { @@ -845,13 +797,13 @@ void Scene::loadScene(LoadSceneParams &loadSceneParams) { event.param2 = MUSIC_DEFAULT; event.op = kEventPlay; event.time = 0; - _vm->_events->queue(&event); + _vm->_events->queue(event); } else { event.type = kEvTOneshot; event.code = kMusicEvent; event.op = kEventStop; event.time = 0; - _vm->_events->queue(&event); + _vm->_events->queue(event); } } @@ -861,14 +813,14 @@ void Scene::loadScene(LoadSceneParams &loadSceneParams) { event.op = kEventDisplay; event.param = kEvPSetPalette; event.time = 0; - _vm->_events->queue(&event); + _vm->_events->queue(event); // Begin palette cycle animation if present event.type = kEvTOneshot; event.code = kPalAnimEvent; event.op = kEventCycleStart; event.time = 0; - q_event = _vm->_events->queue(&event); + _vm->_events->queue(event); // Start the scene main script if (_sceneDescription.sceneScriptEntrypointNumber > 0) { @@ -882,7 +834,7 @@ void Scene::loadScene(LoadSceneParams &loadSceneParams) { event.param4 = _sceneNumber; // Object event.param5 = loadSceneParams.actorsEntrance; // With Object event.param6 = 0; // Actor - _vm->_events->queue(&event); + _vm->_events->queue(event); } debug(3, "Scene started"); @@ -905,7 +857,7 @@ void Scene::loadScene(LoadSceneParams &loadSceneParams) { event.code = kInterfaceEvent; event.op = kEventActivate; event.time = 0; - _vm->_events->queue(&event); + _vm->_events->queue(event); } // Change the cursor back to a crosshair in IHNM @@ -913,23 +865,22 @@ void Scene::loadScene(LoadSceneParams &loadSceneParams) { event.code = kCursorEvent; event.op = kEventSetNormalCursor; event.time = 0; - _vm->_events->queue(&event); + _vm->_events->queue(event); } void Scene::loadSceneDescriptor(uint32 resourceId) { - byte *sceneDescriptorData; - size_t sceneDescriptorDataLength; + ByteArray sceneDescriptorData; - memset(&_sceneDescription, 0, sizeof(_sceneDescription)); + _sceneDescription.reset(); if (resourceId == 0) { return; } - _vm->_resource->loadResource(_sceneContext, resourceId, sceneDescriptorData, sceneDescriptorDataLength); + _vm->_resource->loadResource(_sceneContext, resourceId, sceneDescriptorData); - if (sceneDescriptorDataLength == 16) { - MemoryReadStreamEndian readS(sceneDescriptorData, sceneDescriptorDataLength, _sceneContext->isBigEndian()); + if (sceneDescriptorData.size() == 16) { + ByteArrayReadStreamEndian readS(sceneDescriptorData, _sceneContext->isBigEndian()); _sceneDescription.flags = readS.readSint16(); _sceneDescription.resourceListResourceId = readS.readSint16(); @@ -940,53 +891,44 @@ void Scene::loadSceneDescriptor(uint32 resourceId) { _sceneDescription.startScriptEntrypointNumber = readS.readUint16(); _sceneDescription.musicResourceId = readS.readSint16(); } - - free(sceneDescriptorData); } -void Scene::loadSceneResourceList(uint32 resourceId) { - byte *resourceListData; - size_t resourceListDataLength; - size_t i; +void Scene::loadSceneResourceList(uint32 resourceId, SceneResourceDataArray &resourceList) { + ByteArray resourceListData; - _resourceListCount = 0; - _resourceList = NULL; + resourceList.clear(); if (resourceId == 0) { return; } // Load the scene resource table - _vm->_resource->loadResource(_sceneContext, resourceId, resourceListData, resourceListDataLength); + _vm->_resource->loadResource(_sceneContext, resourceId, resourceListData); - if ((resourceListDataLength % SAGA_RESLIST_ENTRY_LEN) == 0) { - MemoryReadStreamEndian readS(resourceListData, resourceListDataLength, _sceneContext->isBigEndian()); + if ((resourceListData.size() % SAGA_RESLIST_ENTRY_LEN) == 0) { + ByteArrayReadStreamEndian readS(resourceListData, _sceneContext->isBigEndian()); // Allocate memory for scene resource list - _resourceListCount = resourceListDataLength / SAGA_RESLIST_ENTRY_LEN; - debug(3, "Scene resource list contains %i entries", (int)_resourceListCount); - _resourceList = (SceneResourceData *)calloc(_resourceListCount, sizeof(*_resourceList)); + resourceList.resize(resourceListData.size() / SAGA_RESLIST_ENTRY_LEN); + debug(3, "Scene resource list contains %i entries", (int)resourceList.size()); // Load scene resource list from raw scene // resource table debug(3, "Loading scene resource list"); - for (i = 0; i < _resourceListCount; i++) { - _resourceList[i].resourceId = readS.readUint16(); - _resourceList[i].resourceType = readS.readUint16(); + for (SceneResourceDataArray::iterator resource = resourceList.begin(); resource != resourceList.end(); ++resource) { + resource->resourceId = readS.readUint16(); + resource->resourceType = readS.readUint16(); // demo version may contain invalid resourceId - _resourceList[i].invalid = !_sceneContext->validResourceId(_resourceList[i].resourceId); + resource->invalid = !_sceneContext->validResourceId(resource->resourceId); } } - free(resourceListData); } -void Scene::processSceneResources() { - byte *resourceData; - size_t resourceDataLength; +void Scene::processSceneResources(SceneResourceDataArray &resourceList) { + ByteArray resourceData; const byte *palPointer; - size_t i; SAGAResourceTypes *types = 0; int typesCount = 0; SAGAResourceTypes resType; @@ -994,22 +936,33 @@ void Scene::processSceneResources() { getResourceTypes(types, typesCount); // Process the scene resource list - for (i = 0; i < _resourceListCount; i++) { - if (_resourceList[i].invalid) { + for (SceneResourceDataArray::iterator resource = resourceList.begin(); resource != resourceList.end(); ++resource) { + if (resource->invalid) { + continue; + } + _vm->_resource->loadResource(_sceneContext, resource->resourceId, resourceData); + + + if (resourceData.size() >= 6) { + if (!memcmp(resourceData.getBuffer(), "DUMMY!", 6)) { + resource->invalid = true; + warning("DUMMY resource %i", resource->resourceId); + } + } + + if (resource->invalid) { continue; } - resourceData = _resourceList[i].buffer; - resourceDataLength = _resourceList[i].size; - if (_resourceList[i].resourceType >= typesCount) { - error("Scene::processSceneResources() wrong resource type %i", _resourceList[i].resourceType); + if (resource->resourceType >= typesCount) { + error("Scene::processSceneResources() wrong resource type %i", resource->resourceType); } - resType = types[_resourceList[i].resourceType]; + resType = types[resource->resourceType]; switch (resType) { case SAGA_UNKNOWN: - warning("UNKNOWN resourceType %i", _resourceList[i].resourceType); + warning("UNKNOWN resourceType %i", resource->resourceType); break; case SAGA_ACTOR: //for (a = actorsInScene; a; a = a->nextInScene) @@ -1027,20 +980,16 @@ void Scene::processSceneResources() { } debug(3, "Loading background resource."); - _bg.res_buf = resourceData; - _bg.res_len = resourceDataLength; - _bg.loaded = 1; - - if (_vm->decodeBGImage(_bg.res_buf, - _bg.res_len, - &_bg.buf, - &_bg.buf_len, + + if (!_vm->decodeBGImage(resourceData, + _bg.buffer, &_bg.w, - &_bg.h) != SUCCESS) { - error("Scene::processSceneResources() Error loading background resource %i", _resourceList[i].resourceId); + &_bg.h)) { + error("Scene::processSceneResources() Error loading background resource %i", resource->resourceId); } + _bg.loaded = true; - palPointer = _vm->getImagePal(_bg.res_buf, _bg.res_len); + palPointer = _vm->getImagePal(resourceData); memcpy(_bg.pal, palPointer, sizeof(_bg.pal)); break; case SAGA_BG_MASK: // Scene background mask resource @@ -1048,30 +997,27 @@ void Scene::processSceneResources() { error("Scene::ProcessSceneResources(): Duplicate background mask resource encountered"); } debug(3, "Loading BACKGROUND MASK resource."); - _bgMask.res_buf = resourceData; - _bgMask.res_len = resourceDataLength; - _bgMask.loaded = 1; - _vm->decodeBGImage(_bgMask.res_buf, _bgMask.res_len, &_bgMask.buf, - &_bgMask.buf_len, &_bgMask.w, &_bgMask.h, true); + _vm->decodeBGImage(resourceData, _bgMask.buffer, &_bgMask.w, &_bgMask.h, true); + _bgMask.loaded = true; // At least in ITE the mask needs to be clipped. _bgMask.w = MIN(_bgMask.w, _vm->getDisplayInfo().width); _bgMask.h = MIN(_bgMask.h, getHeight()); - debug(4, "BACKGROUND MASK width=%d height=%d length=%d", _bgMask.w, _bgMask.h, (int)_bgMask.buf_len); + debug(4, "BACKGROUND MASK width=%d height=%d length=%d", _bgMask.w, _bgMask.h, _bgMask.buffer.size()); break; case SAGA_STRINGS: debug(3, "Loading scene strings resource..."); - _vm->loadStrings(_sceneStrings, resourceData, resourceDataLength); + _vm->loadStrings(_sceneStrings, resourceData); break; case SAGA_OBJECT_MAP: debug(3, "Loading object map resource..."); - _objectMap->load(resourceData, resourceDataLength); + _objectMap->load(resourceData); break; case SAGA_ACTION_MAP: debug(3, "Loading action map resource..."); - _actionMap->load(resourceData, resourceDataLength); + _actionMap->load(resourceData); break; case SAGA_ISO_IMAGES: if (!(_sceneDescription.flags & kSceneFlagISO)) { @@ -1080,7 +1026,7 @@ void Scene::processSceneResources() { debug(3, "Loading isometric images resource."); - _vm->_isoMap->loadImages(resourceData, resourceDataLength); + _vm->_isoMap->loadImages(resourceData); break; case SAGA_ISO_MAP: if (!(_sceneDescription.flags & kSceneFlagISO)) { @@ -1089,7 +1035,7 @@ void Scene::processSceneResources() { debug(3, "Loading isometric map resource."); - _vm->_isoMap->loadMap(resourceData, resourceDataLength); + _vm->_isoMap->loadMap(resourceData); break; case SAGA_ISO_PLATFORMS: if (!(_sceneDescription.flags & kSceneFlagISO)) { @@ -1098,7 +1044,7 @@ void Scene::processSceneResources() { debug(3, "Loading isometric platforms resource."); - _vm->_isoMap->loadPlatforms(resourceData, resourceDataLength); + _vm->_isoMap->loadPlatforms(resourceData); break; case SAGA_ISO_METATILES: if (!(_sceneDescription.flags & kSceneFlagISO)) { @@ -1107,20 +1053,20 @@ void Scene::processSceneResources() { debug(3, "Loading isometric metatiles resource."); - _vm->_isoMap->loadMetaTiles(resourceData, resourceDataLength); + _vm->_isoMap->loadMetaTiles(resourceData); break; case SAGA_ANIM: { - uint16 animId = _resourceList[i].resourceType - 14; + uint16 animId = resource->resourceType - 14; debug(3, "Loading animation resource animId=%i", animId); - _vm->_anim->load(animId, resourceData, resourceDataLength); + _vm->_anim->load(animId, resourceData); } break; case SAGA_ENTRY: debug(3, "Loading entry list resource..."); - loadSceneEntryList(resourceData, resourceDataLength); + loadSceneEntryList(resourceData); break; case SAGA_ISO_MULTI: if (!(_sceneDescription.flags & kSceneFlagISO)) { @@ -1129,23 +1075,23 @@ void Scene::processSceneResources() { debug(3, "Loading isometric multi resource."); - _vm->_isoMap->loadMulti(resourceData, resourceDataLength); + _vm->_isoMap->loadMulti(resourceData); break; case SAGA_PAL_ANIM: debug(3, "Loading palette animation resource."); - _vm->_palanim->loadPalAnim(resourceData, resourceDataLength); + _vm->_palanim->loadPalAnim(resourceData); break; case SAGA_FACES: if (_vm->getGameId() == GID_ITE) - _vm->_interface->loadScenePortraits(_resourceList[i].resourceId); + _vm->_interface->loadScenePortraits(resource->resourceId); break; case SAGA_PALETTE: { PalEntry pal[PAL_ENTRIES]; - byte *palPtr = resourceData; + byte *palPtr = resourceData.getBuffer(); - if (resourceDataLength < 3 * PAL_ENTRIES) - error("Too small scene palette %i", (int)resourceDataLength); + if (resourceData.size() < 3 * PAL_ENTRIES) + error("Too small scene palette %i", (int)resourceData.size()); for (uint16 c = 0; c < PAL_ENTRIES; c++) { pal[c].red = *palPtr++; @@ -1156,7 +1102,7 @@ void Scene::processSceneResources() { } break; default: - error("Scene::ProcessSceneResources() Encountered unknown resource type %i", _resourceList[i].resourceType); + error("Scene::ProcessSceneResources() Encountered unknown resource type %i", resource->resourceType); break; } } @@ -1184,7 +1130,6 @@ void Scene::draw() { void Scene::endScene() { Rect rect; - size_t i; if (!_sceneLoaded) return; @@ -1222,37 +1167,28 @@ void Scene::endScene() { // Free scene background if (_bg.loaded) { - free(_bg.buf); - _bg.loaded = 0; + _bg.buffer.clear(); + _bg.loaded = false; } // Free scene background mask if (_bgMask.loaded) { - free(_bgMask.buf); - _bgMask.loaded = 0; - } - - // Free scene resource list - for (i = 0; i < _resourceListCount; i++) { - free(_resourceList[i].buffer); - } - - if (_loadDescription) { - free(_resourceList); + _bgMask.buffer.clear(); + _bgMask.loaded = false; } // Free animation info list _vm->_anim->reset(); - _vm->_palanim->freePalAnim(); + _vm->_palanim->clear(); - _objectMap->freeMem(); - _actionMap->freeMem(); - _entryList.freeMem(); - _sceneStrings.freeMem(); + _objectMap->clear(); + _actionMap->clear(); + _entryList.clear(); + _sceneStrings.clear(); if (_vm->getGameId() == GID_ITE) - _vm->_isoMap->freeMem(); + _vm->_isoMap->clear(); _vm->_events->clearList(); _textList.clear(); @@ -1275,7 +1211,7 @@ void Scene::restoreScene() { event.param = kEvPNoSetPalette; event.time = 0; event.duration = 0; - _vm->_events->queue(&event); + _vm->_events->queue(event); _vm->_gfx->showCursor(true); } @@ -1285,7 +1221,7 @@ void Scene::cmdSceneChange(int argc, const char **argv) { scene_num = atoi(argv[1]); - if ((scene_num < 1) || (scene_num >= _sceneCount)) { + if ((scene_num < 1) || (uint(scene_num) >= _sceneLUT.size())) { _vm->_console->DebugPrintf("Invalid scene number.\n"); return; } @@ -1303,34 +1239,29 @@ void Scene::cmdObjectMapInfo() { _objectMap->cmdInfo(); } -void Scene::loadSceneEntryList(const byte* resourcePointer, size_t resourceLength) { - int i; - - _entryList.entryListCount = resourceLength / 8; - - MemoryReadStreamEndian readS(resourcePointer, resourceLength, _sceneContext->isBigEndian()); +void Scene::loadSceneEntryList(const ByteArray &resourceData) { + uint i; + if (!_entryList.empty()) { + error("Scene::loadSceneEntryList entryList not empty"); + } - if (_entryList.entryList) - error("Scene::loadSceneEntryList entryList != NULL"); + _entryList.resize(resourceData.size() / 8); - _entryList.entryList = (SceneEntry *) malloc(_entryList.entryListCount * sizeof(*_entryList.entryList)); - if (_entryList.entryList == NULL) { - memoryError("Scene::loadSceneEntryList"); - } + ByteArrayReadStreamEndian readS(resourceData, _sceneContext->isBigEndian()); - for (i = 0; i < _entryList.entryListCount; i++) { - _entryList.entryList[i].location.x = readS.readSint16(); - _entryList.entryList[i].location.y = readS.readSint16(); - _entryList.entryList[i].location.z = readS.readSint16(); - _entryList.entryList[i].facing = readS.readUint16(); + for (i = 0; i < _entryList.size(); i++) { + _entryList[i].location.x = readS.readSint16(); + _entryList[i].location.y = readS.readSint16(); + _entryList[i].location.z = readS.readSint16(); + _entryList[i].facing = readS.readUint16(); } } void Scene::clearPlacard() { static PalEntry cur_pal[PAL_ENTRIES]; Event event; - Event *q_event; + EventColumns *eventColumns; _vm->_interface->setFadeMode(kFadeOut); @@ -1342,7 +1273,7 @@ void Scene::clearPlacard() { event.time = 0; event.duration = kNormalFadeDuration; event.data = cur_pal; - q_event = _vm->_events->queue(&event); + eventColumns = _vm->_events->queue(event); // set fade mode event.type = kEvTImmediate; @@ -1351,14 +1282,14 @@ void Scene::clearPlacard() { event.param = kNoFade; event.time = 0; event.duration = 0; - q_event = _vm->_events->chain(q_event, &event); + _vm->_events->chain(eventColumns, event); if (_vm->getGameId() == GID_ITE) { event.type = kEvTOneshot; event.code = kTextEvent; event.op = kEventRemove; event.data = _vm->_script->getPlacardTextEntry(); - q_event = _vm->_events->chain(q_event, &event); + _vm->_events->chain(eventColumns, event); } else { _vm->_scene->_textList.clear(); } @@ -1368,7 +1299,7 @@ void Scene::clearPlacard() { event.op = kEventRestoreMode; event.time = 0; event.duration = 0; - q_event = _vm->_events->chain(q_event, &event); + _vm->_events->chain(eventColumns, event); #ifdef ENABLE_IHNM if (_vm->getGameId() == GID_IHNM) { @@ -1379,7 +1310,7 @@ void Scene::clearPlacard() { event.param = kPanelMain; event.time = 0; event.duration = 0; - q_event = _vm->_events->chain(q_event, &event); + _vm->_events->chain(eventColumns, event); } #endif @@ -1390,7 +1321,7 @@ void Scene::clearPlacard() { event.param = kEvPNoSetPalette; event.time = 0; event.duration = 0; - q_event = _vm->_events->chain(q_event, &event); + _vm->_events->chain(eventColumns, event); // set fade mode event.type = kEvTImmediate; @@ -1399,7 +1330,7 @@ void Scene::clearPlacard() { event.param = kFadeIn; event.time = 0; event.duration = 0; - q_event = _vm->_events->chain(q_event, &event); + _vm->_events->chain(eventColumns, event); // Fade in from black to the scene background palette event.type = kEvTImmediate; @@ -1408,7 +1339,7 @@ void Scene::clearPlacard() { event.time = 0; event.duration = kNormalFadeDuration; event.data = _bg.pal; - q_event = _vm->_events->chain(q_event, &event); + _vm->_events->chain(eventColumns, event); // set fade mode event.type = kEvTImmediate; @@ -1417,18 +1348,18 @@ void Scene::clearPlacard() { event.param = kNoFade; event.time = 0; event.duration = 0; - q_event = _vm->_events->chain(q_event, &event); + _vm->_events->chain(eventColumns, event); event.type = kEvTOneshot; event.code = kCursorEvent; event.op = kEventShow; - q_event = _vm->_events->chain(q_event, &event); + _vm->_events->chain(eventColumns, event); event.type = kEvTOneshot; event.code = kScriptEvent; event.op = kEventThreadWake; event.param = kWaitTypePlacard; - q_event = _vm->_events->chain(q_event, &event); + _vm->_events->chain(eventColumns, event); } #ifdef ENABLE_IHNM @@ -1439,7 +1370,7 @@ void Scene::showPsychicProfile(const char *text) { PalEntry *pal; TextListEntry textEntry; Event event; - Event *q_event; + EventColumns *eventColumns; if (_vm->_interface->getMode() == kPanelPlacard) return; @@ -1453,7 +1384,7 @@ void Scene::showPsychicProfile(const char *text) { event.type = kEvTOneshot; event.code = kCursorEvent; event.op = kEventHide; - q_event = _vm->_events->queue(&event); + eventColumns = _vm->_events->queue(event); _vm->_interface->setFadeMode(kFadeOut); @@ -1465,7 +1396,7 @@ void Scene::showPsychicProfile(const char *text) { event.time = 0; event.duration = kNormalFadeDuration; event.data = cur_pal; - q_event = _vm->_events->chain(q_event, &event); + _vm->_events->chain(eventColumns, event); // set fade mode event.type = kEvTImmediate; @@ -1474,17 +1405,17 @@ void Scene::showPsychicProfile(const char *text) { event.param = kNoFade; event.time = 0; event.duration = 0; - q_event = _vm->_events->chain(q_event, &event); + _vm->_events->chain(eventColumns, event); event.type = kEvTOneshot; event.code = kInterfaceEvent; event.op = kEventClearStatus; - q_event = _vm->_events->chain(q_event, &event); + _vm->_events->chain(eventColumns, event); // Set the background and palette for the psychic profile event.type = kEvTOneshot; event.code = kPsychicProfileBgEvent; - q_event = _vm->_events->chain(q_event, &event); + _vm->_events->chain(eventColumns, event); _vm->_scene->_textList.clear(); @@ -1507,7 +1438,7 @@ void Scene::showPsychicProfile(const char *text) { event.code = kTextEvent; event.op = kEventDisplay; event.data = _psychicProfileTextEntry; - q_event = _vm->_events->chain(q_event, &event); + _vm->_events->chain(eventColumns, event); } _vm->_scene->getBGPal(pal); @@ -1518,13 +1449,13 @@ void Scene::showPsychicProfile(const char *text) { event.time = 0; event.duration = kNormalFadeDuration; event.data = pal; - q_event = _vm->_events->chain(q_event, &event); + _vm->_events->chain(eventColumns, event); event.type = kEvTOneshot; event.code = kScriptEvent; event.op = kEventThreadWake; event.param = kWaitTypePlacard; - q_event = _vm->_events->chain(q_event, &event); + _vm->_events->chain(eventColumns, event); } void Scene::clearPsychicProfile() { diff --git a/engines/saga/scene.h b/engines/saga/scene.h index 0131e01abb..8d48e71445 100644 --- a/engines/saga/scene.h +++ b/engines/saga/scene.h @@ -32,6 +32,7 @@ #include "saga/actor.h" #include "saga/interface.h" #include "saga/puzzle.h" +#include "saga/events.h" namespace Saga { @@ -55,8 +56,6 @@ namespace Saga { class ObjectMap; -struct Event; - enum SceneFlags { kSceneFlagISO = 1, kSceneFlagShowCursor = 2 @@ -74,7 +73,6 @@ enum FTA2Endings { struct BGInfo { Rect bounds; byte *buffer; - size_t bufferLength; }; typedef int (SceneProc) (int, void *); @@ -112,11 +110,14 @@ enum SAGAResourceTypes { struct SceneResourceData { uint32 resourceId; int resourceType; - byte *buffer; - size_t size; bool invalid; + + SceneResourceData() : resourceId(0), resourceType(0), invalid(false) { + } }; +typedef Common::Array<SceneResourceData> SceneResourceDataArray; + #define SAGA_SCENE_DESC_LEN 16 struct SceneDescription { @@ -128,47 +129,31 @@ struct SceneDescription { uint16 sceneScriptEntrypointNumber; uint16 startScriptEntrypointNumber; int16 musicResourceId; - SceneResourceData *resourceList; - size_t resourceListCount; + + void reset() { + flags = resourceListResourceId = endSlope = beginSlope = scriptModuleNumber = sceneScriptEntrypointNumber = startScriptEntrypointNumber = musicResourceId = 0; + } }; struct SceneEntry { Location location; - int facing; + uint16 facing; }; -struct SceneEntryList { - SceneEntry *entryList; - int entryListCount; - - const SceneEntry * getEntry(int index) { - if ((index < 0) || (index >= entryListCount)) { - error("SceneEntryList::getEntry wrong index (%d)", index); - } - return &entryList[index]; - } - void freeMem() { - free(entryList); - memset(this, 0, sizeof(*this)); - } - SceneEntryList() { - memset(this, 0, sizeof(*this)); - } - ~SceneEntryList() { - freeMem(); - } +class SceneEntryList : public Common::Array<SceneEntry> { }; struct SceneImage { - int loaded; + bool loaded; int w; int h; int p; - byte *buf; - size_t buf_len; - byte *res_buf; - size_t res_len; + ByteArray buffer; PalEntry pal[256]; + + SceneImage() : loaded(false), w(0), h(0), p(0) { + memset(pal, 0, sizeof(pal)); + } }; @@ -179,14 +164,12 @@ enum SceneTransitionType { enum SceneLoadFlags { kLoadByResourceId, - kLoadBySceneNumber, - kLoadByDescription + kLoadBySceneNumber }; struct LoadSceneParams { int32 sceneDescriptor; SceneLoadFlags loadFlag; - SceneDescription* sceneDescription; SceneProc *sceneProc; bool sceneSkipTarget; SceneTransitionType transitionType; @@ -248,8 +231,8 @@ class Scene { void skipScene(); void endScene(); void restoreScene(); - void queueScene(LoadSceneParams *sceneQueue) { - _sceneQueue.push_back(*sceneQueue); + void queueScene(const LoadSceneParams &sceneQueue) { + _sceneQueue.push_back(sceneQueue); } void draw(); @@ -258,7 +241,7 @@ class Scene { bool isInIntro() { return !_inGame; } const Rect& getSceneClip() const { return _sceneClip; } - void getBGMaskInfo(int &width, int &height, byte *&buffer, size_t &bufferLength); + void getBGMaskInfo(int &width, int &height, byte *&buffer); int isBGMaskPresent() { return _bgMask.loaded; } int getBGMaskType(const Point &testPoint) { @@ -274,7 +257,7 @@ class Scene { } #endif - return (_bgMask.buf[offset] >> 4) & 0x0f; + return (_bgMask.buffer[offset] >> 4) & 0x0f; } bool validBGMaskPoint(const Point &testPoint) { @@ -325,7 +308,7 @@ class Scene { bool isSceneLoaded() const { return _sceneLoaded; } - int getSceneResourceId(int sceneNumber) { + uint16 getSceneResourceId(int sceneNumber) { #ifdef SCENE_DEBUG if ((sceneNumber < 0) || (sceneNumber >= _sceneCount)) { error("getSceneResourceId: wrong sceneNumber %i", sceneNumber); @@ -376,17 +359,16 @@ class Scene { private: void loadScene(LoadSceneParams &loadSceneParams); void loadSceneDescriptor(uint32 resourceId); - void loadSceneResourceList(uint32 resourceId); - void loadSceneEntryList(const byte* resourcePointer, size_t resourceLength); - void processSceneResources(); + void loadSceneResourceList(uint32 resourceId, SceneResourceDataArray &resourceList); + void loadSceneEntryList(const ByteArray &resourceData); + void processSceneResources(SceneResourceDataArray &resourceList); void getResourceTypes(SAGAResourceTypes *&types, int &typesCount); SagaEngine *_vm; ResourceContext *_sceneContext; - int *_sceneLUT; - int _sceneCount; + Common::Array<uint16> _sceneLUT; SceneQueueList _sceneQueue; bool _sceneLoaded; int _currentProtag; @@ -398,10 +380,7 @@ class Scene { int _currentMusicRepeat; bool _chapterPointsChanged; bool _inGame; - bool _loadDescription; SceneDescription _sceneDescription; - size_t _resourceListCount; - SceneResourceData *_resourceList; SceneProc *_sceneProc; SceneImage _bg; SceneImage _bgMask; @@ -456,8 +435,8 @@ class Scene { static int SC_ITEIntroFaireTentProc(int param, void *refCon); private: - Event *ITEQueueDialogue(Event *q_event, int n_dialogues, const IntroDialogue dialogue[]); - Event *ITEQueueCredits(int delta_time, int duration, int n_credits, const IntroCredit credits[]); + EventColumns *ITEQueueDialogue(EventColumns *eventColumns, int n_dialogues, const IntroDialogue dialogue[]); + EventColumns *ITEQueueCredits(int delta_time, int duration, int n_credits, const IntroCredit credits[]); int ITEIntroAnimProc(int param); int ITEIntroCave1Proc(int param); int ITEIntroCave2Proc(int param); diff --git a/engines/saga/script.cpp b/engines/saga/script.cpp index b0e20da48c..3ae2f19e1b 100644 --- a/engines/saga/script.cpp +++ b/engines/saga/script.cpp @@ -46,12 +46,11 @@ namespace Saga { SAGA1Script::SAGA1Script(SagaEngine *vm) : Script(vm) { ResourceContext *resourceContext; - byte *resourcePointer; - size_t resourceLength; + ByteArray resourceData; int prevTell; - int i, j; - byte *stringsPointer; - size_t stringsLength; + uint ui; + int j; + ByteArray stringsData; //initialize member variables _abortEnabled = true; @@ -67,9 +66,7 @@ SAGA1Script::SAGA1Script(SagaEngine *vm) : Script(vm) { _pointerObject = ID_NOTHING; _staticSize = 0; - _commonBufferSize = COMMON_BUFFER_SIZE; - _commonBuffer = (byte*)malloc(_commonBufferSize); - memset(_commonBuffer, 0, _commonBufferSize); + _commonBuffer.resize(COMMON_BUFFER_SIZE); debug(8, "Initializing scripting subsystem"); // Load script resource file context @@ -86,47 +83,41 @@ SAGA1Script::SAGA1Script(SagaEngine *vm) : Script(vm) { uint32 scriptResourceId = 0; scriptResourceId = _vm->getResourceDescription()->moduleLUTResourceId; debug(3, "Loading module LUT from resource %i", scriptResourceId); - _vm->_resource->loadResource(resourceContext, scriptResourceId, resourcePointer, resourceLength); + _vm->_resource->loadResource(resourceContext, scriptResourceId, resourceData); // Create logical script LUT from resource - if (resourceLength % 22 == 0) { // ITE CD + if (resourceData.size() % 22 == 0) { // ITE CD _modulesLUTEntryLen = 22; - } else if (resourceLength % 16 == 0) { // ITE disk, IHNM + } else if (resourceData.size() % 16 == 0) { // ITE disk, IHNM _modulesLUTEntryLen = 16; } else { - error("Script::Script() Invalid script lookup table length (%i)", (int)resourceLength); + error("Script::Script() Invalid script lookup table length (%i)", (int)resourceData.size()); } // Calculate number of entries - _modulesCount = resourceLength / _modulesLUTEntryLen; + int modulesCount = resourceData.size() / _modulesLUTEntryLen; - debug(3, "LUT has %i entries", _modulesCount); + debug(3, "LUT has %i entries", modulesCount); // Allocate space for logical LUT - _modules = (ModuleData *)malloc(_modulesCount * sizeof(*_modules)); - if (_modules == NULL) { - memoryError("Script::Script()"); - } + _modules.resize(modulesCount); // Convert LUT resource to logical LUT - MemoryReadStreamEndian scriptS(resourcePointer, resourceLength, resourceContext->isBigEndian()); - for (i = 0; i < _modulesCount; i++) { - memset(&_modules[i], 0, sizeof(ModuleData)); + ByteArrayReadStreamEndian scriptS(resourceData, resourceContext->isBigEndian()); + for (ui = 0; ui < _modules.size(); ui++) { prevTell = scriptS.pos(); - _modules[i].scriptResourceId = scriptS.readUint16(); - _modules[i].stringsResourceId = scriptS.readUint16(); - _modules[i].voicesResourceId = scriptS.readUint16(); + _modules[ui].scriptResourceId = scriptS.readUint16(); + _modules[ui].stringsResourceId = scriptS.readUint16(); + _modules[ui].voicesResourceId = scriptS.readUint16(); // Skip the unused portion of the structure for (j = scriptS.pos(); j < prevTell + _modulesLUTEntryLen; j++) { if (scriptS.readByte() != 0) - warning("Unused scriptLUT part isn't really unused for LUT %d (pos: %d)", i, j); + warning("Unused scriptLUT part isn't really unused for LUT %d (pos: %d)", ui, j); } } - free(resourcePointer); - // TODO // // In ITE, the "main strings" resource contains both the verb strings @@ -135,10 +126,9 @@ SAGA1Script::SAGA1Script(SagaEngine *vm) : Script(vm) { // In IHNM, the "main strings" contains the verb strings, but not the // object names. At least, I think that's the case. - _vm->_resource->loadResource(resourceContext, _vm->getResourceDescription()->mainStringsResourceId, stringsPointer, stringsLength); + _vm->_resource->loadResource(resourceContext, _vm->getResourceDescription()->mainStringsResourceId, stringsData); - _vm->loadStrings(_mainStrings, stringsPointer, stringsLength); - free(stringsPointer); + _vm->loadStrings(_mainStrings, stringsData); setupScriptOpcodeList(); @@ -157,19 +147,10 @@ SAGA1Script::SAGA1Script(SagaEngine *vm) : Script(vm) { SAGA1Script::~SAGA1Script() { debug(8, "Shutting down scripting subsystem."); - - _mainStrings.freeMem(); - _globalVoiceLUT.freeMem(); - - freeModules(); - free(_modules); - - free(_commonBuffer); } SAGA2Script::SAGA2Script(SagaEngine *vm) : Script(vm) { - byte *resourcePointer; - size_t resourceLength; + ByteArray resourceData; debug(8, "Initializing scripting subsystem"); // Load script resource file context @@ -184,14 +165,14 @@ SAGA2Script::SAGA2Script(SagaEngine *vm) : Script(vm) { if (entryNum < 0) error("Unable to locate the script's export segment"); debug(3, "Loading module LUT from resource %i", entryNum); - _vm->_resource->loadResource(_scriptContext, (uint32)entryNum, resourcePointer, resourceLength); + _vm->_resource->loadResource(_scriptContext, (uint32)entryNum, resourceData); _modulesLUTEntryLen = sizeof(uint32); // Calculate number of entries - _modulesCount = resourceLength / _modulesLUTEntryLen + 1; + int modulesCount = resourceData.size() / _modulesLUTEntryLen + 1; - debug(3, "LUT has %i entries", _modulesCount); + debug(3, "LUT has %i entries", modulesCount); // Script data segment /* @@ -994,8 +975,8 @@ void Script::opSpeak(SCRIPTOP_PARAMS) { } } else { #endif - if (thread->_voiceLUT->voicesCount > first) - sampleResourceId = thread->_voiceLUT->voices[first]; + if (thread->_voiceLUT->size() > uint16(first)) + sampleResourceId = (*thread->_voiceLUT)[uint16(first)]; #if 0 } #endif @@ -1067,12 +1048,11 @@ void Script::opJmpSeedRandom(SCRIPTOP_PARAMS) { warning("opJmpSeedRandom"); } -void Script::loadModule(int scriptModuleNumber) { - byte *resourcePointer; - size_t resourceLength; +void Script::loadModule(uint scriptModuleNumber) { + ByteArray resourceData; // Validate script number - if ((scriptModuleNumber < 0) || (scriptModuleNumber >= _modulesCount)) { + if (scriptModuleNumber >= _modules.size()) { error("Script::loadScript() Invalid script module number"); } @@ -1083,79 +1063,70 @@ void Script::loadModule(int scriptModuleNumber) { // Initialize script data structure debug(3, "Loading script module #%d", scriptModuleNumber); - _vm->_resource->loadResource(_scriptContext, _modules[scriptModuleNumber].scriptResourceId, resourcePointer, resourceLength); + _vm->_resource->loadResource(_scriptContext, _modules[scriptModuleNumber].scriptResourceId, resourceData); - loadModuleBase(_modules[scriptModuleNumber], resourcePointer, resourceLength); - free(resourcePointer); + loadModuleBase(_modules[scriptModuleNumber], resourceData); - _vm->_resource->loadResource(_scriptContext, _modules[scriptModuleNumber].stringsResourceId, resourcePointer, resourceLength); + _vm->_resource->loadResource(_scriptContext, _modules[scriptModuleNumber].stringsResourceId, resourceData); - _vm->loadStrings(_modules[scriptModuleNumber].strings, resourcePointer, resourceLength); - free(resourcePointer); + _vm->loadStrings(_modules[scriptModuleNumber].strings, resourceData); if (_modules[scriptModuleNumber].voicesResourceId > 0) { - _vm->_resource->loadResource(_scriptContext, _modules[scriptModuleNumber].voicesResourceId, resourcePointer, resourceLength); + _vm->_resource->loadResource(_scriptContext, _modules[scriptModuleNumber].voicesResourceId, resourceData); - loadVoiceLUT(_modules[scriptModuleNumber].voiceLUT, resourcePointer, resourceLength); - free(resourcePointer); + loadVoiceLUT(_modules[scriptModuleNumber].voiceLUT, resourceData); } _modules[scriptModuleNumber].staticOffset = _staticSize; _staticSize += _modules[scriptModuleNumber].staticSize; - if (_staticSize > _commonBufferSize) { - error("Script::loadModule() _staticSize > _commonBufferSize"); + if (_staticSize > _commonBuffer.size()) { + error("Script::loadModule() _staticSize > _commonBuffer.size()"); } _modules[scriptModuleNumber].loaded = true; } -void Script::freeModules() { - int i; - for (i = 0; i < _modulesCount; i++) { +void Script::clearModules() { + uint i; + for (i = 0; i < _modules.size(); i++) { if (_modules[i].loaded) { - _modules[i].freeMem(); - _modules[i].loaded = false; + _modules[i].clear(); } } _staticSize = 0; } -void Script::loadModuleBase(ModuleData &module, const byte *resourcePointer, size_t resourceLength) { - int i; +void Script::loadModuleBase(ModuleData &module, const ByteArray &resourceData) { + uint i; debug(3, "Loading module base..."); - module.moduleBase = (byte*)malloc(resourceLength); - module.moduleBaseSize = resourceLength; - - memcpy(module.moduleBase, resourcePointer, resourceLength); + module.moduleBase.assign(resourceData); - MemoryReadStreamEndian scriptS(module.moduleBase, module.moduleBaseSize, _scriptContext->isBigEndian()); + ByteArrayReadStreamEndian scriptS(module.moduleBase, _scriptContext->isBigEndian()); - module.entryPointsCount = scriptS.readUint16(); + uint entryPointsCount = scriptS.readUint16(); scriptS.readUint16(); //skip - module.entryPointsTableOffset = scriptS.readUint16(); + uint16 entryPointsTableOffset; // offset of entrypoint table in moduleBase + entryPointsTableOffset = scriptS.readUint16(); scriptS.readUint16(); //skip - if ((module.moduleBaseSize - module.entryPointsTableOffset) < (module.entryPointsCount * SCRIPT_TBLENTRY_LEN)) { + if ((module.moduleBase.size() - entryPointsTableOffset) < (entryPointsCount * SCRIPT_TBLENTRY_LEN)) { error("Script::loadModuleBase() Invalid table offset"); } - if (module.entryPointsCount > SCRIPT_MAX) { + if (entryPointsCount > SCRIPT_MAX) { error("Script::loadModuleBase()Script limit exceeded"); } - module.entryPoints = (EntryPoint *)malloc(module.entryPointsCount * sizeof(*module.entryPoints)); - if (module.entryPoints == NULL) { - memoryError("Script::loadModuleBase"); - } + module.entryPoints.resize(entryPointsCount); // Read in the entrypoint table module.staticSize = scriptS.readUint16(); - while (scriptS.pos() < module.entryPointsTableOffset) + while (scriptS.pos() < entryPointsTableOffset) scriptS.readByte(); - for (i = 0; i < module.entryPointsCount; i++) { + for (i = 0; i < module.entryPoints.size(); i++) { // First uint16 is the offset of the entrypoint name from the start // of the bytecode resource, second uint16 is the offset of the // bytecode itself for said entrypoint @@ -1163,26 +1134,21 @@ void Script::loadModuleBase(ModuleData &module, const byte *resourcePointer, siz module.entryPoints[i].offset = scriptS.readUint16(); // Perform a simple range check on offset values - if ((module.entryPoints[i].nameOffset >= module.moduleBaseSize) || (module.entryPoints[i].offset >= module.moduleBaseSize)) { + if ((module.entryPoints[i].nameOffset >= module.moduleBase.size()) || (module.entryPoints[i].offset >= module.moduleBase.size())) { error("Script::loadModuleBase() Invalid offset encountered in script entrypoint table"); } } } -void Script::loadVoiceLUT(VoiceLUT &voiceLUT, const byte *resourcePointer, size_t resourceLength) { +void Script::loadVoiceLUT(VoiceLUT &voiceLUT, const ByteArray &resourceData) { uint16 i; - voiceLUT.voicesCount = resourceLength / 2; - - voiceLUT.voices = (uint16 *)malloc(voiceLUT.voicesCount * sizeof(*voiceLUT.voices)); - if (voiceLUT.voices == NULL) { - error("Script::loadVoiceLUT() not enough memory"); - } + voiceLUT.resize(resourceData.size() / 2); - MemoryReadStreamEndian scriptS(resourcePointer, resourceLength, _scriptContext->isBigEndian()); + ByteArrayReadStreamEndian scriptS(resourceData, _scriptContext->isBigEndian()); - for (i = 0; i < voiceLUT.voicesCount; i++) { - voiceLUT.voices[i] = scriptS.readUint16(); + for (i = 0; i < voiceLUT.size(); i++) { + voiceLUT[i] = scriptS.readUint16(); } } @@ -1442,7 +1408,7 @@ void Script::doVerb() { event.param4 = _pendingObject[0]; // Object event.param5 = _pendingObject[1]; // With Object event.param6 = (objectType == kGameObjectActor) ? _pendingObject[0] : ID_PROTAG; // Actor - _vm->_events->queue(&event); + _vm->_events->queue(event); } else { // Show excuse text in ITE CD Versions diff --git a/engines/saga/script.h b/engines/saga/script.h index 21afeb5c44..e5054d5f4e 100644 --- a/engines/saga/script.h +++ b/engines/saga/script.h @@ -129,16 +129,7 @@ struct EntryPoint { uint16 offset; }; -struct VoiceLUT { - uint16 voicesCount; - uint16 *voices; - void freeMem() { - voicesCount = 0; - free(voices); - } - VoiceLUT() { - memset(this, 0, sizeof(*this)); - } +class VoiceLUT : public Common::Array<uint16> { }; struct ModuleData { @@ -147,28 +138,29 @@ struct ModuleData { int stringsResourceId; int voicesResourceId; - byte *moduleBase; // all base module - uint16 moduleBaseSize; // base module size + ByteArray moduleBase; // all base module uint16 staticSize; // size of static data uint staticOffset; // offset of static data begining in _commonBuffer - - uint16 entryPointsTableOffset; // offset of entrypoint table in moduleBase - uint16 entryPointsCount; - EntryPoint *entryPoints; + Common::Array<EntryPoint> entryPoints; StringsTable strings; VoiceLUT voiceLUT; - void freeMem() { - strings.freeMem(); - voiceLUT.freeMem(); - free(moduleBase); - free(entryPoints); + + void clear() { + loaded = false; + strings.clear(); + voiceLUT.clear(); + moduleBase.clear(); + entryPoints.clear(); + } + + ModuleData() : loaded(false), scriptResourceId(0), stringsResourceId(0), voicesResourceId(0), staticSize(0), staticOffset(0) { } }; class ScriptThread { public: - int16 *_stackBuf; + Common::Array<int16> _stackBuf; uint16 _stackTopIndex; uint16 _frameIndex; @@ -264,41 +256,15 @@ public: } ScriptThread() { - memset(this, 0xFE, sizeof(*this)); - _flags = kTFlagNone; - _stackBuf = 0; - } - - // copy constructor - ScriptThread(const ScriptThread& s) { - // Verify that s doesn't have a non-zero _stackBuf, for else - // we would have to clone that buffer, too, which we currently - // don't do. This case should never occur anyway, though (at - // least as long as the thread handling code does not change). - assert(!s._stackBuf); + memset(&_frameIndex, 0xFE, sizeof(_frameIndex)); + memset(_threadVars, 0xFE, sizeof(_threadVars)); + memset(&_waitType, 0xFE, sizeof(_waitType)); + memset(&_sleepTime, 0xFE, sizeof(_sleepTime)); + memset(&_threadObj, 0xFE, sizeof(_threadObj)); + memset(&_returnValue, 0xFE, sizeof(_threadObj)); + memset(&_frameWait, 0xFE, sizeof(_frameWait)); - memcpy(this, &s, sizeof(*this)); - } - - // assignment operator - ScriptThread& operator=(const ScriptThread &s) { - if (this == &s) - return *this; - - // Verify that s doesn't have a non-zero _stackBuf, for else - // we would have to clone that buffer, too, which we currently - // don't do. This case should never occur anyway, though (at - // least as long as the thread handling code does not change). - assert(!s._stackBuf); - - free(_stackBuf); - memcpy(this, &s, sizeof(*this)); - - return *this; - } - - ~ScriptThread() { - free(_stackBuf); + _flags = kTFlagNone; } }; @@ -315,8 +281,8 @@ public: Script(SagaEngine *vm); virtual ~Script(); - void loadModule(int scriptModuleNumber); - void freeModules(); + void loadModule(uint scriptModuleNumber); + void clearModules(); void doVerb(); void showVerb(int statusColor = -1); @@ -384,13 +350,11 @@ protected: ResourceContext *_dataContext; uint16 _modulesLUTEntryLen; - ModuleData *_modules; - int _modulesCount; + Common::Array<ModuleData> _modules; TextListEntry *_placardTextEntry; friend class SagaEngine; - byte *_commonBuffer; - uint _commonBufferSize; + ByteArray _commonBuffer; uint _staticSize; ScriptThreadList _threadList; @@ -428,10 +392,10 @@ public: void wakeUpThreads(int waitType); void wakeUpThreadsDelayed(int waitType, int sleepTime); - void loadVoiceLUT(VoiceLUT &voiceLUT, const byte *resourcePointer, size_t resourceLength); + void loadVoiceLUT(VoiceLUT &voiceLUT, const ByteArray &resourceData); protected: - void loadModuleBase(ModuleData &module, const byte *resourcePointer, size_t resourceLength); + void loadModuleBase(ModuleData &module, const ByteArray &resourceData); // runThread returns true if we should break running of other threads bool runThread(ScriptThread &thread); diff --git a/engines/saga/sfuncs.cpp b/engines/saga/sfuncs.cpp index 328d4040af..1e34362dc4 100644 --- a/engines/saga/sfuncs.cpp +++ b/engines/saga/sfuncs.cpp @@ -327,7 +327,7 @@ void Script::sfScriptDoAction(SCRIPTFUNC_PARAMS) { event.param4 = theObject; // Object event.param5 = withObject; // With Object event.param6 = objectId; - _vm->_events->queue(&event); + _vm->_events->queue(event); } // Script function #8 (0x08) nonblocking @@ -782,11 +782,11 @@ void Script::sfSimulSpeech(SCRIPTFUNC_PARAMS) { for (i = 0; i < actorsCount; i++) actorsIds[i] = thread->pop(); - if (thread->_voiceLUT->voices) { + if (!thread->_voiceLUT->empty()) { if (_vm->getGameId() == GID_IHNM && stringId >= 338) { sampleResourceId = -1; } else { - sampleResourceId = thread->_voiceLUT->voices[stringId]; + sampleResourceId = (*thread->_voiceLUT)[stringId]; if (sampleResourceId <= 0 || sampleResourceId > 4000) sampleResourceId = -1; } @@ -953,7 +953,7 @@ void Script::sfPlaceActor(SCRIPTFUNC_PARAMS) { int frameOffset = thread->pop(); ActorFrameRange *frameRange; - debug(1, "sfPlaceActor(id = 0x%x, x=%d, y=%d, dir=%d, frameType=%d, frameOffset=%d)", actorId, actor->_location.x, + debug(1, "sfPlaceActor(id = 0x%X, x=%d, y=%d, dir=%d, frameType=%d, frameOffset=%d)", actorId, actor->_location.x, actor->_location.y, actor->_facingDirection, frameType, frameOffset); if (frameType >= 0) { @@ -1042,8 +1042,8 @@ void Script::sfSimulSpeech2(SCRIPTFUNC_PARAMS) { for (i = 0; i < actorsCount; i++) actorsIds[i] = thread->pop(); - if (thread->_voiceLUT->voices) { - sampleResourceId = thread->_voiceLUT->voices[stringId]; + if (!thread->_voiceLUT->empty()) { + sampleResourceId = (*thread->_voiceLUT)[stringId]; if (sampleResourceId <= 0 || sampleResourceId > 4000) sampleResourceId = -1; } @@ -1060,7 +1060,7 @@ void Script::sfPlacard(SCRIPTFUNC_PARAMS) { static PalEntry cur_pal[PAL_ENTRIES]; PalEntry *pal; Event event; - Event *q_event; + EventColumns *eventColumns; thread->wait(kWaitTypePlacard); @@ -1070,7 +1070,7 @@ void Script::sfPlacard(SCRIPTFUNC_PARAMS) { event.type = kEvTOneshot; event.code = kCursorEvent; event.op = kEventHide; - q_event = _vm->_events->queue(&event); + eventColumns = _vm->_events->queue(event); _vm->_interface->setFadeMode(kFadeOut); @@ -1082,7 +1082,7 @@ void Script::sfPlacard(SCRIPTFUNC_PARAMS) { event.time = 0; event.duration = kNormalFadeDuration; event.data = cur_pal; - q_event = _vm->_events->chain(q_event, &event); + _vm->_events->chain(eventColumns, event); // set fade mode event.type = kEvTImmediate; @@ -1091,12 +1091,12 @@ void Script::sfPlacard(SCRIPTFUNC_PARAMS) { event.param = kNoFade; event.time = 0; event.duration = 0; - q_event = _vm->_events->chain(q_event, &event); + _vm->_events->chain(eventColumns, event); event.type = kEvTOneshot; event.code = kInterfaceEvent; event.op = kEventClearStatus; - q_event = _vm->_events->chain(q_event, &event); + _vm->_events->chain(eventColumns, event); event.type = kEvTOneshot; event.code = kGraphicsEvent; @@ -1106,7 +1106,7 @@ void Script::sfPlacard(SCRIPTFUNC_PARAMS) { event.param3 = _vm->_scene->getHeight(); event.param4 = 0; event.param5 = _vm->getDisplayInfo().width; - q_event = _vm->_events->chain(q_event, &event); + _vm->_events->chain(eventColumns, event); // Put the text in the center of the viewport, assuming it will fit on // one line. If we cannot make that assumption we'll need to extend @@ -1130,7 +1130,7 @@ void Script::sfPlacard(SCRIPTFUNC_PARAMS) { event.code = kTextEvent; event.op = kEventDisplay; event.data = _placardTextEntry; - q_event = _vm->_events->chain(q_event, &event); + _vm->_events->chain(eventColumns, event); _vm->_scene->getBGPal(pal); event.type = kEvTImmediate; @@ -1139,13 +1139,13 @@ void Script::sfPlacard(SCRIPTFUNC_PARAMS) { event.time = 0; event.duration = kNormalFadeDuration; event.data = pal; - q_event = _vm->_events->chain(q_event, &event); + _vm->_events->chain(eventColumns, event); event.type = kEvTOneshot; event.code = kScriptEvent; event.op = kEventThreadWake; event.param = kWaitTypePlacard; - q_event = _vm->_events->chain(q_event, &event); + _vm->_events->chain(eventColumns, event); } @@ -1349,8 +1349,8 @@ void Script::sfPlayMusic(SCRIPTFUNC_PARAMS) { return; } - if (param1 >= _vm->_music->_songTableLen) { - warning("sfPlayMusic: Wrong song number (%d > %d)", param1, _vm->_music->_songTableLen - 1); + if (uint(param1) >= _vm->_music->_songTable.size()) { + warning("sfPlayMusic: Wrong song number (%d > %d)", param1, _vm->_music->_songTable.size() - 1); } else { _vm->_music->setVolume(_vm->_musicVolume, 1); _vm->_music->play(_vm->_music->_songTable[param1], param2 ? MUSIC_LOOP : MUSIC_NORMAL); @@ -1440,7 +1440,7 @@ void Script::sfPlaySound(SCRIPTFUNC_PARAMS) { int16 param = thread->pop(); int res; - if (param >= 0 && param < _vm->_sndRes->_fxTableLen) { + if (uint(param) < _vm->_sndRes->_fxTable.size()) { res = _vm->_sndRes->_fxTable[param].res; if (_vm->getGameId() == GID_ITE && !(_vm->getFeatures() & GF_ITE_FLOPPY)) res -= 14; @@ -1455,7 +1455,7 @@ void Script::sfPlayLoopedSound(SCRIPTFUNC_PARAMS) { int16 param = thread->pop(); int res; - if (param >= 0 && param < _vm->_sndRes->_fxTableLen) { + if (uint(param) < _vm->_sndRes->_fxTable.size()) { res = _vm->_sndRes->_fxTable[param].res; if (_vm->getGameId() == GID_ITE && !(_vm->getFeatures() & GF_ITE_FLOPPY)) res -= 14; @@ -1527,7 +1527,7 @@ void Script::finishDialog(int strID, int replyID, int flags, int bitOffset) { const char *str = _conversingThread->_strings->getString(strID); if (*str != '[') { int sampleResourceId = -1; - sampleResourceId = _conversingThread->_voiceLUT->voices[strID]; + sampleResourceId = (*_conversingThread->_voiceLUT)[strID]; if (sampleResourceId < 0 || sampleResourceId > 4000) sampleResourceId = -1; diff --git a/engines/saga/sfuncs_ihnm.cpp b/engines/saga/sfuncs_ihnm.cpp index b98c1cb852..dd6bbbe6f8 100644 --- a/engines/saga/sfuncs_ihnm.cpp +++ b/engines/saga/sfuncs_ihnm.cpp @@ -247,7 +247,7 @@ void Script::sfScriptFade(SCRIPTFUNC_PARAMS) { event.param2 = endingBrightness; event.param3 = firstPalEntry; event.param4 = lastPalEntry - firstPalEntry + 1; - _vm->_events->queue(&event); + _vm->_events->queue(event); } void Script::sfScriptStartVideo(SCRIPTFUNC_PARAMS) { @@ -294,7 +294,7 @@ void Script::sfAddIHNMDemoHelpTextLine(SCRIPTFUNC_PARAMS) { event.code = kTextEvent; event.op = kEventDisplay; event.data = _psychicProfileTextEntry; - _vm->_events->queue(&event); + _vm->_events->queue(event); _ihnmDemoCurrentY += _vm->_font->getHeight(kKnownFontVerb, thread->_strings->getString(stringId), 226, kFontCentered); } @@ -413,8 +413,8 @@ void Script::sfQueueMusic(SCRIPTFUNC_PARAMS) { return; } - if (param1 >= _vm->_music->_songTableLen) { - warning("sfQueueMusic: Wrong song number (%d > %d)", param1, _vm->_music->_songTableLen - 1); + if (uint(param1) >= _vm->_music->_songTable.size()) { + warning("sfQueueMusic: Wrong song number (%d > %d)", param1, _vm->_music->_songTable.size() - 1); } else { _vm->_music->setVolume(_vm->_musicVolume, 1); event.type = kEvTOneshot; @@ -424,7 +424,7 @@ void Script::sfQueueMusic(SCRIPTFUNC_PARAMS) { event.op = kEventPlay; event.time = _vm->ticksToMSec(1000); - _vm->_events->queue(&event); + _vm->_events->queue(event); if (!_vm->_scene->haveChapterPointsChanged()) { _vm->_scene->setCurrentMusicTrack(param1); diff --git a/engines/saga/shorten.cpp b/engines/saga/shorten.cpp index 2137423a5a..592c2d0618 100644 --- a/engines/saga/shorten.cpp +++ b/engines/saga/shorten.cpp @@ -239,7 +239,7 @@ byte *loadShortenFromStream(Common::ReadStream &stream, int &size, int &rate, by return NULL; } - // Get block size + // Get block size if (version > 0) { blockSize = gReader->getUint32((int) (log((double) DEFAULT_BLOCK_SIZE) / M_LN2)); maxLPC = gReader->getUint32(2); @@ -366,7 +366,12 @@ byte *loadShortenFromStream(Common::ReadStream &stream, int &size, int &rate, by if (maxLPC < lpcNum) { warning("Safeguard: maxLPC < lpcNum (should never happen)"); maxLPC = lpcNum; - lpc = (int32 *) realloc(lpc, maxLPC * 4); + int32 *tmp = (int32 *) realloc(lpc, maxLPC * 4); + if ((tmp != NULL) || (maxLPC == 0)) { + lpc = tmp; + } else { + error("loadShortenFromStream(): Error while reallocating memory"); + } } for (i = 0; i < lpcNum; i++) @@ -430,7 +435,12 @@ byte *loadShortenFromStream(Common::ReadStream &stream, int &size, int &rate, by prevSize = size; size += (blockSize * dataSize); - unpackedBuffer = (byte *) realloc(unpackedBuffer, size); + byte *tmp = (byte *) realloc(unpackedBuffer, size); + if ((tmp != NULL) || (size == 0)) { + unpackedBuffer = tmp; + } else { + error("loadShortenFromStream(): Error while reallocating memory"); + } pBuf = unpackedBuffer + prevSize; if (flags & Audio::FLAG_16BITS) { @@ -464,7 +474,12 @@ byte *loadShortenFromStream(Common::ReadStream &stream, int &size, int &rate, by uint32 vLen = (uint32)gReader->getURice(5); prevSize = size; size += vLen; - unpackedBuffer = (byte *) realloc(unpackedBuffer, size); + byte *tmp = (byte *) realloc(unpackedBuffer, size); + if ((tmp != NULL) || (size == 0)) { + unpackedBuffer = tmp; + } else { + error("loadShortenFromStream(): Error while reallocating memory"); + } pBuf = unpackedBuffer + prevSize; while (vLen--) { diff --git a/engines/saga/sndres.cpp b/engines/saga/sndres.cpp index 9322918db5..74fde3e497 100644 --- a/engines/saga/sndres.cpp +++ b/engines/saga/sndres.cpp @@ -60,8 +60,11 @@ SndRes::SndRes(SagaEngine *vm) : _vm(vm), _sfxContext(NULL), _voiceContext(NULL) setVoiceBank(0); if (_vm->getGameId() == GID_ITE) { - _fxTable = ITE_SfxTable; - _fxTableLen = ITE_SFXCOUNT; + _fxTable.resize(ITE_SFXCOUNT); + for (uint i = 0; i < _fxTable.size(); i++) { + _fxTable[i].res = ITE_SfxTable[i].res; + _fxTable[i].vol = ITE_SfxTable[i].vol; + } #ifdef ENABLE_IHNM } else if (_vm->getGameId() == GID_IHNM) { ResourceContext *resourceContext; @@ -71,32 +74,24 @@ SndRes::SndRes(SagaEngine *vm) : _vm(vm), _sfxContext(NULL), _voiceContext(NULL) error("Resource::loadGlobalResources() resource context not found"); } - byte *resourcePointer; - size_t resourceLength; + ByteArray resourceData; if (_vm->isIHNMDemo()) { - _vm->_resource->loadResource(resourceContext, RID_IHNMDEMO_SFX_LUT, - resourcePointer, resourceLength); + _vm->_resource->loadResource(resourceContext, RID_IHNMDEMO_SFX_LUT, resourceData); } else { - _vm->_resource->loadResource(resourceContext, RID_IHNM_SFX_LUT, - resourcePointer, resourceLength); + _vm->_resource->loadResource(resourceContext, RID_IHNM_SFX_LUT, resourceData); } - if (resourceLength == 0) { + if (resourceData.empty()) { error("Sndres::SndRes can't read SfxIDs table"); } - _fxTableIDsLen = resourceLength / 2; - _fxTableIDs = (int16 *)malloc(_fxTableIDsLen * sizeof(int16)); + _fxTableIDs.resize(resourceData.size() / 2); - MemoryReadStream metaS(resourcePointer, resourceLength); - for (int i = 0; i < _fxTableIDsLen; i++) + ByteArrayReadStreamEndian metaS(resourceData); + for (uint i = 0; i < _fxTableIDs.size(); i++) { _fxTableIDs[i] = metaS.readSint16LE(); - - free(resourcePointer); - - _fxTable = 0; - _fxTableLen = 0; + } #endif #ifdef ENABLE_SAGA2 } else if (_vm->getGameId() == GID_DINO) { @@ -108,12 +103,6 @@ SndRes::SndRes(SagaEngine *vm) : _vm(vm), _sfxContext(NULL), _voiceContext(NULL) } SndRes::~SndRes() { -#ifdef ENABLE_IHNM - if (_vm->getGameId() == GID_IHNM) { - free(_fxTable); - free(_fxTableIDs); - } -#endif } void SndRes::setVoiceBank(int serial) { @@ -327,7 +316,7 @@ bool SndRes::load(ResourceContext *context, uint32 resourceId, SoundBuffer &buff #endif } else if (resourceType == kSoundVOC) { data = Audio::loadVOCFromStream(readS, size, rate); - result = (data != 0); + result = (data != NULL); if (onlyHeader) free(data); buffer.flags |= Audio::FLAG_UNSIGNED; @@ -339,11 +328,13 @@ bool SndRes::load(ResourceContext *context, uint32 resourceId, SoundBuffer &buff buffer.frequency = rate; buffer.size = size; - if (!onlyHeader && resourceType != kSoundVOC) { - buffer.buffer = (byte *)malloc(size); - readS.read(buffer.buffer, size); - } else if (!onlyHeader && resourceType == kSoundVOC) { - buffer.buffer = data; + if (!onlyHeader) { + if (resourceType == kSoundVOC) { + buffer.buffer = data; + } else { + buffer.buffer = (byte *)malloc(size); + readS.read(buffer.buffer, size); + } } } break; diff --git a/engines/saga/sndres.h b/engines/saga/sndres.h index d5507ebc55..e4bae1b143 100644 --- a/engines/saga/sndres.h +++ b/engines/saga/sndres.h @@ -33,6 +33,11 @@ namespace Saga { +struct FxTable { + int16 res; + int16 vol; +}; + class SndRes { public: @@ -44,11 +49,9 @@ public: int getVoiceLength(uint32 resourceId); void setVoiceBank(int serial); - FxTable *_fxTable; - int _fxTableLen; + Common::Array<FxTable> _fxTable; - int16 *_fxTableIDs; - int _fxTableIDsLen; + Common::Array<int16> _fxTableIDs; private: bool load(ResourceContext *context, uint32 resourceId, SoundBuffer &buffer, bool onlyHeader); diff --git a/engines/saga/sound.cpp b/engines/saga/sound.cpp index db979e8104..b3fcf4def3 100644 --- a/engines/saga/sound.cpp +++ b/engines/saga/sound.cpp @@ -36,7 +36,7 @@ namespace Saga { Sound::Sound(SagaEngine *vm, Audio::Mixer *mixer) : - _vm(vm), _mixer(mixer), _voxStream(0) { + _vm(vm), _mixer(mixer) { for (int i = 0; i < SOUND_HANDLES; i++) _handles[i].type = kFreeHandle; @@ -45,7 +45,6 @@ Sound::Sound(SagaEngine *vm, Audio::Mixer *mixer) : } Sound::~Sound() { - delete _voxStream; } SndHandle *Sound::getHandle() { diff --git a/engines/saga/sound.h b/engines/saga/sound.h index 7ee2765a0f..b5f82369f4 100644 --- a/engines/saga/sound.h +++ b/engines/saga/sound.h @@ -95,7 +95,6 @@ public: SagaEngine *_vm; Audio::Mixer *_mixer; - MemoryReadStream *_voxStream; SndHandle _handles[SOUND_HANDLES]; }; diff --git a/engines/saga/sprite.cpp b/engines/saga/sprite.cpp index c1a9846b47..eb62fb20ff 100644 --- a/engines/saga/sprite.cpp +++ b/engines/saga/sprite.cpp @@ -51,13 +51,6 @@ Sprite::Sprite(SagaEngine *vm) : _vm(vm) { error("Sprite::Sprite resource context not found"); } - _decodeBufLen = DECODE_BUF_LEN; - - _decodeBuf = (byte *)malloc(_decodeBufLen); - if (_decodeBuf == NULL) { - memoryError("Sprite::Sprite"); - } - if (_vm->getGameId() == GID_ITE) { loadList(_vm->getResourceDescription()->mainSpritesResourceId, _mainSprites); _arrowSprites = _saveReminderSprites = _inventorySprites = _mainSprites; @@ -78,67 +71,54 @@ Sprite::Sprite(SagaEngine *vm) : _vm(vm) { Sprite::~Sprite() { debug(8, "Shutting down sprite subsystem..."); - _mainSprites.freeMem(); - if (_vm->getGameId() == GID_IHNM) { - _inventorySprites.freeMem(); - _arrowSprites.freeMem(); - _saveReminderSprites.freeMem(); - } - free(_decodeBuf); } void Sprite::loadList(int resourceId, SpriteList &spriteList) { SpriteInfo *spriteInfo; - byte *spriteListData = 0; - size_t spriteListLength = 0; + ByteArray spriteListData; uint16 oldSpriteCount; uint16 newSpriteCount; uint16 spriteCount; - int i; + uint i; int outputLength, inputLength; uint32 offset; const byte *spritePointer; const byte *spriteDataPointer; - _vm->_resource->loadResource(_spriteContext, resourceId, spriteListData, spriteListLength); + _vm->_resource->loadResource(_spriteContext, resourceId, spriteListData); - if (spriteListLength == 0) { + if (spriteListData.empty()) { return; } - MemoryReadStreamEndian readS(spriteListData, spriteListLength, _spriteContext->isBigEndian()); + ByteArrayReadStreamEndian readS(spriteListData, _spriteContext->isBigEndian()); spriteCount = readS.readUint16(); debug(9, "Sprites: %d", spriteCount); - oldSpriteCount = spriteList.spriteCount; - newSpriteCount = spriteList.spriteCount + spriteCount; + oldSpriteCount = spriteList.size(); + newSpriteCount = oldSpriteCount + spriteCount; - spriteList.infoList = (SpriteInfo *)realloc(spriteList.infoList, newSpriteCount * sizeof(*spriteList.infoList)); - if (spriteList.infoList == NULL) { - memoryError("Sprite::loadList"); - } - - spriteList.spriteCount = newSpriteCount; + spriteList.resize(newSpriteCount); bool bigHeader = _vm->getGameId() == GID_IHNM || _vm->isMacResources(); - for (i = oldSpriteCount; i < spriteList.spriteCount; i++) { - spriteInfo = &spriteList.infoList[i]; + for (i = oldSpriteCount; i < spriteList.size(); i++) { + spriteInfo = &spriteList[i]; if (bigHeader) offset = readS.readUint32(); else offset = readS.readUint16(); - if (offset >= spriteListLength) { + if (offset >= spriteListData.size()) { // ITE Mac demos throw this warning warning("Sprite::loadList offset exceeded"); - spriteList.spriteCount = i; + spriteList.resize(i); return; } - spritePointer = spriteListData; + spritePointer = spriteListData.getBuffer(); spritePointer += offset; if (bigHeader) { @@ -163,114 +143,147 @@ void Sprite::loadList(int resourceId, SpriteList &spriteList) { } outputLength = spriteInfo->width * spriteInfo->height; - inputLength = spriteListLength - (spriteDataPointer - spriteListData); - decodeRLEBuffer(spriteDataPointer, inputLength, outputLength); - spriteInfo->decodedBuffer = (byte *) malloc(outputLength); - if (spriteInfo->decodedBuffer == NULL) { - memoryError("Sprite::loadList"); - } - + inputLength = spriteListData.size() - (spriteDataPointer - spriteListData.getBuffer()); + spriteInfo->decodedBuffer.resize(outputLength); + if (outputLength > 0) { + decodeRLEBuffer(spriteDataPointer, inputLength, outputLength); + byte *dst = &spriteInfo->decodedBuffer.front(); #ifdef ENABLE_IHNM - // IHNM sprites are upside-down, for reasons which i can only - // assume are perverse. To simplify things, flip them now. Not - // at drawing time. - - if (_vm->getGameId() == GID_IHNM) { - byte *src = _decodeBuf + spriteInfo->width * (spriteInfo->height - 1); - byte *dst = spriteInfo->decodedBuffer; - - for (int j = 0; j < spriteInfo->height; j++) { - memcpy(dst, src, spriteInfo->width); - src -= spriteInfo->width; - dst += spriteInfo->width; - } - } else + // IHNM sprites are upside-down, for reasons which i can only + // assume are perverse. To simplify things, flip them now. Not + // at drawing time. + + if (_vm->getGameId() == GID_IHNM) { + byte *src = &_decodeBuf[spriteInfo->width * (spriteInfo->height - 1)]; + + for (int j = 0; j < spriteInfo->height; j++) { + memcpy(dst, src, spriteInfo->width); + src -= spriteInfo->width; + dst += spriteInfo->width; + } + } else #endif - memcpy(spriteInfo->decodedBuffer, _decodeBuf, outputLength); + memcpy(dst, &_decodeBuf.front(), outputLength); + } } - - free(spriteListData); } -void Sprite::getScaledSpriteBuffer(SpriteList &spriteList, int spriteNumber, int scale, int &width, int &height, int &xAlign, int &yAlign, const byte *&buffer) { +void Sprite::getScaledSpriteBuffer(SpriteList &spriteList, uint spriteNumber, int scale, int &width, int &height, int &xAlign, int &yAlign, const byte *&buffer) { SpriteInfo *spriteInfo; - if (spriteList.spriteCount <= spriteNumber) { + if (spriteList.size() <= spriteNumber) { // this can occur in IHNM while loading a saved game from chapter 1-5 when being in the end chapter - warning("spriteList.spriteCount <= spriteNumber"); + warning("spriteList.size() <= spriteNumber"); return; } - spriteInfo = &spriteList.infoList[spriteNumber]; + spriteInfo = &spriteList[spriteNumber]; if (scale < 256) { - xAlign = (spriteInfo->xAlign * scale) >> 8; - yAlign = (spriteInfo->yAlign * scale) >> 8; + xAlign = (spriteInfo->xAlign * scale) >> 8; //TODO: do we need to take in account sprite x&y aligns ? + yAlign = (spriteInfo->yAlign * scale) >> 8; // ???? height = (spriteInfo->height * scale + 0x7f) >> 8; width = (spriteInfo->width * scale + 0x7f) >> 8; - scaleBuffer(spriteInfo->decodedBuffer, spriteInfo->width, spriteInfo->height, scale); - buffer = _decodeBuf; + size_t outLength = width * height; + if (outLength > 0) { + scaleBuffer(&spriteInfo->decodedBuffer.front(), spriteInfo->width, spriteInfo->height, scale, outLength); + buffer = &_decodeBuf.front(); + } else { + buffer = NULL; + } } else { xAlign = spriteInfo->xAlign; yAlign = spriteInfo->yAlign; height = spriteInfo->height; width = spriteInfo->width; - buffer = spriteInfo->decodedBuffer; + buffer = spriteInfo->decodedBuffer.getBuffer(); } } void Sprite::drawClip(const Point &spritePointer, int width, int height, const byte *spriteBuffer, bool clipToScene) { - int clipWidth; - int clipHeight; Common::Rect clipRect = clipToScene ? _vm->_scene->getSceneClip() : _vm->getDisplayClip(); - int i, j, jo, io; + int xDstOffset, yDstOffset, xSrcOffset, ySrcOffset, xDiff, yDiff, cWidth, cHeight; byte *bufRowPointer; + byte *bufPointer; const byte *srcRowPointer; + const byte *srcPointer; + + int backBufferPitch = _vm->_gfx->getBackBufferPitch(); + + //find Rects intersection + yDiff = clipRect.top - spritePointer.y; + if (yDiff > 0) { + ySrcOffset = yDiff; + yDstOffset = clipRect.top; + cHeight = height - yDiff; + } else { + ySrcOffset = 0; + yDstOffset = spritePointer.y; + cHeight = height; + } - bufRowPointer = _vm->_gfx->getBackBufferPixels() + _vm->_gfx->getBackBufferPitch() * spritePointer.y; - srcRowPointer = spriteBuffer; - - clipWidth = CLIP(width, 0, clipRect.right - spritePointer.x); - clipHeight = CLIP(height, 0, clipRect.bottom - spritePointer.y); - - jo = 0; - io = 0; - if (spritePointer.x < clipRect.left) { - jo = clipRect.left - spritePointer.x; + xDiff = clipRect.left - spritePointer.x; + if (xDiff > 0) { + xSrcOffset = xDiff; + xDstOffset = clipRect.left; + cWidth = width - xDiff; + } else { + xSrcOffset = 0; + xDstOffset = spritePointer.x; + cWidth = width; } - if (spritePointer.y < clipRect.top) { - io = clipRect.top - spritePointer.y; - bufRowPointer += _vm->_gfx->getBackBufferPitch() * io; - srcRowPointer += width * io; + + yDiff = yDstOffset + cHeight - clipRect.bottom; + if (yDiff > 0) { + cHeight -= yDiff; } - for (i = io; i < clipHeight; i++) { - for (j = jo; j < clipWidth; j++) { - assert(_vm->_gfx->getBackBufferPixels() <= (byte *)(bufRowPointer + j + spritePointer.x)); - assert((_vm->_gfx->getBackBufferPixels() + (_vm->getDisplayInfo().width * - _vm->getDisplayInfo().height)) > (byte *)(bufRowPointer + j + spritePointer.x)); - assert((const byte *)spriteBuffer <= (const byte *)(srcRowPointer + j)); - assert(((const byte *)spriteBuffer + (width * height)) > (const byte *)(srcRowPointer + j)); + xDiff = xDstOffset + cWidth - clipRect.right; + if (xDiff > 0) { + cWidth -= xDiff; + } - if (*(srcRowPointer + j) != 0) { - *(bufRowPointer + j + spritePointer.x) = *(srcRowPointer + j); + if ((cHeight <= 0) || (cWidth <= 0)) { + //no intersection + return; + } + bufRowPointer = _vm->_gfx->getBackBufferPixels() + backBufferPitch * yDstOffset + xDstOffset; + srcRowPointer = spriteBuffer + width * ySrcOffset + xSrcOffset; + + // validate src, dst buffers + assert(_vm->_gfx->getBackBufferPixels() <= bufRowPointer); + assert((_vm->_gfx->getBackBufferPixels() + (_vm->getDisplayInfo().width * _vm->getDisplayInfo().height)) >= + (byte *)(bufRowPointer + backBufferPitch * (cHeight - 1) + cWidth)); + assert((const byte *)spriteBuffer <= srcRowPointer); + assert(((const byte *)spriteBuffer + (width * height)) >= (const byte *)(srcRowPointer + width * (cHeight - 1) + cWidth)); + + const byte *srcPointerFinish2 = srcRowPointer + width * cHeight; + for (;;) { + srcPointer = srcRowPointer; + bufPointer = bufRowPointer; + const byte *srcPointerFinish = srcRowPointer + cWidth; + for (;;) { + if (*srcPointer != 0) { + *bufPointer = *srcPointer; + } + srcPointer++; + bufPointer++; + if (srcPointer == srcPointerFinish) { + break; } } - bufRowPointer += _vm->_gfx->getBackBufferPitch(); srcRowPointer += width; + if (srcRowPointer == srcPointerFinish2) { + break; + } + bufRowPointer += backBufferPitch; } - int x1 = MAX<int>(spritePointer.x, 0); - int y1 = MAX<int>(spritePointer.y, 0); - int x2 = MIN<int>(MAX<int>(spritePointer.x + clipWidth, 0), clipRect.right); - int y2 = MIN<int>(MAX<int>(spritePointer.y + clipHeight, 0), clipRect.bottom); - - if (x2 > x1 && y2 > y1) - _vm->_render->addDirtyRect(Common::Rect(x1, y1, x2, y2)); + _vm->_render->addDirtyRect(Common::Rect(xDstOffset, yDstOffset, xDstOffset + cWidth, yDstOffset + cHeight)); } -void Sprite::draw(SpriteList &spriteList, int32 spriteNumber, const Point &screenCoord, int scale, bool clipToScene) { +void Sprite::draw(SpriteList &spriteList, uint spriteNumber, const Point &screenCoord, int scale, bool clipToScene) { const byte *spriteBuffer = NULL; int width = 0; int height = 0; @@ -286,7 +299,7 @@ void Sprite::draw(SpriteList &spriteList, int32 spriteNumber, const Point &scree drawClip(spritePointer, width, height, spriteBuffer, clipToScene); } -void Sprite::draw(SpriteList &spriteList, int32 spriteNumber, const Rect &screenRect, int scale, bool clipToScene) { +void Sprite::draw(SpriteList &spriteList, uint spriteNumber, const Rect &screenRect, int scale, bool clipToScene) { const byte *spriteBuffer = NULL; int width = 0; int height = 0; @@ -310,7 +323,7 @@ void Sprite::draw(SpriteList &spriteList, int32 spriteNumber, const Rect &screen drawClip(spritePointer, width, height, spriteBuffer, clipToScene); } -bool Sprite::hitTest(SpriteList &spriteList, int spriteNumber, const Point &screenCoord, int scale, const Point &testPoint) { +bool Sprite::hitTest(SpriteList &spriteList, uint spriteNumber, const Point &screenCoord, int scale, const Point &testPoint) { const byte *spriteBuffer = NULL; int i, j; const byte *srcRowPointer; @@ -337,7 +350,7 @@ bool Sprite::hitTest(SpriteList &spriteList, int spriteNumber, const Point &scre return *srcRowPointer != 0; } -void Sprite::drawOccluded(SpriteList &spriteList, int spriteNumber, const Point &screenCoord, int scale, int depth) { +void Sprite::drawOccluded(SpriteList &spriteList, uint spriteNumber, const Point &screenCoord, int scale, int depth) { const byte *spriteBuffer = NULL; int x, y; byte *destRowPointer; @@ -356,7 +369,6 @@ void Sprite::drawOccluded(SpriteList &spriteList, int spriteNumber, const Point int maskWidth; int maskHeight; byte *maskBuffer; - size_t maskBufferLength; byte *maskRowPointer; int maskZ; @@ -365,7 +377,7 @@ void Sprite::drawOccluded(SpriteList &spriteList, int spriteNumber, const Point return; } - _vm->_scene->getBGMaskInfo(maskWidth, maskHeight, maskBuffer, maskBufferLength); + _vm->_scene->getBGMaskInfo(maskWidth, maskHeight, maskBuffer); getScaledSpriteBuffer(spriteList, spriteNumber, scale, width, height, xAlign, yAlign, spriteBuffer); @@ -420,15 +432,11 @@ void Sprite::decodeRLEBuffer(const byte *inputBuffer, size_t inLength, size_t ou byte *outPointerEnd; int c; - if (outLength > _decodeBufLen) { // TODO: may we should make dynamic growing? - error("Sprite::decodeRLEBuffer outLength > _decodeBufLen"); - } - - outPointer = _decodeBuf; - outPointerEnd = _decodeBuf + outLength; - outPointerEnd--; + _decodeBuf.resize(outLength); + outPointer = &_decodeBuf.front(); + outPointerEnd = &_decodeBuf.back(); - memset(outPointer, 0, outLength); + memset(outPointer, 0, _decodeBuf.size()); MemoryReadStream readS(inputBuffer, inLength); @@ -458,10 +466,14 @@ void Sprite::decodeRLEBuffer(const byte *inputBuffer, size_t inLength, size_t ou } } -void Sprite::scaleBuffer(const byte *src, int width, int height, int scale) { +void Sprite::scaleBuffer(const byte *src, int width, int height, int scale, size_t outLength) { byte skip = 256 - scale; // skip factor byte vskip = 0x80, hskip; - byte *dst = _decodeBuf; + + _decodeBuf.resize(outLength); + byte *dst = &_decodeBuf.front(); + + memset(dst, 0, _decodeBuf.size()); for (int i = 0; i < height; i++) { vskip += skip; diff --git a/engines/saga/sprite.h b/engines/saga/sprite.h index b7365fd28f..4e463cdd88 100644 --- a/engines/saga/sprite.h +++ b/engines/saga/sprite.h @@ -33,32 +33,19 @@ namespace Saga { #define SPRITE_ZMAX 16 #define SPRITE_ZMASK 0x0F -#define DECODE_BUF_LEN 64000 - struct SpriteInfo { - byte *decodedBuffer; + ByteArray decodedBuffer; int width; int height; int xAlign; int yAlign; -}; -struct SpriteList { - int spriteListResourceId; - int spriteCount; - SpriteInfo *infoList; - - void freeMem() { - for (int i = 0; i < spriteCount; i++) { - free(infoList[i].decodedBuffer); - } - free(infoList); - memset(this, 0, sizeof(*this)); + SpriteInfo() : width(0), height(0), xAlign(0), yAlign(0) { } +}; - SpriteList() { - memset(this, 0, sizeof(*this)); - } +class SpriteList : public Common::Array<SpriteInfo> { +// int spriteListResourceId; }; @@ -73,28 +60,27 @@ public: ~Sprite(); // draw scaled sprite using background scene mask - void drawOccluded(SpriteList &spriteList, int spriteNumber, const Point &screenCoord, int scale, int depth); + void drawOccluded(SpriteList &spriteList, uint spriteNumber, const Point &screenCoord, int scale, int depth); // draw scaled sprite using background scene mask - void draw(SpriteList &spriteList, int32 spriteNumber, const Point &screenCoord, int scale, bool clipToScene = false); + void draw(SpriteList &spriteList, uint spriteNumber, const Point &screenCoord, int scale, bool clipToScene = false); // main function void drawClip(const Point &spritePointer, int width, int height, const byte *spriteBuffer, bool clipToScene = false); - void draw(SpriteList &spriteList, int32 spriteNumber, const Rect &screenRect, int scale, bool clipToScene = false); + void draw(SpriteList &spriteList, uint spriteNumber, const Rect &screenRect, int scale, bool clipToScene = false); void loadList(int resourceId, SpriteList &spriteList); // load or append spriteList - bool hitTest(SpriteList &spriteList, int spriteNumber, const Point &screenCoord, int scale, const Point &testPoint); - void getScaledSpriteBuffer(SpriteList &spriteList, int spriteNumber, int scale, int &width, int &height, int &xAlign, int &yAlign, const byte *&buffer); + bool hitTest(SpriteList &spriteList, uint spriteNumber, const Point &screenCoord, int scale, const Point &testPoint); + void getScaledSpriteBuffer(SpriteList &spriteList, uint spriteNumber, int scale, int &width, int &height, int &xAlign, int &yAlign, const byte *&buffer); private: void decodeRLEBuffer(const byte *inputBuffer, size_t inLength, size_t outLength); - void scaleBuffer(const byte *src, int width, int height, int scale); + void scaleBuffer(const byte *src, int width, int height, int scale, size_t outLength); SagaEngine *_vm; ResourceContext *_spriteContext; - byte *_decodeBuf; - size_t _decodeBufLen; + ByteArray _decodeBuf; }; } // End of namespace Saga diff --git a/engines/saga/sthread.cpp b/engines/saga/sthread.cpp index be674e5acd..098970f4e8 100644 --- a/engines/saga/sthread.cpp +++ b/engines/saga/sthread.cpp @@ -39,16 +39,18 @@ namespace Saga { ScriptThread &Script::createThread(uint16 scriptModuleNumber, uint16 scriptEntryPointNumber) { loadModule(scriptModuleNumber); - if (_modules[scriptModuleNumber].entryPointsCount <= scriptEntryPointNumber) { + if (_modules[scriptModuleNumber].entryPoints.size() <= scriptEntryPointNumber) { error("Script::createThread wrong scriptEntryPointNumber"); } - ScriptThread newThread; + ScriptThread tmp; + _threadList.push_front(tmp); + ScriptThread &newThread = _threadList.front(); newThread._instructionOffset = _modules[scriptModuleNumber].entryPoints[scriptEntryPointNumber].offset; - newThread._commonBase = _commonBuffer; - newThread._staticBase = _commonBuffer + _modules[scriptModuleNumber].staticOffset; - newThread._moduleBase = _modules[scriptModuleNumber].moduleBase; - newThread._moduleBaseSize = _modules[scriptModuleNumber].moduleBaseSize; + newThread._commonBase = _commonBuffer.getBuffer(); + newThread._staticBase = _commonBuffer.getBuffer() + _modules[scriptModuleNumber].staticOffset; + newThread._moduleBase = _modules[scriptModuleNumber].moduleBase.getBuffer(); + newThread._moduleBaseSize = _modules[scriptModuleNumber].moduleBase.size(); newThread._strings = &_modules[scriptModuleNumber].strings; if (_vm->getGameId() == GID_IHNM) @@ -56,14 +58,10 @@ ScriptThread &Script::createThread(uint16 scriptModuleNumber, uint16 scriptEntry else newThread._voiceLUT = &_modules[scriptModuleNumber].voiceLUT; - _threadList.push_front(newThread); - + newThread._stackBuf.resize(ScriptThread::THREAD_STACK_SIZE); + newThread._stackTopIndex = ScriptThread::THREAD_STACK_SIZE - 2; debug(3, "createThread(). Total threads: %d", _threadList.size()); - - ScriptThread &tmp = *_threadList.begin(); - tmp._stackBuf = (int16 *)malloc(ScriptThread::THREAD_STACK_SIZE * sizeof(int16)); - tmp._stackTopIndex = ScriptThread::THREAD_STACK_SIZE - 2; - return tmp; + return newThread; } void Script::wakeUpActorThread(int waitType, void *threadObj) { @@ -211,7 +209,7 @@ bool Script::runThread(ScriptThread &thread) { savedInstructionOffset = thread._instructionOffset; operandChar = scriptS.readByte(); - debug(8, "Executing thread offset: %u (%x) stack: %d", thread._instructionOffset, operandChar, thread.pushedSize()); + debug(8, "Executing thread offset: %u (0x%X) stack: %d", thread._instructionOffset, operandChar, thread.pushedSize()); stopParsing = false; debug(4, "Calling op %s", this->_scriptOpsList[operandChar].scriptOpName); |