From 9916b263831f20e5841275051a8ed014de1f24eb Mon Sep 17 00:00:00 2001 From: Colin Snover Date: Wed, 29 Nov 2017 00:06:12 -0600 Subject: SCUMM: Replace UB-triggering serialization code with Common::Serializer Fixes Trac#10342. --- engines/scumm/actor.cpp | 284 ++++--- engines/scumm/actor.h | 9 +- engines/scumm/charset.cpp | 15 +- engines/scumm/charset.h | 2 +- engines/scumm/he/intern_he.h | 12 +- engines/scumm/he/sprite_he.cpp | 137 ++-- engines/scumm/he/sprite_he.h | 6 +- engines/scumm/imuse/imuse.cpp | 85 +- engines/scumm/imuse/imuse.h | 4 +- engines/scumm/imuse/imuse_internal.h | 11 +- engines/scumm/imuse/imuse_part.cpp | 54 +- engines/scumm/imuse/imuse_player.cpp | 101 ++- engines/scumm/imuse/instrument.cpp | 106 ++- engines/scumm/imuse/instrument.h | 9 +- engines/scumm/imuse_digi/dimuse.cpp | 94 ++- engines/scumm/imuse_digi/dimuse.h | 4 +- engines/scumm/music.h | 7 +- engines/scumm/players/player_ad.cpp | 31 +- engines/scumm/players/player_ad.h | 4 +- engines/scumm/players/player_mac.cpp | 53 +- engines/scumm/players/player_mac.h | 4 +- engines/scumm/players/player_towns.cpp | 63 +- engines/scumm/players/player_towns.h | 7 +- engines/scumm/saveload.cpp | 1333 +++++++++++++------------------- engines/scumm/saveload.h | 120 +-- engines/scumm/scumm.h | 13 +- engines/scumm/scumm_v0.h | 2 +- engines/scumm/scumm_v2.h | 2 +- engines/scumm/scumm_v5.h | 2 +- engines/scumm/scumm_v7.h | 3 +- engines/scumm/sound.cpp | 11 +- engines/scumm/sound.h | 6 +- 32 files changed, 1061 insertions(+), 1533 deletions(-) (limited to 'engines') diff --git a/engines/scumm/actor.cpp b/engines/scumm/actor.cpp index 66a7d90b42..c00e38e91d 100644 --- a/engines/scumm/actor.cpp +++ b/engines/scumm/actor.cpp @@ -3437,43 +3437,38 @@ void Actor_v0::actorSetWalkTo() { } } -void Actor_v0::saveLoadWithSerializer(Serializer *ser) { - Actor::saveLoadWithSerializer(ser); - - static const SaveLoadEntry actorEntries[] = { - MKLINE(Actor_v0, _costCommand, sleByte, VER(84)), - MK_OBSOLETE(Actor_v0, _costFrame, sleByte, VER(84), VER(89)), - MKLINE(Actor_v0, _miscflags, sleByte, VER(84)), - MKLINE(Actor_v0, _speaking, sleByte, VER(84)), - MK_OBSOLETE(Actor_v0, _speakingPrev, sleByte, VER(84), VER(89)), - MK_OBSOLETE(Actor_v0, _limbTemp, sleByte, VER(89), VER(89)), - MKLINE(Actor_v0, _animFrameRepeat, sleByte, VER(89)), - MKARRAY(Actor_v0, _limbFrameRepeatNew[0], sleInt8, 8, VER(89)), - MKARRAY(Actor_v0, _limbFrameRepeat[0], sleInt8, 8, VER(90)), - MKLINE(Actor_v0, _CurrentWalkTo.x, sleInt16, VER(97)), - MKLINE(Actor_v0, _CurrentWalkTo.y, sleInt16, VER(97)), - MKLINE(Actor_v0, _NewWalkTo.x, sleInt16, VER(97)), - MKLINE(Actor_v0, _NewWalkTo.y, sleInt16, VER(97)), - MKLINE(Actor_v0, _walkCountModulo, sleInt8, VER(97)), - MKLINE(Actor_v0, _newWalkBoxEntered, sleByte, VER(97)), - MKLINE(Actor_v0, _walkDirX, sleByte, VER(97)), - MKLINE(Actor_v0, _walkDirY, sleByte, VER(97)), - MKLINE(Actor_v0, _walkYCountGreaterThanXCount, sleByte, VER(97)), - MKLINE(Actor_v0, _walkXCount, sleByte, VER(97)), - MKLINE(Actor_v0, _walkXCountInc, sleByte, VER(97)), - MKLINE(Actor_v0, _walkYCount, sleByte, VER(97)), - MKLINE(Actor_v0, _walkYCountInc, sleByte, VER(97)), - MKLINE(Actor_v0, _walkMaxXYCountInc, sleByte, VER(97)), - - MKARRAY(Actor_v0, _walkboxQueue[0], sleByte, 16, VER(98)), - MKLINE(Actor_v0, _walkboxQueueIndex, sleByte, VER(98)), - MKEND() - }; - - ser->saveLoadEntries(this, actorEntries); +void Actor_v0::saveLoadWithSerializer(Common::Serializer &s) { + Actor::saveLoadWithSerializer(s); + + s.syncAsByte(_costCommand, VER(84)); + s.skip(1, VER(84), VER(89)); // _costFrame + s.syncAsByte(_miscflags, VER(84)); + s.syncAsByte(_speaking, VER(84)); + s.skip(1, VER(84), VER(89)); // _speakingPrev + s.skip(1, VER(89), VER(89)); // _limbTemp + s.syncAsByte(_animFrameRepeat, VER(89)); + s.syncArray(_limbFrameRepeatNew, 8, Common::Serializer::SByte, VER(89)); + s.syncArray(_limbFrameRepeat, 8, Common::Serializer::SByte, VER(90)); + s.syncAsSint16LE(_CurrentWalkTo.x, VER(97)); + s.syncAsSint16LE(_CurrentWalkTo.y, VER(97)); + s.syncAsSint16LE(_NewWalkTo.x, VER(97)); + s.syncAsSint16LE(_NewWalkTo.y, VER(97)); + s.syncAsSByte(_walkCountModulo, VER(97)); + s.syncAsByte(_newWalkBoxEntered, VER(97)); + s.syncAsByte(_walkDirX, VER(97)); + s.syncAsByte(_walkDirY, VER(97)); + s.syncAsByte(_walkYCountGreaterThanXCount, VER(97)); + s.syncAsByte(_walkXCount, VER(97)); + s.syncAsByte(_walkXCountInc, VER(97)); + s.syncAsByte(_walkYCount, VER(97)); + s.syncAsByte(_walkYCountInc, VER(97)); + s.syncAsByte(_walkMaxXYCountInc, VER(97)); + + s.syncBytes(_walkboxQueue, 16, VER(98)); + s.syncAsByte(_walkboxQueueIndex, VER(98)); // When loading, we need to ensure the limbs are restarted - if (ser->isLoading()) { + if (s.isLoading()) { // valid costume command? if (_costCommand != 0xFF) { @@ -3498,124 +3493,119 @@ void Actor_v0::saveLoadWithSerializer(Serializer *ser) { } } -void Actor::saveLoadWithSerializer(Serializer *ser) { - static const SaveLoadEntry actorEntries[] = { - MKLINE(Actor, _pos.x, sleInt16, VER(8)), - MKLINE(Actor, _pos.y, sleInt16, VER(8)), - MKLINE(Actor, _heOffsX, sleInt16, VER(32)), - MKLINE(Actor, _heOffsY, sleInt16, VER(32)), - MKLINE(Actor, _top, sleInt16, VER(8)), - MKLINE(Actor, _bottom, sleInt16, VER(8)), - MKLINE(Actor, _elevation, sleInt16, VER(8)), - MKLINE(Actor, _width, sleUint16, VER(8)), - MKLINE(Actor, _facing, sleUint16, VER(8)), - MKLINE(Actor, _costume, sleUint16, VER(8)), - MKLINE(Actor, _room, sleByte, VER(8)), - MKLINE(Actor, _talkColor, sleByte, VER(8)), - MKLINE(Actor, _talkFrequency, sleInt16, VER(16)), - MKLINE(Actor, _talkPan, sleInt16, VER(24)), - MKLINE(Actor, _talkVolume, sleInt16, VER(29)), - MKLINE(Actor, _boxscale, sleUint16, VER(34)), - MKLINE(Actor, _scalex, sleByte, VER(8)), - MKLINE(Actor, _scaley, sleByte, VER(8)), - MKLINE(Actor, _charset, sleByte, VER(8)), - - // Actor sound grew from 8 to 32 bytes and switched to uint16 in HE games - MKARRAY_OLD(Actor, _sound[0], sleByte, 8, VER(8), VER(36)), - MKARRAY_OLD(Actor, _sound[0], sleByte, 32, VER(37), VER(61)), - MKARRAY(Actor, _sound[0], sleUint16, 32, VER(62)), - - // Actor animVariable grew from 8 to 27 - MKARRAY_OLD(Actor, _animVariable[0], sleUint16, 8, VER(8), VER(40)), - MKARRAY(Actor, _animVariable[0], sleUint16, 27, VER(41)), - - MKLINE(Actor, _targetFacing, sleUint16, VER(8)), - MKLINE(Actor, _moving, sleByte, VER(8)), - MKLINE(Actor, _ignoreBoxes, sleByte, VER(8)), - MKLINE(Actor, _forceClip, sleByte, VER(8)), - MKLINE(Actor, _initFrame, sleByte, VER(8)), - MKLINE(Actor, _walkFrame, sleByte, VER(8)), - MKLINE(Actor, _standFrame, sleByte, VER(8)), - MKLINE(Actor, _talkStartFrame, sleByte, VER(8)), - MKLINE(Actor, _talkStopFrame, sleByte, VER(8)), - MKLINE(Actor, _speedx, sleUint16, VER(8)), - MKLINE(Actor, _speedy, sleUint16, VER(8)), - MKLINE(Actor, _cost.animCounter, sleUint16, VER(8)), - MKLINE(Actor, _cost.soundCounter, sleByte, VER(8)), - MKLINE(Actor, _drawToBackBuf, sleByte, VER(32)), - MKLINE(Actor, _flip, sleByte, VER(32)), - MKLINE(Actor, _heSkipLimbs, sleByte, VER(32)), - - // Actor palette grew from 64 to 256 bytes and switched to uint16 in HE games - MKARRAY_OLD(Actor, _palette[0], sleByte, 64, VER(8), VER(9)), - MKARRAY_OLD(Actor, _palette[0], sleByte, 256, VER(10), VER(79)), - MKARRAY(Actor, _palette[0], sleUint16, 256, VER(80)), - - MK_OBSOLETE(Actor, _mask, sleByte, VER(8), VER(9)), - MKLINE(Actor, _shadowMode, sleByte, VER(8)), - MKLINE(Actor, _visible, sleByte, VER(8)), - MKLINE(Actor, _frame, sleByte, VER(8)), - MKLINE(Actor, _animSpeed, sleByte, VER(8)), - MKLINE(Actor, _animProgress, sleByte, VER(8)), - MKLINE(Actor, _walkbox, sleByte, VER(8)), - MKLINE(Actor, _needRedraw, sleByte, VER(8)), - MKLINE(Actor, _needBgReset, sleByte, VER(8)), - MKLINE(Actor, _costumeNeedsInit, sleByte, VER(8)), - MKLINE(Actor, _heCondMask, sleUint32, VER(38)), - MKLINE(Actor, _hePaletteNum, sleUint32, VER(59)), - MKLINE(Actor, _heXmapNum, sleUint32, VER(59)), - - MKLINE(Actor, _talkPosY, sleInt16, VER(8)), - MKLINE(Actor, _talkPosX, sleInt16, VER(8)), - MKLINE(Actor, _ignoreTurns, sleByte, VER(8)), - - // Actor layer switched to int32 in HE games - MKLINE_OLD(Actor, _layer, sleByte, VER(8), VER(57)), - MKLINE(Actor, _layer, sleInt32, VER(58)), - - MKLINE(Actor, _talkScript, sleUint16, VER(8)), - MKLINE(Actor, _walkScript, sleUint16, VER(8)), - - MKLINE(Actor, _walkdata.dest.x, sleInt16, VER(8)), - MKLINE(Actor, _walkdata.dest.y, sleInt16, VER(8)), - MKLINE(Actor, _walkdata.destbox, sleByte, VER(8)), - MKLINE(Actor, _walkdata.destdir, sleUint16, VER(8)), - MKLINE(Actor, _walkdata.curbox, sleByte, VER(8)), - MKLINE(Actor, _walkdata.cur.x, sleInt16, VER(8)), - MKLINE(Actor, _walkdata.cur.y, sleInt16, VER(8)), - MKLINE(Actor, _walkdata.next.x, sleInt16, VER(8)), - MKLINE(Actor, _walkdata.next.y, sleInt16, VER(8)), - MKLINE(Actor, _walkdata.deltaXFactor, sleInt32, VER(8)), - MKLINE(Actor, _walkdata.deltaYFactor, sleInt32, VER(8)), - MKLINE(Actor, _walkdata.xfrac, sleUint16, VER(8)), - MKLINE(Actor, _walkdata.yfrac, sleUint16, VER(8)), - - MKLINE(Actor, _walkdata.point3.x, sleUint16, VER(42)), - MKLINE(Actor, _walkdata.point3.y, sleUint16, VER(42)), - - MKARRAY(Actor, _cost.active[0], sleByte, 16, VER(8)), - MKLINE(Actor, _cost.stopped, sleUint16, VER(8)), - MKARRAY(Actor, _cost.curpos[0], sleUint16, 16, VER(8)), - MKARRAY(Actor, _cost.start[0], sleUint16, 16, VER(8)), - MKARRAY(Actor, _cost.end[0], sleUint16, 16, VER(8)), - MKARRAY(Actor, _cost.frame[0], sleUint16, 16, VER(8)), - - MKARRAY(Actor, _cost.heJumpOffsetTable[0], sleUint16, 16, VER(65)), - MKARRAY(Actor, _cost.heJumpCountTable[0], sleUint16, 16, VER(65)), - MKARRAY(Actor, _cost.heCondMaskTable[0], sleUint32, 16, VER(65)), - MKEND() - }; - - if (ser->isLoading()) { +void Actor::saveLoadWithSerializer(Common::Serializer &s) { + if (s.isLoading()) { // Not all actor data is saved; so when loading, we first reset // the actor, to ensure completely reproducible behavior (else, // some not saved value in the actor class can cause odd things) initActor(-1); } - ser->saveLoadEntries(this, actorEntries); - - if (ser->isLoading() && _vm->_game.version <= 2 && ser->getVersion() < VER(70)) { + s.syncAsSint16LE(_pos.x, VER(8)); + s.syncAsSint16LE(_pos.y, VER(8)); + s.syncAsSint16LE(_heOffsX, VER(32)); + s.syncAsSint16LE(_heOffsY, VER(32)); + s.syncAsSint16LE(_top, VER(8)); + s.syncAsSint16LE(_bottom, VER(8)); + s.syncAsSint16LE(_elevation, VER(8)); + s.syncAsUint16LE(_width, VER(8)); + s.syncAsUint16LE(_facing, VER(8)); + s.syncAsUint16LE(_costume, VER(8)); + s.syncAsByte(_room, VER(8)); + s.syncAsByte(_talkColor, VER(8)); + s.syncAsSint16LE(_talkFrequency, VER(16)); + s.syncAsSint16LE(_talkPan, VER(24)); + s.syncAsSint16LE(_talkVolume, VER(29)); + s.syncAsUint16LE(_boxscale, VER(34)); + s.syncAsByte(_scalex, VER(8)); + s.syncAsByte(_scaley, VER(8)); + s.syncAsByte(_charset, VER(8)); + + // Actor sound grew from 8 to 32 bytes and switched to uint16 in HE games + s.syncArray(_sound, 8, Common::Serializer::Byte, VER(8), VER(36)); + s.syncArray(_sound, 32, Common::Serializer::Byte, VER(37), VER(61)); + s.syncArray(_sound, 32, Common::Serializer::Uint16LE, VER(62)); + + // Actor animVariable grew from 8 to 27 + s.syncArray(_animVariable, 8, Common::Serializer::Uint16LE, VER(8), VER(40)); + s.syncArray(_animVariable, 27, Common::Serializer::Uint16LE, VER(41)); + + s.syncAsUint16LE(_targetFacing, VER(8)); + s.syncAsByte(_moving, VER(8)); + s.syncAsByte(_ignoreBoxes, VER(8)); + s.syncAsByte(_forceClip, VER(8)); + s.syncAsByte(_initFrame, VER(8)); + s.syncAsByte(_walkFrame, VER(8)); + s.syncAsByte(_standFrame, VER(8)); + s.syncAsByte(_talkStartFrame, VER(8)); + s.syncAsByte(_talkStopFrame, VER(8)); + s.syncAsUint16LE(_speedx, VER(8)); + s.syncAsUint16LE(_speedy, VER(8)); + s.syncAsUint16LE(_cost.animCounter, VER(8)); + s.syncAsByte(_cost.soundCounter, VER(8)); + s.syncAsByte(_drawToBackBuf, VER(32)); + s.syncAsByte(_flip, VER(32)); + s.syncAsByte(_heSkipLimbs, VER(32)); + + // Actor palette grew from 64 to 256 bytes and switched to uint16 in HE games + s.syncArray(_palette, 64, Common::Serializer::Byte, VER(8), VER(9)); + s.syncArray(_palette, 256, Common::Serializer::Byte, VER(10), VER(79)); + s.syncArray(_palette, 256, Common::Serializer::Uint16LE, VER(80)); + + s.skip(1, VER(8), VER(9)); // _mask + s.syncAsByte(_shadowMode, VER(8)); + s.syncAsByte(_visible, VER(8)); + s.syncAsByte(_frame, VER(8)); + s.syncAsByte(_animSpeed, VER(8)); + s.syncAsByte(_animProgress, VER(8)); + s.syncAsByte(_walkbox, VER(8)); + s.syncAsByte(_needRedraw, VER(8)); + s.syncAsByte(_needBgReset, VER(8)); + s.syncAsByte(_costumeNeedsInit, VER(8)); + s.syncAsUint32LE(_heCondMask, VER(38)); + s.syncAsUint32LE(_hePaletteNum, VER(59)); + s.syncAsUint32LE(_heXmapNum, VER(59)); + + s.syncAsSint16LE(_talkPosY, VER(8)); + s.syncAsSint16LE(_talkPosX, VER(8)); + s.syncAsByte(_ignoreTurns, VER(8)); + + // Actor layer switched to int32 in HE games + s.syncAsByte(_layer, VER(8), VER(57)); + s.syncAsSint32LE(_layer, VER(58)); + + s.syncAsUint16LE(_talkScript, VER(8)); + s.syncAsUint16LE(_walkScript, VER(8)); + + s.syncAsSint16LE(_walkdata.dest.x, VER(8)); + s.syncAsSint16LE(_walkdata.dest.y, VER(8)); + s.syncAsByte(_walkdata.destbox, VER(8)); + s.syncAsUint16LE(_walkdata.destdir, VER(8)); + s.syncAsByte(_walkdata.curbox, VER(8)); + s.syncAsSint16LE(_walkdata.cur.x, VER(8)); + s.syncAsSint16LE(_walkdata.cur.y, VER(8)); + s.syncAsSint16LE(_walkdata.next.x, VER(8)); + s.syncAsSint16LE(_walkdata.next.y, VER(8)); + s.syncAsSint32LE(_walkdata.deltaXFactor, VER(8)); + s.syncAsSint32LE(_walkdata.deltaYFactor, VER(8)); + s.syncAsUint16LE(_walkdata.xfrac, VER(8)); + s.syncAsUint16LE(_walkdata.yfrac, VER(8)); + + s.syncAsUint16LE(_walkdata.point3.x, VER(42)); + s.syncAsUint16LE(_walkdata.point3.y, VER(42)); + + s.syncBytes(_cost.active, 16, VER(8)); + s.syncAsUint16LE(_cost.stopped, VER(8)); + s.syncArray(_cost.curpos, 16, Common::Serializer::Uint16LE, VER(8)); + s.syncArray(_cost.start, 16, Common::Serializer::Uint16LE, VER(8)); + s.syncArray(_cost.end, 16, Common::Serializer::Uint16LE, VER(8)); + s.syncArray(_cost.frame, 16, Common::Serializer::Uint16LE, VER(8)); + + s.syncArray(_cost.heJumpOffsetTable, 16, Common::Serializer::Uint16LE, VER(65)); + s.syncArray(_cost.heJumpCountTable, 16, Common::Serializer::Uint16LE, VER(65)); + s.syncArray(_cost.heCondMaskTable, 16, Common::Serializer::Uint32LE, VER(65)); + + if (s.isLoading() && _vm->_game.version <= 2 && s.getVersion() < VER(70)) { _pos.x >>= V12_X_SHIFT; _pos.y >>= V12_Y_SHIFT; diff --git a/engines/scumm/actor.h b/engines/scumm/actor.h index 62ba161f4e..c059d08397 100644 --- a/engines/scumm/actor.h +++ b/engines/scumm/actor.h @@ -25,6 +25,7 @@ #define SCUMM_ACTOR_H #include "common/scummsys.h" +#include "common/serializer.h" #include "scumm/saveload.h" #include "scumm/scumm.h" @@ -82,7 +83,7 @@ enum { kNewInavlidBox = 0 }; -class Actor : public Serializable { +class Actor : public Common::Serializable { public: static byte kInvalidBox; @@ -300,8 +301,7 @@ public: void classChanged(int cls, bool value); - // Used by the save/load system: - virtual void saveLoadWithSerializer(Serializer *ser); + virtual void saveLoadWithSerializer(Common::Serializer &ser); protected: bool isInClass(int cls); @@ -421,8 +421,7 @@ public: void setTmpFromActor(); void setActorFromTmp(); - // Used by the save/load system: - virtual void saveLoadWithSerializer(Serializer *ser); + virtual void saveLoadWithSerializer(Common::Serializer &ser); }; diff --git a/engines/scumm/charset.cpp b/engines/scumm/charset.cpp index e546c805b5..214eeb7d5c 100644 --- a/engines/scumm/charset.cpp +++ b/engines/scumm/charset.cpp @@ -708,17 +708,12 @@ void CharsetRenderer::translateColor() { } } -void CharsetRenderer::saveLoadWithSerializer(Serializer *ser) { - static const SaveLoadEntry charsetRendererEntries[] = { - MKLINE_OLD(CharsetRenderer, _curId, sleByte, VER(73), VER(73)), - MKLINE(CharsetRenderer, _curId, sleInt32, VER(74)), - MKLINE(CharsetRenderer, _color, sleByte, VER(73)), - MKEND() - }; +void CharsetRenderer::saveLoadWithSerializer(Common::Serializer &ser) { + ser.syncAsByte(_curId, VER(73), VER(73)); + ser.syncAsSint32LE(_curId, VER(74)); + ser.syncAsByte(_color, VER(73)); - ser->saveLoadEntries(this, charsetRendererEntries); - - if (ser->isLoading()) { + if (ser.isLoading()) { setCurID(_curId); setColor(_color); } diff --git a/engines/scumm/charset.h b/engines/scumm/charset.h index b4b3d88ccd..7f3a8baf88 100644 --- a/engines/scumm/charset.h +++ b/engines/scumm/charset.h @@ -89,7 +89,7 @@ public: virtual void setColor(byte color) { _color = color; translateColor(); } - void saveLoadWithSerializer(Serializer *ser); + void saveLoadWithSerializer(Common::Serializer &ser); }; class CharsetRendererCommon : public CharsetRenderer { diff --git a/engines/scumm/he/intern_he.h b/engines/scumm/he/intern_he.h index bd3cdb2c57..25dd31f007 100644 --- a/engines/scumm/he/intern_he.h +++ b/engines/scumm/he/intern_he.h @@ -73,7 +73,7 @@ public: protected: virtual void setupOpcodes(); - virtual void saveOrLoad(Serializer *s); + virtual void saveLoadWithSerializer(Common::Serializer &s); void localizeArray(int slot, byte scriptSlot); void redimArray(int arrayId, int newX, int newY, int d); @@ -163,7 +163,7 @@ protected: virtual void setupScummVars(); virtual void resetScummVars(); - virtual void saveOrLoad(Serializer *s); + virtual void saveLoadWithSerializer(Common::Serializer &s); virtual void readRoomsOffsets(); virtual void readGlobalObjects(); @@ -222,7 +222,7 @@ public: protected: virtual void setupOpcodes(); - virtual void saveOrLoad(Serializer *s); + virtual void saveLoadWithSerializer(Common::Serializer &s); virtual void redrawBGAreas(); @@ -490,7 +490,7 @@ protected: virtual void processInput(); virtual void clearClickedStatus(); - virtual void saveOrLoad(Serializer *s); + virtual void saveLoadWithSerializer(Common::Serializer &s); virtual void readMAXS(int blockSize); void setResourceOffHeap(int typeId, int resId, int val); @@ -581,7 +581,7 @@ protected: virtual void readMAXS(int blockSize); - virtual void saveOrLoad(Serializer *s); + virtual void saveLoadWithSerializer(Common::Serializer &s); virtual void copyPalColor(int dst, int src); virtual void darkenPalette(int redScale, int greenScale, int blueScale, int startColor, int endColor); @@ -613,7 +613,7 @@ public: protected: virtual void setupOpcodes(); - virtual void saveOrLoad(Serializer *s); + virtual void saveLoadWithSerializer(Common::Serializer &s); virtual void decodeParseString(int a, int b); diff --git a/engines/scumm/he/sprite_he.cpp b/engines/scumm/he/sprite_he.cpp index bef1c0b5eb..16c3b50365 100644 --- a/engines/scumm/he/sprite_he.cpp +++ b/engines/scumm/he/sprite_he.cpp @@ -1389,80 +1389,79 @@ void Sprite::processImages(bool arg) { } } -void Sprite::saveOrLoadSpriteData(Serializer *s) { - static const SaveLoadEntry spriteEntries[] = { - MKLINE(SpriteInfo, id, sleInt32, VER(48)), - MKLINE(SpriteInfo, zorder, sleInt32, VER(48)), - MKLINE(SpriteInfo, flags, sleInt32, VER(48)), - MKLINE(SpriteInfo, image, sleInt32, VER(48)), - MKLINE(SpriteInfo, imageState, sleInt32, VER(48)), - MKLINE(SpriteInfo, group, sleInt32, VER(48)), - MKLINE(SpriteInfo, palette, sleInt32, VER(48)), - MKLINE(SpriteInfo, priority, sleInt32, VER(48)), - MKLINE(SpriteInfo, bbox.left, sleInt32, VER(48)), - MKLINE(SpriteInfo, bbox.top, sleInt32, VER(48)), - MKLINE(SpriteInfo, bbox.right, sleInt32, VER(48)), - MKLINE(SpriteInfo, bbox.bottom, sleInt32, VER(48)), - MKLINE(SpriteInfo, dx, sleInt32, VER(48)), - MKLINE(SpriteInfo, dy, sleInt32, VER(48)), - MKLINE(SpriteInfo, pos.x, sleInt32, VER(48)), - MKLINE(SpriteInfo, pos.y, sleInt32, VER(48)), - MKLINE(SpriteInfo, tx, sleInt32, VER(48)), - MKLINE(SpriteInfo, ty, sleInt32, VER(48)), - MKLINE(SpriteInfo, userValue, sleInt32, VER(48)), - MKLINE(SpriteInfo, curImageState, sleInt32, VER(48)), - MKLINE(SpriteInfo, curImage, sleInt32, VER(48)), - MKLINE(SpriteInfo, imglistNum, sleInt32, VER(48)), - MKLINE(SpriteInfo, shadow, sleInt32, VER(48)), - MKLINE(SpriteInfo, imageStateCount, sleInt32, VER(48)), - MKLINE(SpriteInfo, angle, sleInt32, VER(48)), - MKLINE(SpriteInfo, scale, sleInt32, VER(48)), - MKLINE(SpriteInfo, animProgress, sleInt32, VER(48)), - MKLINE(SpriteInfo, curAngle, sleInt32, VER(48)), - MKLINE(SpriteInfo, curScale, sleInt32, VER(48)), - MKLINE(SpriteInfo, curImgFlags, sleInt32, VER(48)), - MKLINE(SpriteInfo, animIndex, sleInt32, VER(48)), - MKLINE(SpriteInfo, animSpeed, sleInt32, VER(48)), - MKLINE(SpriteInfo, sourceImage, sleInt32, VER(48)), - MKLINE(SpriteInfo, maskImage, sleInt32, VER(48)), - MKLINE(SpriteInfo, zbufferImage, sleInt32, VER(48)), - MKLINE(SpriteInfo, classFlags, sleInt32, VER(48)), - MKLINE(SpriteInfo, imgFlags, sleInt32, VER(48)), - MKLINE(SpriteInfo, conditionBits, sleInt32, VER(48)), - MKEND() - }; - - static const SaveLoadEntry spriteGroupEntries[] = { - MKLINE(SpriteGroup, bbox.left, sleInt32, VER(48)), - MKLINE(SpriteGroup, bbox.top, sleInt32, VER(48)), - MKLINE(SpriteGroup, bbox.right, sleInt32, VER(48)), - MKLINE(SpriteGroup, bbox.bottom, sleInt32, VER(48)), - MKLINE(SpriteGroup, priority, sleInt32, VER(48)), - MKLINE(SpriteGroup, flags, sleInt32, VER(48)), - MKLINE(SpriteGroup, tx, sleInt32, VER(48)), - MKLINE(SpriteGroup, ty, sleInt32, VER(48)), - MKLINE(SpriteGroup, image, sleInt32, VER(48)), - MKLINE(SpriteGroup, scaling, sleInt32, VER(48)), - MKLINE(SpriteGroup, scale_x_ratio_mul, sleInt32, VER(48)), - MKLINE(SpriteGroup, scale_x_ratio_div, sleInt32, VER(48)), - MKLINE(SpriteGroup, scale_y_ratio_mul, sleInt32, VER(48)), - MKLINE(SpriteGroup, scale_y_ratio_div, sleInt32, VER(48)), - MKEND() - }; - - if (s->getVersion() >= VER(64)) { - s->saveLoadArrayOf(_spriteTable, _varNumSprites + 1, sizeof(_spriteTable[0]), spriteEntries); - s->saveLoadArrayOf(_spriteGroups, _varNumSpriteGroups + 1, sizeof(_spriteGroups[0]), spriteGroupEntries); +static void syncWithSerializer(Common::Serializer &s, SpriteInfo &si) { + s.syncAsSint32LE(si.id, VER(48)); + s.syncAsSint32LE(si.zorder, VER(48)); + s.syncAsSint32LE(si.flags, VER(48)); + s.syncAsSint32LE(si.image, VER(48)); + s.syncAsSint32LE(si.imageState, VER(48)); + s.syncAsSint32LE(si.group, VER(48)); + s.syncAsSint32LE(si.palette, VER(48)); + s.syncAsSint32LE(si.priority, VER(48)); + s.syncAsSint32LE(si.bbox.left, VER(48)); + s.syncAsSint32LE(si.bbox.top, VER(48)); + s.syncAsSint32LE(si.bbox.right, VER(48)); + s.syncAsSint32LE(si.bbox.bottom, VER(48)); + s.syncAsSint32LE(si.dx, VER(48)); + s.syncAsSint32LE(si.dy, VER(48)); + s.syncAsSint32LE(si.pos.x, VER(48)); + s.syncAsSint32LE(si.pos.y, VER(48)); + s.syncAsSint32LE(si.tx, VER(48)); + s.syncAsSint32LE(si.ty, VER(48)); + s.syncAsSint32LE(si.userValue, VER(48)); + s.syncAsSint32LE(si.curImageState, VER(48)); + s.syncAsSint32LE(si.curImage, VER(48)); + s.syncAsSint32LE(si.imglistNum, VER(48)); + s.syncAsSint32LE(si.shadow, VER(48)); + s.syncAsSint32LE(si.imageStateCount, VER(48)); + s.syncAsSint32LE(si.angle, VER(48)); + s.syncAsSint32LE(si.scale, VER(48)); + s.syncAsSint32LE(si.animProgress, VER(48)); + s.syncAsSint32LE(si.curAngle, VER(48)); + s.syncAsSint32LE(si.curScale, VER(48)); + s.syncAsSint32LE(si.curImgFlags, VER(48)); + s.syncAsSint32LE(si.animIndex, VER(48)); + s.syncAsSint32LE(si.animSpeed, VER(48)); + s.syncAsSint32LE(si.sourceImage, VER(48)); + s.syncAsSint32LE(si.maskImage, VER(48)); + s.syncAsSint32LE(si.zbufferImage, VER(48)); + s.syncAsSint32LE(si.classFlags, VER(48)); + s.syncAsSint32LE(si.imgFlags, VER(48)); + s.syncAsSint32LE(si.conditionBits, VER(48)); +} + +static void syncWithSerializer(Common::Serializer &s, SpriteGroup &sg) { + s.syncAsSint32LE(sg.bbox.left, VER(48)); + s.syncAsSint32LE(sg.bbox.top, VER(48)); + s.syncAsSint32LE(sg.bbox.right, VER(48)); + s.syncAsSint32LE(sg.bbox.bottom, VER(48)); + s.syncAsSint32LE(sg.priority, VER(48)); + s.syncAsSint32LE(sg.flags, VER(48)); + s.syncAsSint32LE(sg.tx, VER(48)); + s.syncAsSint32LE(sg.ty, VER(48)); + s.syncAsSint32LE(sg.image, VER(48)); + s.syncAsSint32LE(sg.scaling, VER(48)); + s.syncAsSint32LE(sg.scale_x_ratio_mul, VER(48)); + s.syncAsSint32LE(sg.scale_x_ratio_div, VER(48)); + s.syncAsSint32LE(sg.scale_y_ratio_mul, VER(48)); + s.syncAsSint32LE(sg.scale_y_ratio_div, VER(48)); +} + +void Sprite::saveLoadWithSerializer(Common::Serializer &s) { + if (s.getVersion() >= VER(64)) { + s.syncArray(_spriteTable, _varNumSprites + 1, syncWithSerializer); + s.syncArray(_spriteGroups, _varNumSpriteGroups + 1, syncWithSerializer); } else { - s->saveLoadArrayOf(_activeSpritesTable, _varNumSprites, sizeof(_activeSpritesTable[0]), spriteEntries); - s->saveLoadArrayOf(_spriteTable, _varNumSprites, sizeof(_spriteTable[0]), spriteEntries); - s->saveLoadArrayOf(_spriteGroups, _varNumSpriteGroups, sizeof(_spriteGroups[0]), spriteGroupEntries); + // TODO: This had been bogus, what is it really supposed to do? +// s->saveLoadArrayOf(_activeSpritesTable, _varNumSprites, sizeof(_activeSpritesTable[0]), spriteEntries); + s.syncArray(*_activeSpritesTable, _varNumSprites, syncWithSerializer); + s.syncArray(_spriteTable, _varNumSprites, syncWithSerializer); + s.syncArray(_spriteGroups, _varNumSpriteGroups, syncWithSerializer); } // Reset active sprite table - if (s->isLoading()) + if (s.isLoading()) _numSpritesToProcess = 0; - } } // End of namespace Scumm diff --git a/engines/scumm/he/sprite_he.h b/engines/scumm/he/sprite_he.h index 3ea6bb9f84..77e527b3ce 100644 --- a/engines/scumm/he/sprite_he.h +++ b/engines/scumm/he/sprite_he.h @@ -23,6 +23,8 @@ #if !defined(SCUMM_HE_SPRITE_HE_H) && defined(ENABLE_HE) #define SCUMM_HE_SPRITE_HE_H +#include "common/serializer.h" + namespace Scumm { enum SpriteFlags { @@ -98,7 +100,7 @@ struct SpriteGroup { class ScummEngine_v90he; -class Sprite { +class Sprite : public Common::Serializable { public: Sprite(ScummEngine_v90he *vm); virtual ~Sprite(); @@ -112,7 +114,7 @@ public: int32 _varNumSprites; int32 _varMaxSprites; - void saveOrLoadSpriteData(Serializer *s); + void saveLoadWithSerializer(Common::Serializer &s); void resetBackground(); void setRedrawFlags(bool checkZOrder); void sortActiveSprites(); diff --git a/engines/scumm/imuse/imuse.cpp b/engines/scumm/imuse/imuse.cpp index b7b72ba181..d083dc8dfd 100644 --- a/engines/scumm/imuse/imuse.cpp +++ b/engines/scumm/imuse/imuse.cpp @@ -362,70 +362,50 @@ void IMuseInternal::pause(bool paused) { _paused = paused; } -int IMuseInternal::save_or_load(Serializer *ser, ScummEngine *scumm, bool fixAfterLoad) { - Common::StackLock lock(_mutex, "IMuseInternal::save_or_load()"); - const SaveLoadEntry mainEntries[] = { - MKLINE(IMuseInternal, _queue_end, sleUint8, VER(8)), - MKLINE(IMuseInternal, _queue_pos, sleUint8, VER(8)), - MKLINE(IMuseInternal, _queue_sound, sleUint16, VER(8)), - MKLINE(IMuseInternal, _queue_adding, sleByte, VER(8)), - MKLINE(IMuseInternal, _queue_marker, sleByte, VER(8)), - MKLINE(IMuseInternal, _queue_cleared, sleByte, VER(8)), - MKLINE(IMuseInternal, _master_volume, sleByte, VER(8)), - MKLINE(IMuseInternal, _trigger_count, sleUint16, VER(8)), - MKLINE(IMuseInternal, _snm_trigger_index, sleUint16, VER(54)), - MKARRAY(IMuseInternal, _channel_volume[0], sleUint16, 8, VER(8)), - MKARRAY(IMuseInternal, _volchan_table[0], sleUint16, 8, VER(8)), - MKEND() - }; - - const SaveLoadEntry cmdQueueEntries[] = { - MKARRAY(CommandQueue, array[0], sleUint16, 8, VER(23)), - MKEND() - }; +static void syncWithSerializer(Common::Serializer &s, CommandQueue &cq) { + s.syncArray(cq.array, 8, Common::Serializer::Uint16LE, VER(23)); +} - // VolumeFader is obsolete. - const SaveLoadEntry volumeFaderEntries[] = { - MK_OBSOLETE(VolumeFader, player, sleUint16, VER(8), VER(16)), - MK_OBSOLETE(VolumeFader, active, sleUint8, VER(8), VER(16)), - MK_OBSOLETE(VolumeFader, curvol, sleUint8, VER(8), VER(16)), - MK_OBSOLETE(VolumeFader, speed_lo_max, sleUint16, VER(8), VER(16)), - MK_OBSOLETE(VolumeFader, num_steps, sleUint16, VER(8), VER(16)), - MK_OBSOLETE(VolumeFader, speed_hi, sleInt8, VER(8), VER(16)), - MK_OBSOLETE(VolumeFader, direction, sleInt8, VER(8), VER(16)), - MK_OBSOLETE(VolumeFader, speed_lo, sleInt8, VER(8), VER(16)), - MK_OBSOLETE(VolumeFader, speed_lo_counter, sleUint16, VER(8), VER(16)), - MKEND() - }; +static void syncWithSerializer(Common::Serializer &s, ImTrigger &it) { + s.syncAsSint16LE(it.sound, VER(54)); + s.syncAsByte(it.id, VER(54)); + s.syncAsUint16LE(it.expire, VER(54)); + s.syncArray(it.command, 8, Common::Serializer::Uint16LE, VER(54)); +} - const SaveLoadEntry snmTriggerEntries[] = { - MKLINE(ImTrigger, sound, sleInt16, VER(54)), - MKLINE(ImTrigger, id, sleByte, VER(54)), - MKLINE(ImTrigger, expire, sleUint16, VER(54)), - MKARRAY(ImTrigger, command[0], sleUint16, 8, VER(54)), - MKEND() - }; +void IMuseInternal::saveLoadWithSerializer(Common::Serializer &s, ScummEngine *scumm, bool fixAfterLoad) { + Common::StackLock lock(_mutex, "IMuseInternal::saveLoadWithSerializer()"); int i; - ser->saveLoadEntries(this, mainEntries); - ser->saveLoadArrayOf(_cmd_queue, ARRAYSIZE(_cmd_queue), sizeof(_cmd_queue[0]), cmdQueueEntries); - ser->saveLoadArrayOf(_snm_triggers, ARRAYSIZE(_snm_triggers), sizeof(_snm_triggers[0]), snmTriggerEntries); + s.syncAsByte(_queue_end, VER(8)); + s.syncAsByte(_queue_pos, VER(8)); + s.syncAsUint16LE(_queue_sound, VER(8)); + s.syncAsByte(_queue_adding, VER(8)); + s.syncAsByte(_queue_marker, VER(8)); + s.syncAsByte(_queue_cleared, VER(8)); + s.syncAsByte(_master_volume, VER(8)); + s.syncAsUint16LE(_trigger_count, VER(8)); + s.syncAsUint16LE(_snm_trigger_index, VER(54)); + s.syncArray(_channel_volume, 8, Common::Serializer::Uint16LE, VER(8)); + s.syncArray(_volchan_table, 8, Common::Serializer::Uint16LE, VER(8)); + s.syncArray(_cmd_queue, ARRAYSIZE(_cmd_queue), syncWithSerializer); + s.syncArray(_snm_triggers, ARRAYSIZE(_snm_triggers), syncWithSerializer); // The players for (i = 0; i < ARRAYSIZE(_players); ++i) - _players[i].saveLoadWithSerializer(ser); + _players[i].saveLoadWithSerializer(s); // The parts for (i = 0; i < ARRAYSIZE(_parts); ++i) - _parts[i].saveLoadWithSerializer(ser); + _parts[i].saveLoadWithSerializer(s); { // Load/save the instrument definitions, which were revamped with V11. Part *part = &_parts[0]; - if (ser->getVersion() >= VER(11)) { + if (s.getVersion() >= VER(11)) { for (i = ARRAYSIZE(_parts); i; --i, ++part) { - part->_instrument.saveOrLoad(ser); + part->_instrument.saveLoadWithSerializer(s); } } else { for (i = ARRAYSIZE(_parts); i; --i, ++part) @@ -434,10 +414,7 @@ int IMuseInternal::save_or_load(Serializer *ser, ScummEngine *scumm, bool fixAft } // VolumeFader has been replaced with the more generic ParameterFader. - // FIXME: replace this loop by something like - // if (loading && version <= 16) ser->skip(XXX bytes); - for (i = 0; i < 8; ++i) - ser->saveLoadEntries(0, volumeFaderEntries); + s.skip(13 * 8, VER(8), VER(16)); // Normally, we have to fix up the data structures after loading a // saved game. But there are cases where we don't. For instance, The @@ -448,7 +425,7 @@ int IMuseInternal::save_or_load(Serializer *ser, ScummEngine *scumm, bool fixAft // dummy iMUSE object, but since the resource is no longer recognizable // to iMUSE, the fixup fails hard. So yes, this is a bit of a hack. - if (ser->isLoading() && fixAfterLoad) { + if (s.isLoading() && fixAfterLoad) { // Load all sounds that we need fix_players_after_load(scumm); fix_parts_after_load(); @@ -459,8 +436,6 @@ int IMuseInternal::save_or_load(Serializer *ser, ScummEngine *scumm, bool fixAft if (_midi_adlib) reallocateMidiChannels(_midi_adlib); } - - return 0; } bool IMuseInternal::get_sound_active(int sound) const { diff --git a/engines/scumm/imuse/imuse.h b/engines/scumm/imuse/imuse.h index 35ccc931b5..513d27e8e9 100644 --- a/engines/scumm/imuse/imuse.h +++ b/engines/scumm/imuse/imuse.h @@ -24,6 +24,7 @@ #define SCUMM_IMUSE_H #include "common/scummsys.h" +#include "common/serializer.h" #include "common/mutex.h" #include "scumm/music.h" @@ -35,7 +36,6 @@ namespace Scumm { class IMuseInternal; class Player; class ScummEngine; -class Serializer; typedef void (*sysexfunc)(Player *, const byte *, uint16); @@ -62,7 +62,7 @@ public: public: virtual void on_timer(MidiDriver *midi) = 0; virtual void pause(bool paused) = 0; - virtual int save_or_load(Serializer *ser, ScummEngine *scumm, bool fixAfterLoad = true) = 0; + virtual void saveLoadWithSerializer(Common::Serializer &ser, ScummEngine *scumm, bool fixAfterLoad = true) = 0; virtual bool get_sound_active(int sound) const = 0; virtual int32 doCommand(int numargs, int args[]) = 0; virtual int clear_queue() = 0; diff --git a/engines/scumm/imuse/imuse_internal.h b/engines/scumm/imuse/imuse_internal.h index fed716e300..7b1d2f65fa 100644 --- a/engines/scumm/imuse/imuse_internal.h +++ b/engines/scumm/imuse/imuse_internal.h @@ -24,6 +24,7 @@ #define SCUMM_IMUSE_INTERNAL #include "common/scummsys.h" +#include "common/serializer.h" #include "scumm/imuse/imuse.h" #include "scumm/imuse/instrument.h" #include "scumm/saveload.h" @@ -153,7 +154,7 @@ struct CommandQueue { // ////////////////////////////////////////////////// -class Player : public MidiDriver_BASE { +class Player : public MidiDriver_BASE, public Common::Serializable { /* * External SysEx handler functions shall each be defined in * a separate file. This header file shall be included at the @@ -267,7 +268,7 @@ public: void onTimer(); void removePart(Part *part); int scan(uint totrack, uint tobeat, uint totick); - void saveLoadWithSerializer(Serializer *ser); + void saveLoadWithSerializer(Common::Serializer &ser); int setHook(byte cls, byte value, byte chan) { return _hook.set(cls, value, chan); } void setDetune(int detune); void setOffsetNote(int offset); @@ -295,7 +296,7 @@ public: // ////////////////////////////////////////////////// -struct Part : public Serializable { +struct Part : public Common::Serializable { IMuseInternal *_se; int _slot; Part *_next, *_prev; @@ -360,7 +361,7 @@ struct Part : public Serializable { Part(); - void saveLoadWithSerializer(Serializer *ser); + void saveLoadWithSerializer(Common::Serializer &ser); private: void sendPitchBend(); @@ -518,7 +519,7 @@ protected: public: // IMuse interface void pause(bool paused); - int save_or_load(Serializer *ser, ScummEngine *scumm, bool fixAfterLoad = true); + void saveLoadWithSerializer(Common::Serializer &ser, ScummEngine *scumm, bool fixAfterLoad = true); bool get_sound_active(int sound) const; int32 doCommand(int numargs, int args[]); uint32 property(int prop, uint32 value); diff --git a/engines/scumm/imuse/imuse_part.cpp b/engines/scumm/imuse/imuse_part.cpp index 937523d275..ca0eaa4630 100644 --- a/engines/scumm/imuse/imuse_part.cpp +++ b/engines/scumm/imuse/imuse_part.cpp @@ -66,48 +66,44 @@ Part::Part() { _unassigned_instrument = false; } -void Part::saveLoadWithSerializer(Serializer *ser) { - const SaveLoadEntry partEntries[] = { - MKLINE(Part, _pitchbend, sleInt16, VER(8)), - MKLINE(Part, _pitchbend_factor, sleUint8, VER(8)), - MKLINE(Part, _transpose, sleInt8, VER(8)), - MKLINE(Part, _vol, sleUint8, VER(8)), - MKLINE(Part, _detune, sleInt8, VER(8)), - MKLINE(Part, _pan, sleInt8, VER(8)), - MKLINE(Part, _on, sleUint8, VER(8)), - MKLINE(Part, _modwheel, sleUint8, VER(8)), - MKLINE(Part, _pedal, sleUint8, VER(8)), - MK_OBSOLETE(Part, _program, sleUint8, VER(8), VER(16)), - MKLINE(Part, _pri, sleUint8, VER(8)), - MKLINE(Part, _chan, sleUint8, VER(8)), - MKLINE(Part, _effect_level, sleUint8, VER(8)), - MKLINE(Part, _chorus, sleUint8, VER(8)), - MKLINE(Part, _percussion, sleUint8, VER(8)), - MKLINE(Part, _bank, sleUint8, VER(8)), - MKEND() - }; - +void Part::saveLoadWithSerializer(Common::Serializer &ser) { int num; - if (ser->isSaving()) { + if (ser.isSaving()) { num = (_next ? (_next - _se->_parts + 1) : 0); - ser->saveUint16(num); + ser.syncAsUint16LE(num); num = (_prev ? (_prev - _se->_parts + 1) : 0); - ser->saveUint16(num); + ser.syncAsUint16LE(num); num = (_player ? (_player - _se->_players + 1) : 0); - ser->saveUint16(num); + ser.syncAsUint16LE(num); } else { - num = ser->loadUint16(); + ser.syncAsUint16LE(num); _next = (num ? &_se->_parts[num - 1] : 0); - num = ser->loadUint16(); + ser.syncAsUint16LE(num); _prev = (num ? &_se->_parts[num - 1] : 0); - num = ser->loadUint16(); + ser.syncAsUint16LE(num); _player = (num ? &_se->_players[num - 1] : 0); } - ser->saveLoadEntries(this, partEntries); + + ser.syncAsSint16LE(_pitchbend, VER(8)); + ser.syncAsByte(_pitchbend_factor, VER(8)); + ser.syncAsSByte(_transpose, VER(8)); + ser.syncAsByte(_vol, VER(8)); + ser.syncAsSByte(_detune, VER(8)); + ser.syncAsSByte(_pan, VER(8)); + ser.syncAsByte(_on, VER(8)); + ser.syncAsByte(_modwheel, VER(8)); + ser.syncAsByte(_pedal, VER(8)); + ser.skip(1, VER(8), VER(16)); // _program + ser.syncAsByte(_pri, VER(8)); + ser.syncAsByte(_chan, VER(8)); + ser.syncAsByte(_effect_level, VER(8)); + ser.syncAsByte(_chorus, VER(8)); + ser.syncAsByte(_percussion, VER(8)); + ser.syncAsByte(_bank, VER(8)); } void Part::set_detune(int8 detune) { diff --git a/engines/scumm/imuse/imuse_player.cpp b/engines/scumm/imuse/imuse_player.cpp index 33b38eec72..a4b79f75d3 100644 --- a/engines/scumm/imuse/imuse_player.cpp +++ b/engines/scumm/imuse/imuse_player.cpp @@ -1033,70 +1033,63 @@ void Player::metaEvent(byte type, byte *msg, uint16 len) { // //////////////////////////////////////// -void Player::saveLoadWithSerializer(Serializer *ser) { - static const SaveLoadEntry playerEntries[] = { - MKLINE(Player, _active, sleByte, VER(8)), - MKLINE(Player, _id, sleUint16, VER(8)), - MKLINE(Player, _priority, sleByte, VER(8)), - MKLINE(Player, _volume, sleByte, VER(8)), - MKLINE(Player, _pan, sleInt8, VER(8)), - MKLINE(Player, _transpose, sleByte, VER(8)), - MKLINE(Player, _detune, sleInt8, VER(8)), - MKLINE(Player, _vol_chan, sleUint16, VER(8)), - MKLINE(Player, _vol_eff, sleByte, VER(8)), - MKLINE(Player, _speed, sleByte, VER(8)), - MK_OBSOLETE(Player, _song_index, sleUint16, VER(8), VER(19)), - MKLINE(Player, _track_index, sleUint16, VER(8)), - MK_OBSOLETE(Player, _timer_counter, sleUint16, VER(8), VER(17)), - MKLINE(Player, _loop_to_beat, sleUint16, VER(8)), - MKLINE(Player, _loop_from_beat, sleUint16, VER(8)), - MKLINE(Player, _loop_counter, sleUint16, VER(8)), - MKLINE(Player, _loop_to_tick, sleUint16, VER(8)), - MKLINE(Player, _loop_from_tick, sleUint16, VER(8)), - MK_OBSOLETE(Player, _tempo, sleUint32, VER(8), VER(19)), - MK_OBSOLETE(Player, _cur_pos, sleUint32, VER(8), VER(17)), - MK_OBSOLETE(Player, _next_pos, sleUint32, VER(8), VER(17)), - MK_OBSOLETE(Player, _song_offset, sleUint32, VER(8), VER(17)), - MK_OBSOLETE(Player, _tick_index, sleUint16, VER(8), VER(17)), - MK_OBSOLETE(Player, _beat_index, sleUint16, VER(8), VER(17)), - MK_OBSOLETE(Player, _ticks_per_beat, sleUint16, VER(8), VER(17)), - MKLINE(Player, _music_tick, sleUint32, VER(19)), - MKLINE(Player, _hook._jump[0], sleByte, VER(8)), - MKLINE(Player, _hook._transpose, sleByte, VER(8)), - MKARRAY(Player, _hook._part_onoff[0], sleByte, 16, VER(8)), - MKARRAY(Player, _hook._part_volume[0], sleByte, 16, VER(8)), - MKARRAY(Player, _hook._part_program[0], sleByte, 16, VER(8)), - MKARRAY(Player, _hook._part_transpose[0], sleByte, 16, VER(8)), - MKEND() - }; - - const SaveLoadEntry parameterFaderEntries[] = { - MKLINE(ParameterFader, param, sleInt16, VER(17)), - MKLINE(ParameterFader, start, sleInt16, VER(17)), - MKLINE(ParameterFader, end, sleInt16, VER(17)), - MKLINE(ParameterFader, total_time, sleUint32, VER(17)), - MKLINE(ParameterFader, current_time, sleUint32, VER(17)), - MKEND() - }; - - if (!ser->isSaving() && _parser) { +static void syncWithSerializer(Common::Serializer &s, ParameterFader &pf) { + s.syncAsSint16LE(pf.param, VER(17)); + s.syncAsSint16LE(pf.start, VER(17)); + s.syncAsSint16LE(pf.end, VER(17)); + s.syncAsUint32LE(pf.total_time, VER(17)); + s.syncAsUint32LE(pf.current_time, VER(17)); +} + +void Player::saveLoadWithSerializer(Common::Serializer &s) { + if (!s.isSaving() && _parser) { delete _parser; _parser = 0; } _music_tick = _parser ? _parser->getTick() : 0; int num; - if (ser->isSaving()) { + if (s.isSaving()) { num = (_parts ? (_parts - _se->_parts + 1) : 0); - ser->saveUint16(num); + s.syncAsUint16LE(num); } else { - num = ser->loadUint16(); + s.syncAsUint16LE(num); _parts = (num ? &_se->_parts[num - 1] : 0); } - ser->saveLoadEntries(this, playerEntries); - ser->saveLoadArrayOf(_parameterFaders, ARRAYSIZE(_parameterFaders), - sizeof(ParameterFader), parameterFaderEntries); - return; + + s.syncAsByte(_active, VER(8)); + s.syncAsUint16LE(_id, VER(8)); + s.syncAsByte(_priority, VER(8)); + s.syncAsByte(_volume, VER(8)); + s.syncAsSByte(_pan, VER(8)); + s.syncAsByte(_transpose, VER(8)); + s.syncAsSByte(_detune, VER(8)); + s.syncAsUint16LE(_vol_chan, VER(8)); + s.syncAsByte(_vol_eff, VER(8)); + s.syncAsByte(_speed, VER(8)); + s.skip(2, VER(8), VER(19)); // _song_index + s.syncAsUint16LE(_track_index, VER(8)); + s.skip(2, VER(8), VER(17)); // _timer_counter + s.syncAsUint16LE(_loop_to_beat, VER(8)); + s.syncAsUint16LE(_loop_from_beat, VER(8)); + s.syncAsUint16LE(_loop_counter, VER(8)); + s.syncAsUint16LE(_loop_to_tick, VER(8)); + s.syncAsUint16LE(_loop_from_tick, VER(8)); + s.skip(4, VER(8), VER(19)); // _tempo + s.skip(4, VER(8), VER(17)); // _cur_pos + s.skip(4, VER(8), VER(17)); // _next_pos + s.skip(4, VER(8), VER(17)); // _song_offset + s.skip(2, VER(8), VER(17)); // _tick_index + s.skip(2, VER(8), VER(17)); // _beat_index + s.skip(2, VER(8), VER(17)); // _ticks_per_beat + s.syncAsUint32LE(_music_tick, VER(19)); + s.syncAsByte(_hook._jump[0], VER(8)); + s.syncAsByte(_hook._transpose, VER(8)); + s.syncBytes(_hook._part_onoff, 16, VER(8)); + s.syncBytes(_hook._part_volume, 16, VER(8)); + s.syncBytes(_hook._part_program, 16, VER(8)); + s.syncBytes(_hook._part_transpose, 16, VER(8)); + s.syncArray(_parameterFaders, ARRAYSIZE(_parameterFaders), syncWithSerializer); } } // End of namespace Scumm diff --git a/engines/scumm/imuse/instrument.cpp b/engines/scumm/imuse/instrument.cpp index 670b3647eb..708a98046b 100644 --- a/engines/scumm/imuse/instrument.cpp +++ b/engines/scumm/imuse/instrument.cpp @@ -20,7 +20,6 @@ * */ - #include "scumm/scumm.h" #include "scumm/saveload.h" #include "scumm/imuse/instrument.h" @@ -132,8 +131,8 @@ private: public: Instrument_Program(byte program, bool mt32); - Instrument_Program(Serializer *s); - void saveOrLoad(Serializer *s); + Instrument_Program(Common::Serializer &s); + void saveLoadWithSerializer(Common::Serializer &s); void send(MidiChannel *mc); void copy_to(Instrument *dest) { dest->program(_program, _mt32); } bool is_valid() { @@ -178,8 +177,8 @@ private: public: Instrument_AdLib(const byte *data); - Instrument_AdLib(Serializer *s); - void saveOrLoad(Serializer *s); + Instrument_AdLib(Common::Serializer &s); + void saveLoadWithSerializer(Common::Serializer &s); void send(MidiChannel *mc); void copy_to(Instrument *dest) { dest->adlib((byte *)&_instrument); } bool is_valid() { return true; } @@ -259,8 +258,8 @@ private: public: Instrument_Roland(const byte *data); - Instrument_Roland(Serializer *s); - void saveOrLoad(Serializer *s); + Instrument_Roland(Common::Serializer &s); + void saveLoadWithSerializer(Common::Serializer &s); void send(MidiChannel *mc); void copy_to(Instrument *dest) { dest->roland((byte *)&_instrument); } bool is_valid() { return (_native_mt32 ? true : (_instrument_name[0] != '\0')); } @@ -269,8 +268,8 @@ public: class Instrument_PcSpk : public InstrumentInternal { public: Instrument_PcSpk(const byte *data); - Instrument_PcSpk(Serializer *s); - void saveOrLoad(Serializer *s); + Instrument_PcSpk(Common::Serializer &s); + void saveLoadWithSerializer(Common::Serializer &s); void send(MidiChannel *mc); void copy_to(Instrument *dest) { dest->pcspk((byte *)&_instrument); } bool is_valid() { return true; } @@ -285,8 +284,8 @@ private: public: Instrument_MacSfx(byte program); - Instrument_MacSfx(Serializer *s); - void saveOrLoad(Serializer *s); + Instrument_MacSfx(Common::Serializer &s); + void saveLoadWithSerializer(Common::Serializer &s); void send(MidiChannel *mc); void copy_to(Instrument *dest) { dest->macSfx(_program); } bool is_valid() { @@ -350,14 +349,14 @@ void Instrument::macSfx(byte prog) { _instrument = new Instrument_MacSfx(prog); } -void Instrument::saveOrLoad(Serializer *s) { - if (s->isSaving()) { - s->saveByte(_type); +void Instrument::saveLoadWithSerializer(Common::Serializer &s) { + if (s.isSaving()) { + s.syncAsByte(_type); if (_instrument) - _instrument->saveOrLoad(s); + _instrument->saveLoadWithSerializer(s); } else { clear(); - _type = s->loadByte(); + s.syncAsByte(_type); switch (_type) { case itNone: break; @@ -396,20 +395,21 @@ Instrument_Program::Instrument_Program(byte program, bool mt32) : _program = 255; } -Instrument_Program::Instrument_Program(Serializer *s) { +Instrument_Program::Instrument_Program(Common::Serializer &s) { _program = 255; _mt32 = false; - if (!s->isSaving()) - saveOrLoad(s); + if (!s.isSaving()) + saveLoadWithSerializer(s); } -void Instrument_Program::saveOrLoad(Serializer *s) { - if (s->isSaving()) { - s->saveByte(_program); - s->saveByte(_mt32 ? 1 : 0); +void Instrument_Program::saveLoadWithSerializer(Common::Serializer &s) { + s.syncAsByte(_program); + if (s.isSaving()) { + s.syncAsByte(_mt32); } else { - _program = s->loadByte(); - _mt32 = (s->loadByte() > 0); + byte tmp; + s.syncAsByte(tmp); + _mt32 = (tmp > 0); } } @@ -434,18 +434,15 @@ Instrument_AdLib::Instrument_AdLib(const byte *data) { memcpy(&_instrument, data, sizeof(_instrument)); } -Instrument_AdLib::Instrument_AdLib(Serializer *s) { - if (!s->isSaving()) - saveOrLoad(s); +Instrument_AdLib::Instrument_AdLib(Common::Serializer &s) { + if (!s.isSaving()) + saveLoadWithSerializer(s); else memset(&_instrument, 0, sizeof(_instrument)); } -void Instrument_AdLib::saveOrLoad(Serializer *s) { - if (s->isSaving()) - s->saveBytes(&_instrument, sizeof(_instrument)); - else - s->loadBytes(&_instrument, sizeof(_instrument)); +void Instrument_AdLib::saveLoadWithSerializer(Common::Serializer &s) { + s.syncBytes((byte *)(&_instrument), sizeof(_instrument)); } void Instrument_AdLib::send(MidiChannel *mc) { @@ -468,26 +465,24 @@ Instrument_Roland::Instrument_Roland(const byte *data) { } } -Instrument_Roland::Instrument_Roland(Serializer *s) { +Instrument_Roland::Instrument_Roland(Common::Serializer &s) { _instrument_name[0] = '\0'; - if (!s->isSaving()) - saveOrLoad(s); + if (!s.isSaving()) + saveLoadWithSerializer(s); else memset(&_instrument, 0, sizeof(_instrument)); } -void Instrument_Roland::saveOrLoad(Serializer *s) { - if (s->isSaving()) { - s->saveBytes(&_instrument, sizeof(_instrument)); - } else { - s->loadBytes(&_instrument, sizeof(_instrument)); +void Instrument_Roland::saveLoadWithSerializer(Common::Serializer &s) { + s.syncBytes((byte *)(&_instrument), sizeof(_instrument)); + if (!s.isSaving()) { memcpy(&_instrument_name, &_instrument.common.name, sizeof(_instrument.common.name)); _instrument_name[10] = '\0'; if (!_native_mt32 && getEquivalentGM() >= 128) { debug(2, "MT-32 custom instrument \"%s\" not supported", _instrument_name); _instrument_name[0] = '\0'; } - } // end if + } } void Instrument_Roland::send(MidiChannel *mc) { @@ -538,18 +533,15 @@ Instrument_PcSpk::Instrument_PcSpk(const byte *data) { memcpy(_instrument, data, sizeof(_instrument)); } -Instrument_PcSpk::Instrument_PcSpk(Serializer *s) { - if (!s->isSaving()) - saveOrLoad(s); +Instrument_PcSpk::Instrument_PcSpk(Common::Serializer &s) { + if (!s.isSaving()) + saveLoadWithSerializer(s); else memset(_instrument, 0, sizeof(_instrument)); } -void Instrument_PcSpk::saveOrLoad(Serializer *s) { - if (s->isSaving()) - s->saveBytes(_instrument, sizeof(_instrument)); - else - s->loadBytes(_instrument, sizeof(_instrument)); +void Instrument_PcSpk::saveLoadWithSerializer(Common::Serializer &s) { + s.syncBytes(_instrument, sizeof(_instrument)); } void Instrument_PcSpk::send(MidiChannel *mc) { @@ -569,19 +561,15 @@ Instrument_MacSfx::Instrument_MacSfx(byte program) : } } -Instrument_MacSfx::Instrument_MacSfx(Serializer *s) { +Instrument_MacSfx::Instrument_MacSfx(Common::Serializer &s) { _program = 255; - if (!s->isSaving()) { - saveOrLoad(s); + if (!s.isSaving()) { + saveLoadWithSerializer(s); } } -void Instrument_MacSfx::saveOrLoad(Serializer *s) { - if (s->isSaving()) { - s->saveByte(_program); - } else { - _program = s->loadByte(); - } +void Instrument_MacSfx::saveLoadWithSerializer(Common::Serializer &s) { + s.syncAsByte(_program); } void Instrument_MacSfx::send(MidiChannel *mc) { diff --git a/engines/scumm/imuse/instrument.h b/engines/scumm/imuse/instrument.h index 47f556b40b..374b6352f1 100644 --- a/engines/scumm/imuse/instrument.h +++ b/engines/scumm/imuse/instrument.h @@ -25,24 +25,23 @@ #include "common/scummsys.h" +#include "common/serializer.h" class MidiChannel; namespace Scumm { -class Serializer; class Instrument; -class InstrumentInternal { +class InstrumentInternal : public Common::Serializable { public: virtual ~InstrumentInternal() {} - virtual void saveOrLoad(Serializer *s) = 0; virtual void send(MidiChannel *mc) = 0; virtual void copy_to(Instrument *dest) = 0; virtual bool is_valid() = 0; }; -class Instrument { +class Instrument : public Common::Serializable { private: byte _type; InstrumentInternal *_instrument; @@ -78,7 +77,7 @@ public: byte getType() { return _type; } bool isValid() { return (_instrument ? _instrument->is_valid() : false); } - void saveOrLoad(Serializer *s); + void saveLoadWithSerializer(Common::Serializer &s); void send(MidiChannel *mc) { if (_instrument) _instrument->send(mc); diff --git a/engines/scumm/imuse_digi/dimuse.cpp b/engines/scumm/imuse_digi/dimuse.cpp index 3f61946bf2..9dac8b7662 100644 --- a/engines/scumm/imuse_digi/dimuse.cpp +++ b/engines/scumm/imuse_digi/dimuse.cpp @@ -103,61 +103,55 @@ void IMuseDigital::resetState() { _triggerUsed = false; } -void IMuseDigital::saveOrLoad(Serializer *ser) { - Common::StackLock lock(_mutex, "IMuseDigital::saveOrLoad()"); - - const SaveLoadEntry mainEntries[] = { - MK_OBSOLETE(IMuseDigital, _volVoice, sleInt32, VER(31), VER(42)), - MK_OBSOLETE(IMuseDigital, _volSfx, sleInt32, VER(31), VER(42)), - MK_OBSOLETE(IMuseDigital, _volMusic, sleInt32, VER(31), VER(42)), - MKLINE(IMuseDigital, _curMusicState, sleInt32, VER(31)), - MKLINE(IMuseDigital, _curMusicSeq, sleInt32, VER(31)), - MKLINE(IMuseDigital, _curMusicCue, sleInt32, VER(31)), - MKLINE(IMuseDigital, _nextSeqToPlay, sleInt32, VER(31)), - MKLINE(IMuseDigital, _radioChatterSFX, sleByte, VER(76)), - MKARRAY(IMuseDigital, _attributes[0], sleInt32, 188, VER(31)), - MKEND() - }; - - const SaveLoadEntry trackEntries[] = { - MKLINE(Track, pan, sleInt8, VER(31)), - MKLINE(Track, vol, sleInt32, VER(31)), - MKLINE(Track, volFadeDest, sleInt32, VER(31)), - MKLINE(Track, volFadeStep, sleInt32, VER(31)), - MKLINE(Track, volFadeDelay, sleInt32, VER(31)), - MKLINE(Track, volFadeUsed, sleByte, VER(31)), - MKLINE(Track, soundId, sleInt32, VER(31)), - MKARRAY(Track, soundName[0], sleByte, 15, VER(31)), - MKLINE(Track, used, sleByte, VER(31)), - MKLINE(Track, toBeRemoved, sleByte, VER(31)), - MKLINE(Track, souStreamUsed, sleByte, VER(31)), - MK_OBSOLETE(Track, mixerStreamRunning, sleByte, VER(31), VER(76)), - MKLINE(Track, soundPriority, sleInt32, VER(31)), - MKLINE(Track, regionOffset, sleInt32, VER(31)), - MK_OBSOLETE(Track, trackOffset, sleInt32, VER(31), VER(31)), - MKLINE(Track, dataOffset, sleInt32, VER(31)), - MKLINE(Track, curRegion, sleInt32, VER(31)), - MKLINE(Track, curHookId, sleInt32, VER(31)), - MKLINE(Track, volGroupId, sleInt32, VER(31)), - MKLINE(Track, soundType, sleInt32, VER(31)), - MKLINE(Track, feedSize, sleInt32, VER(31)), - MKLINE(Track, dataMod12Bit, sleInt32, VER(31)), - MKLINE(Track, mixerFlags, sleInt32, VER(31)), - MK_OBSOLETE(Track, mixerVol, sleInt32, VER(31), VER(42)), - MK_OBSOLETE(Track, mixerPan, sleInt32, VER(31), VER(42)), - MKLINE(Track, sndDataExtComp, sleByte, VER(45)), - MKEND() - }; - - ser->saveLoadEntries(this, mainEntries); +static void syncWithSerializer(Common::Serializer &s, Track &t) { + s.syncAsSByte(t.pan, VER(31)); + s.syncAsSint32LE(t.vol, VER(31)); + s.syncAsSint32LE(t.volFadeDest, VER(31)); + s.syncAsSint32LE(t.volFadeStep, VER(31)); + s.syncAsSint32LE(t.volFadeDelay, VER(31)); + s.syncAsByte(t.volFadeUsed, VER(31)); + s.syncAsSint32LE(t.soundId, VER(31)); + s.syncArray(t.soundName, 15, Common::Serializer::SByte, VER(31)); + s.syncAsByte(t.used, VER(31)); + s.syncAsByte(t.toBeRemoved, VER(31)); + s.syncAsByte(t.souStreamUsed, VER(31)); + s.skip(1, VER(31), VER(76)); // mixerStreamRunning + s.syncAsSint32LE(t.soundPriority, VER(31)); + s.syncAsSint32LE(t.regionOffset, VER(31)); + s.skip(4, VER(31), VER(31)); // trackOffset + s.syncAsSint32LE(t.dataOffset, VER(31)); + s.syncAsSint32LE(t.curRegion, VER(31)); + s.syncAsSint32LE(t.curHookId, VER(31)); + s.syncAsSint32LE(t.volGroupId, VER(31)); + s.syncAsSint32LE(t.soundType, VER(31)); + s.syncAsSint32LE(t.feedSize, VER(31)); + s.syncAsSint32LE(t.dataMod12Bit, VER(31)); + s.syncAsSint32LE(t.mixerFlags, VER(31)); + s.skip(4, VER(31), VER(42)); // mixerVol + s.skip(4, VER(31), VER(42)); // mixerPan + s.syncAsByte(t.sndDataExtComp, VER(45)); +} + +void IMuseDigital::saveLoadEarly(Common::Serializer &s) { + Common::StackLock lock(_mutex, "IMuseDigital::saveLoadEarly()"); + + s.skip(4, VER(31), VER(42)); // _volVoice + s.skip(4, VER(31), VER(42)); // _volSfx + s.skip(4, VER(31), VER(42)); // _volMusic + s.syncAsSint32LE(_curMusicState, VER(31)); + s.syncAsSint32LE(_curMusicSeq, VER(31)); + s.syncAsSint32LE(_curMusicCue, VER(31)); + s.syncAsSint32LE(_nextSeqToPlay, VER(31)); + s.syncAsByte(_radioChatterSFX, VER(76)); + s.syncArray(_attributes, 188, Common::Serializer::Sint32LE, VER(31)); for (int l = 0; l < MAX_DIGITAL_TRACKS + MAX_DIGITAL_FADETRACKS; l++) { Track *track = _track[l]; - if (ser->isLoading()) { + if (s.isLoading()) { memset(track, 0, sizeof(Track)); } - ser->saveLoadEntries(track, trackEntries); - if (ser->isLoading()) { + syncWithSerializer(s, *track); + if (s.isLoading()) { _track[l]->trackId = l; if (!track->used) continue; diff --git a/engines/scumm/imuse_digi/dimuse.h b/engines/scumm/imuse_digi/dimuse.h index 02f899df85..86c8d21bcc 100644 --- a/engines/scumm/imuse_digi/dimuse.h +++ b/engines/scumm/imuse_digi/dimuse.h @@ -25,6 +25,7 @@ #include "common/scummsys.h" #include "common/mutex.h" +#include "common/serializer.h" #include "common/textconsole.h" #include "common/util.h" @@ -48,7 +49,6 @@ enum { struct imuseDigTable; struct imuseComiTable; -class Serializer; class ScummEngine_v7; struct Track; @@ -136,7 +136,7 @@ public: void startSound(int sound) { error("IMuseDigital::startSound(int) should be never called"); } - void saveOrLoad(Serializer *ser); + void saveLoadEarly(Common::Serializer &ser); void resetState(); void setRadioChatterSFX(bool state) { _radioChatterSFX = state; diff --git a/engines/scumm/music.h b/engines/scumm/music.h index e170647560..9404ce7af3 100644 --- a/engines/scumm/music.h +++ b/engines/scumm/music.h @@ -23,12 +23,11 @@ #ifndef SCUMM_MUSIC_H #define SCUMM_MUSIC_H +#include "common/serializer.h" #include "common/scummsys.h" namespace Scumm { -class Serializer; - /** * Pure virtual base class for the various music/sound engines used in Scumm * games. In particular, the iMuse code provides a subclass of this. There are @@ -39,7 +38,7 @@ class Serializer; * * Instantiated by class Scumm. */ -class MusicEngine { +class MusicEngine : public Common::Serializable { public: virtual ~MusicEngine() {} @@ -84,7 +83,7 @@ public: /** * Save or load the music state. */ - virtual void saveLoadWithSerializer(Serializer *ser) {} + virtual void saveLoadWithSerializer(Common::Serializer &ser) {} }; } // End of namespace Scumm diff --git a/engines/scumm/players/player_ad.cpp b/engines/scumm/players/player_ad.cpp index 55bbeeef98..2de8ac96e4 100644 --- a/engines/scumm/players/player_ad.cpp +++ b/engines/scumm/players/player_ad.cpp @@ -191,27 +191,27 @@ int Player_AD::getSoundStatus(int sound) const { return false; } -void Player_AD::saveLoadWithSerializer(Serializer *ser) { +void Player_AD::saveLoadWithSerializer(Common::Serializer &s) { Common::StackLock lock(_mutex); - if (ser->getVersion() < VER(95)) { + if (s.getVersion() < VER(95)) { IMuse *dummyImuse = IMuse::create(_vm->_system, NULL, NULL); - dummyImuse->save_or_load(ser, _vm, false); + dummyImuse->saveLoadWithSerializer(s, _vm, false); delete dummyImuse; return; } - if (ser->getVersion() >= VER(96)) { + if (s.getVersion() >= VER(96)) { int32 res[4] = { _musicResource, _sfx[0].resource, _sfx[1].resource, _sfx[2].resource }; // The first thing we save is a list of sound resources being played // at the moment. - ser->saveLoadArrayOf(res, 4, sizeof(res[0]), sleInt32); + s.syncArray(res, 4, Common::Serializer::Sint32LE); // If we are loading start the music again at this point. - if (ser->isLoading()) { + if (s.isLoading()) { if (res[0] != -1) { startSound(res[0]); } @@ -219,26 +219,21 @@ void Player_AD::saveLoadWithSerializer(Serializer *ser) { uint32 musicOffset = _curOffset; - static const SaveLoadEntry musicData[] = { - MKLINE(Player_AD, _engineMusicTimer, sleInt32, VER(96)), - MKLINE(Player_AD, _musicTimer, sleUint32, VER(96)), - MKLINE(Player_AD, _internalMusicTimer, sleUint32, VER(96)), - MKLINE(Player_AD, _curOffset, sleUint32, VER(96)), - MKLINE(Player_AD, _nextEventTimer, sleUint32, VER(96)), - MKEND() - }; - - ser->saveLoadEntries(this, musicData); + s.syncAsSint32LE(_engineMusicTimer, VER(96)); + s.syncAsUint32LE(_musicTimer, VER(96)); + s.syncAsUint32LE(_internalMusicTimer, VER(96)); + s.syncAsUint32LE(_curOffset, VER(96)); + s.syncAsUint32LE(_nextEventTimer, VER(96)); // We seek back to the old music position. - if (ser->isLoading()) { + if (s.isLoading()) { SWAP(musicOffset, _curOffset); musicSeekTo(musicOffset); } // Finally start up the SFX. This makes sure that they are not // accidently stopped while seeking to the old music position. - if (ser->isLoading()) { + if (s.isLoading()) { for (int i = 1; i < ARRAYSIZE(res); ++i) { if (res[i] != -1) { startSound(res[i]); diff --git a/engines/scumm/players/player_ad.h b/engines/scumm/players/player_ad.h index 1e665e82d5..20c8b3d475 100644 --- a/engines/scumm/players/player_ad.h +++ b/engines/scumm/players/player_ad.h @@ -26,6 +26,7 @@ #include "scumm/music.h" #include "common/mutex.h" +#include "common/serializer.h" namespace OPL { class OPL; @@ -34,7 +35,6 @@ class OPL; namespace Scumm { class ScummEngine; -class Serializer; /** * Sound output for v3/v4 AdLib data. @@ -52,7 +52,7 @@ public: virtual int getMusicTimer(); virtual int getSoundStatus(int sound) const; - virtual void saveLoadWithSerializer(Serializer *ser); + virtual void saveLoadWithSerializer(Common::Serializer &ser); // Timer callback void onTimer(); diff --git a/engines/scumm/players/player_mac.cpp b/engines/scumm/players/player_mac.cpp index 87406f4e34..cc65adceab 100644 --- a/engines/scumm/players/player_mac.cpp +++ b/engines/scumm/players/player_mac.cpp @@ -97,53 +97,46 @@ Player_Mac::~Player_Mac() { delete[] _channel; } -void Player_Mac::saveLoadWithSerializer(Serializer *ser) { +void syncWithSerializer(Common::Serializer &s, Player_Mac::Channel &c) { + s.syncAsUint16LE(c._pos, VER(94)); + s.syncAsSint32LE(c._pitchModifier, VER(94)); + s.syncAsByte(c._velocity, VER(94)); + s.syncAsUint32LE(c._remaining, VER(94)); + s.syncAsByte(c._notesLeft, VER(94)); +} + +void syncWithSerializer(Common::Serializer &s, Player_Mac::Instrument &i) { + s.syncAsUint32LE(i._pos, VER(94)); + s.syncAsUint32LE(i._subPos, VER(94)); +} + +void Player_Mac::saveLoadWithSerializer(Common::Serializer &s) { Common::StackLock lock(_mutex); - if (ser->getVersion() < VER(94)) { - if (_vm->_game.id == GID_MONKEY && ser->isLoading()) { + if (s.getVersion() < VER(94)) { + if (_vm->_game.id == GID_MONKEY && s.isLoading()) { IMuse *dummyImuse = IMuse::create(_vm->_system, NULL, NULL); - dummyImuse->save_or_load(ser, _vm, false); + dummyImuse->saveLoadWithSerializer(s, _vm, false); delete dummyImuse; } } else { - static const SaveLoadEntry musicEntries[] = { - MKLINE(Player_Mac, _sampleRate, sleUint32, VER(94)), - MKLINE(Player_Mac, _soundPlaying, sleInt16, VER(94)), - MKEND() - }; - - static const SaveLoadEntry channelEntries[] = { - MKLINE(Channel, _pos, sleUint16, VER(94)), - MKLINE(Channel, _pitchModifier, sleInt32, VER(94)), - MKLINE(Channel, _velocity, sleUint8, VER(94)), - MKLINE(Channel, _remaining, sleUint32, VER(94)), - MKLINE(Channel, _notesLeft, sleUint8, VER(94)), - MKEND() - }; - - static const SaveLoadEntry instrumentEntries[] = { - MKLINE(Instrument, _pos, sleUint32, VER(94)), - MKLINE(Instrument, _subPos, sleUint32, VER(94)), - MKEND() - }; - uint32 mixerSampleRate = _sampleRate; int i; - ser->saveLoadEntries(this, musicEntries); + s.syncAsUint32LE(_sampleRate, VER(94)); + s.syncAsSint16LE(_soundPlaying, VER(94)); - if (ser->isLoading() && _soundPlaying != -1) { + if (s.isLoading() && _soundPlaying != -1) { const byte *ptr = _vm->getResourceAddress(rtSound, _soundPlaying); assert(ptr); loadMusic(ptr); } - ser->saveLoadArrayOf(_channel, _numberOfChannels, sizeof(Channel), channelEntries); + s.syncArray(_channel, _numberOfChannels, syncWithSerializer); for (i = 0; i < _numberOfChannels; i++) { - ser->saveLoadEntries(&_channel[i], instrumentEntries); + syncWithSerializer(s, _channel[i]); } - if (ser->isLoading()) { + if (s.isLoading()) { // If necessary, adjust the channel data to fit the // current sample rate. if (_soundPlaying != -1 && _sampleRate != mixerSampleRate) { diff --git a/engines/scumm/players/player_mac.h b/engines/scumm/players/player_mac.h index d247ce9883..897960d775 100644 --- a/engines/scumm/players/player_mac.h +++ b/engines/scumm/players/player_mac.h @@ -63,7 +63,7 @@ public: virtual bool endOfData() const { return false; } virtual int getRate() const { return _sampleRate; } - virtual void saveLoadWithSerializer(Serializer *ser); + virtual void saveLoadWithSerializer(Common::Serializer &ser); private: Common::Mutex _mutex; @@ -92,6 +92,7 @@ private: void generateSamples(int16 *data, int pitchModifier, int volume, int numSamples, int remainingSamplesOnNote, bool fadeNoteEnds); }; + friend void syncWithSerializer(Common::Serializer &, Instrument &); int _pitchTable[128]; int _numberOfChannels; @@ -120,6 +121,7 @@ protected: bool loadInstrument(Common::SeekableReadStream *stream); }; + friend void syncWithSerializer(Common::Serializer &, Channel &); ScummEngine *const _vm; Channel *_channel; diff --git a/engines/scumm/players/player_towns.cpp b/engines/scumm/players/player_towns.cpp index d540fc4f6b..16080205c0 100644 --- a/engines/scumm/players/player_towns.cpp +++ b/engines/scumm/players/player_towns.cpp @@ -46,19 +46,18 @@ int Player_Towns::getSoundStatus(int sound) const { return 0; } -void Player_Towns::saveLoadWithSerializer(Serializer *ser) { - static const SaveLoadEntry pcmEntries[] = { - MKLINE(PcmCurrentSound, index, sleInt16, VER(81)), - MKLINE(PcmCurrentSound, chan, sleInt16, VER(81)), - MKLINE(PcmCurrentSound, note, sleUint8, VER(81)), - MKLINE(PcmCurrentSound, velo, sleUint8, VER(81)), - MKLINE(PcmCurrentSound, pan, sleUint8, VER(81)), - MKLINE(PcmCurrentSound, paused, sleUint8, VER(81)), - MKLINE(PcmCurrentSound, looping, sleUint8, VER(81)), - MKLINE(PcmCurrentSound, priority, sleUint32, VER(81)), - MKEND() - }; - +void syncWithSerializer(Common::Serializer &s, Player_Towns::PcmCurrentSound &pcs) { + s.syncAsSint16LE(pcs.index, VER(81)); + s.syncAsSint16LE(pcs.chan, VER(81)); + s.syncAsByte(pcs.note, VER(81)); + s.syncAsByte(pcs.velo, VER(81)); + s.syncAsByte(pcs.pan, VER(81)); + s.syncAsByte(pcs.paused, VER(81)); + s.syncAsByte(pcs.looping, VER(81)); + s.syncAsUint32LE(pcs.priority, VER(81)); +} + +void Player_Towns::saveLoadWithSerializer(Common::Serializer &s) { for (int i = 1; i < 9; i++) { if (!_pcmCurrentSound[i].index) continue; @@ -71,7 +70,7 @@ void Player_Towns::saveLoadWithSerializer(Serializer *ser) { _pcmCurrentSound[i].index = 0; } - ser->saveLoadArrayOf(_pcmCurrentSound, 9, sizeof(PcmCurrentSound), pcmEntries); + s.syncArray(_pcmCurrentSound, 9, syncWithSerializer); } void Player_Towns::restoreAfterLoad() { @@ -362,34 +361,24 @@ void Player_Towns_v1::setSoundNote(int sound, int note) { _soundOverride[sound].note = note; } -void Player_Towns_v1::saveLoadWithSerializer(Serializer *ser) { +void Player_Towns_v1::saveLoadWithSerializer(Common::Serializer &s) { _cdaCurrentSoundTemp = (_vm->_sound->pollCD() && _cdaNumLoops > 1) ? _cdaCurrentSound & 0xff : 0; _cdaNumLoopsTemp = _cdaNumLoops & 0xff; - static const SaveLoadEntry cdEntries[] = { - MKLINE(Player_Towns_v1, _cdaCurrentSoundTemp, sleUint8, VER(81)), - MKLINE(Player_Towns_v1, _cdaNumLoopsTemp, sleUint8, VER(81)), - MKLINE(Player_Towns_v1, _cdaVolLeft, sleUint8, VER(81)), - MKLINE(Player_Towns_v1, _cdaVolRight, sleUint8, VER(81)), - MKEND() - }; - - ser->saveLoadEntries(this, cdEntries); + s.syncAsByte(_cdaCurrentSoundTemp, VER(81)); + s.syncAsByte(_cdaNumLoopsTemp, VER(81)); + s.syncAsByte(_cdaVolLeft, VER(81)); + s.syncAsByte(_cdaVolRight, VER(81)); if (!_eupLooping && !_player->isPlaying()) _eupCurrentSound = 0; - static const SaveLoadEntry eupEntries[] = { - MKLINE(Player_Towns_v1, _eupCurrentSound, sleUint8, VER(81)), - MKLINE(Player_Towns_v1, _eupLooping, sleUint8, VER(81)), - MKLINE(Player_Towns_v1, _eupVolLeft, sleUint8, VER(81)), - MKLINE(Player_Towns_v1, _eupVolRight, sleUint8, VER(81)), - MKEND() - }; - - ser->saveLoadEntries(this, eupEntries); + s.syncAsByte(_eupCurrentSound, VER(81)); + s.syncAsByte(_eupLooping, VER(81)); + s.syncAsByte(_eupVolLeft, VER(81)); + s.syncAsByte(_eupVolRight, VER(81)); - Player_Towns::saveLoadWithSerializer(ser); + Player_Towns::saveLoadWithSerializer(s); } void Player_Towns_v1::restoreAfterLoad() { @@ -721,9 +710,9 @@ int32 Player_Towns_v2::doCommand(int numargs, int args[]) { return res; } -void Player_Towns_v2::saveLoadWithSerializer(Serializer *ser) { - if (ser->getVersion() >= 83) - Player_Towns::saveLoadWithSerializer(ser); +void Player_Towns_v2::saveLoadWithSerializer(Common::Serializer &s) { + if (s.getVersion() >= VER(83)) + Player_Towns::saveLoadWithSerializer(s); } void Player_Towns_v2::playVocTrack(const uint8 *data) { diff --git a/engines/scumm/players/player_towns.h b/engines/scumm/players/player_towns.h index 576d17e392..ad51c3e561 100644 --- a/engines/scumm/players/player_towns.h +++ b/engines/scumm/players/player_towns.h @@ -43,7 +43,7 @@ public: virtual int32 doCommand(int numargs, int args[]) = 0; - virtual void saveLoadWithSerializer(Serializer *ser); + virtual void saveLoadWithSerializer(Common::Serializer &ser); virtual void restoreAfterLoad(); // version 1 specific @@ -69,6 +69,7 @@ protected: uint8 looping; uint32 priority; } _pcmCurrentSound[9]; + friend void syncWithSerializer(Common::Serializer &, PcmCurrentSound &); uint8 _unkFlags; @@ -101,7 +102,7 @@ public: void setSoundVolume(int sound, int left, int right); void setSoundNote(int sound, int note); - void saveLoadWithSerializer(Serializer *ser); + void saveLoadWithSerializer(Common::Serializer &ser); void restoreAfterLoad(); private: @@ -154,7 +155,7 @@ public: int32 doCommand(int numargs, int args[]); - void saveLoadWithSerializer(Serializer *ser); + void saveLoadWithSerializer(Common::Serializer &ser); private: void playVocTrack(const uint8 *data); diff --git a/engines/scumm/saveload.cpp b/engines/scumm/saveload.cpp index 06d564648b..3e0a7f1ef8 100644 --- a/engines/scumm/saveload.cpp +++ b/engines/scumm/saveload.cpp @@ -23,6 +23,7 @@ #include "common/config-manager.h" #include "common/memstream.h" #include "common/savefile.h" +#include "common/serializer.h" #include "common/system.h" #include "common/zlib.h" @@ -185,8 +186,9 @@ bool ScummEngine::saveState(Common::WriteStream *out, bool writeHeader) { #endif saveInfos(out); - Serializer ser(0, out, CURRENT_VER); - saveOrLoad(&ser); + Common::Serializer ser(0, out); + ser.setVersion(CURRENT_VER); + saveLoadWithSerializer(ser); return true; } @@ -442,8 +444,9 @@ bool ScummEngine::loadState(int slot, bool compat, Common::String &filename) { // // Now do the actual loading // - Serializer ser(in, 0, hdr.ver); - saveOrLoad(&ser); + Common::Serializer ser(in, 0); + ser.setVersion(hdr.ver); + saveLoadWithSerializer(ser); delete in; // Update volume settings @@ -793,334 +796,337 @@ void ScummEngine::saveInfos(Common::WriteStream *file) { file->writeUint16BE(section.time); } -void ScummEngine::saveOrLoad(Serializer *s) { - const SaveLoadEntry objectEntries[] = { - MKLINE(ObjectData, OBIMoffset, sleUint32, VER(8)), - MKLINE(ObjectData, OBCDoffset, sleUint32, VER(8)), - MKLINE(ObjectData, walk_x, sleUint16, VER(8)), - MKLINE(ObjectData, walk_y, sleUint16, VER(8)), - MKLINE(ObjectData, obj_nr, sleUint16, VER(8)), - MKLINE(ObjectData, x_pos, sleInt16, VER(8)), - MKLINE(ObjectData, y_pos, sleInt16, VER(8)), - MKLINE(ObjectData, width, sleUint16, VER(8)), - MKLINE(ObjectData, height, sleUint16, VER(8)), - MKLINE(ObjectData, actordir, sleByte, VER(8)), - MKLINE(ObjectData, parentstate, sleByte, VER(8)), - MKLINE(ObjectData, parent, sleByte, VER(8)), - MKLINE(ObjectData, state, sleByte, VER(8)), - MKLINE(ObjectData, fl_object_index, sleByte, VER(8)), - MKLINE(ObjectData, flags, sleByte, VER(46)), - MKEND() - }; - - const SaveLoadEntry verbEntries[] = { - MKLINE(VerbSlot, curRect.left, sleInt16, VER(8)), - MKLINE(VerbSlot, curRect.top, sleInt16, VER(8)), - MKLINE(VerbSlot, curRect.right, sleInt16, VER(8)), - MKLINE(VerbSlot, curRect.bottom, sleInt16, VER(8)), - MKLINE(VerbSlot, oldRect.left, sleInt16, VER(8)), - MKLINE(VerbSlot, oldRect.top, sleInt16, VER(8)), - MKLINE(VerbSlot, oldRect.right, sleInt16, VER(8)), - MKLINE(VerbSlot, oldRect.bottom, sleInt16, VER(8)), - - MKLINE_OLD(VerbSlot, verbid, sleByte, VER(8), VER(11)), - MKLINE(VerbSlot, verbid, sleInt16, VER(12)), - - MKLINE(VerbSlot, color, sleByte, VER(8)), - MKLINE(VerbSlot, hicolor, sleByte, VER(8)), - MKLINE(VerbSlot, dimcolor, sleByte, VER(8)), - MKLINE(VerbSlot, bkcolor, sleByte, VER(8)), - MKLINE(VerbSlot, type, sleByte, VER(8)), - MKLINE(VerbSlot, charset_nr, sleByte, VER(8)), - MKLINE(VerbSlot, curmode, sleByte, VER(8)), - MKLINE(VerbSlot, saveid, sleByte, VER(8)), - MKLINE(VerbSlot, key, sleByte, VER(8)), - MKLINE(VerbSlot, center, sleByte, VER(8)), - MKLINE(VerbSlot, prep, sleByte, VER(8)), - MKLINE(VerbSlot, imgindex, sleUint16, VER(8)), - MKEND() - }; - - const SaveLoadEntry mainEntries[] = { - MKARRAY(ScummEngine, _gameMD5[0], sleUint8, 16, VER(39)), - MK_OBSOLETE(ScummEngine, _roomWidth, sleUint16, VER(8), VER(50)), - MK_OBSOLETE(ScummEngine, _roomHeight, sleUint16, VER(8), VER(50)), - MK_OBSOLETE(ScummEngine, _ENCD_offs, sleUint32, VER(8), VER(50)), - MK_OBSOLETE(ScummEngine, _EXCD_offs, sleUint32, VER(8), VER(50)), - MK_OBSOLETE(ScummEngine, _IM00_offs, sleUint32, VER(8), VER(50)), - MK_OBSOLETE(ScummEngine, _CLUT_offs, sleUint32, VER(8), VER(50)), - MK_OBSOLETE(ScummEngine, _EPAL_offs, sleUint32, VER(8), VER(9)), - MK_OBSOLETE(ScummEngine, _PALS_offs, sleUint32, VER(8), VER(50)), - MKLINE(ScummEngine, _curPalIndex, sleByte, VER(8)), - MKLINE(ScummEngine, _currentRoom, sleByte, VER(8)), - MKLINE(ScummEngine, _roomResource, sleByte, VER(8)), - MKLINE(ScummEngine, _numObjectsInRoom, sleByte, VER(8)), - MKLINE(ScummEngine, _currentScript, sleByte, VER(8)), - MK_OBSOLETE_ARRAY(ScummEngine, _localScriptOffsets[0], sleUint32, _numLocalScripts, VER(8), VER(50)), - - - // vm.localvar grew from 25 to 40 script entries and then from - // 16 to 32 bit variables (but that wasn't reflect here)... and - // THEN from 16 to 25 variables. - MKARRAY2_OLD(ScummEngine, vm.localvar[0][0], sleUint16, 17, 25, (byte *)vm.localvar[1] - (byte *)vm.localvar[0], VER(8), VER(8)), - MKARRAY2_OLD(ScummEngine, vm.localvar[0][0], sleUint16, 17, 40, (byte *)vm.localvar[1] - (byte *)vm.localvar[0], VER(9), VER(14)), - - // We used to save 25 * 40 = 1000 blocks; but actually, each 'row consisted of 26 entry, - // i.e. 26 * 40 = 1040. Thus the last 40 blocks of localvar where not saved at all. To be - // able to load this screwed format, we use a trick: We load 26 * 38 = 988 blocks. - // Then, we mark the followin 12 blocks (24 bytes) as obsolete. - MKARRAY2_OLD(ScummEngine, vm.localvar[0][0], sleUint16, 26, 38, (byte *)vm.localvar[1] - (byte *)vm.localvar[0], VER(15), VER(17)), - MK_OBSOLETE_ARRAY(ScummEngine, vm.localvar[39][0], sleUint16, 12, VER(15), VER(17)), - - // This was the first proper multi dimensional version of the localvars, with 32 bit values - MKARRAY2_OLD(ScummEngine, vm.localvar[0][0], sleUint32, 26, 40, (byte *)vm.localvar[1] - (byte *)vm.localvar[0], VER(18), VER(19)), - - // Then we doubled the script slots again, from 40 to 80 - MKARRAY2(ScummEngine, vm.localvar[0][0], sleUint32, 26, NUM_SCRIPT_SLOT, (byte *)vm.localvar[1] - (byte *)vm.localvar[0], VER(20)), - - - MKARRAY(ScummEngine, _resourceMapper[0], sleByte, 128, VER(8)), - MKARRAY(ScummEngine, _charsetColorMap[0], sleByte, 16, VER(8)), - - // _charsetData grew from 10*16, to 15*16, to 23*16 bytes - MKARRAY_OLD(ScummEngine, _charsetData[0][0], sleByte, 10 * 16, VER(8), VER(9)), - MKARRAY_OLD(ScummEngine, _charsetData[0][0], sleByte, 15 * 16, VER(10), VER(66)), - MKARRAY(ScummEngine, _charsetData[0][0], sleByte, 23 * 16, VER(67)), - - MK_OBSOLETE(ScummEngine, _curExecScript, sleUint16, VER(8), VER(62)), - - MKLINE(ScummEngine, camera._dest.x, sleInt16, VER(8)), - MKLINE(ScummEngine, camera._dest.y, sleInt16, VER(8)), - MKLINE(ScummEngine, camera._cur.x, sleInt16, VER(8)), - MKLINE(ScummEngine, camera._cur.y, sleInt16, VER(8)), - MKLINE(ScummEngine, camera._last.x, sleInt16, VER(8)), - MKLINE(ScummEngine, camera._last.y, sleInt16, VER(8)), - MKLINE(ScummEngine, camera._accel.x, sleInt16, VER(8)), - MKLINE(ScummEngine, camera._accel.y, sleInt16, VER(8)), - MKLINE(ScummEngine, _screenStartStrip, sleInt16, VER(8)), - MKLINE(ScummEngine, _screenEndStrip, sleInt16, VER(8)), - MKLINE(ScummEngine, camera._mode, sleByte, VER(8)), - MKLINE(ScummEngine, camera._follows, sleByte, VER(8)), - MKLINE(ScummEngine, camera._leftTrigger, sleInt16, VER(8)), - MKLINE(ScummEngine, camera._rightTrigger, sleInt16, VER(8)), - MKLINE(ScummEngine, camera._movingToActor, sleUint16, VER(8)), - - MKLINE(ScummEngine, _actorToPrintStrFor, sleByte, VER(8)), - MKLINE(ScummEngine, _charsetColor, sleByte, VER(8)), - - // _charsetBufPos was changed from byte to int - MKLINE_OLD(ScummEngine, _charsetBufPos, sleByte, VER(8), VER(9)), - MKLINE(ScummEngine, _charsetBufPos, sleInt16, VER(10)), - - MKLINE(ScummEngine, _haveMsg, sleByte, VER(8)), - MKLINE(ScummEngine, _haveActorSpeechMsg, sleByte, VER(61)), - MKLINE(ScummEngine, _useTalkAnims, sleByte, VER(8)), - - MKLINE(ScummEngine, _talkDelay, sleInt16, VER(8)), - MKLINE(ScummEngine, _defaultTalkDelay, sleInt16, VER(8)), - MK_OBSOLETE(ScummEngine, _numInMsgStack, sleInt16, VER(8), VER(27)), - MKLINE(ScummEngine, _sentenceNum, sleByte, VER(8)), - - MKLINE(ScummEngine, vm.cutSceneStackPointer, sleByte, VER(8)), - MKARRAY(ScummEngine, vm.cutScenePtr[0], sleUint32, 5, VER(8)), - MKARRAY(ScummEngine, vm.cutSceneScript[0], sleByte, 5, VER(8)), - MKARRAY(ScummEngine, vm.cutSceneData[0], sleInt16, 5, VER(8)), - MKLINE(ScummEngine, vm.cutSceneScriptIndex, sleInt16, VER(8)), - - MKLINE(ScummEngine, vm.numNestedScripts, sleByte, VER(8)), - MKLINE(ScummEngine, _userPut, sleByte, VER(8)), - MKLINE(ScummEngine, _userState, sleUint16, VER(17)), - MKLINE(ScummEngine, _cursor.state, sleByte, VER(8)), - MK_OBSOLETE(ScummEngine, _gdi->_cursorActive, sleByte, VER(8), VER(20)), - MKLINE(ScummEngine, _currentCursor, sleByte, VER(8)), - MKARRAY(ScummEngine, _grabbedCursor[0], sleByte, 8192, VER(20)), - MKLINE(ScummEngine, _cursor.width, sleInt16, VER(20)), - MKLINE(ScummEngine, _cursor.height, sleInt16, VER(20)), - MKLINE(ScummEngine, _cursor.hotspotX, sleInt16, VER(20)), - MKLINE(ScummEngine, _cursor.hotspotY, sleInt16, VER(20)), - MKLINE(ScummEngine, _cursor.animate, sleByte, VER(20)), - MKLINE(ScummEngine, _cursor.animateIndex, sleByte, VER(20)), - MKLINE(ScummEngine, _mouse.x, sleInt16, VER(20)), - MKLINE(ScummEngine, _mouse.y, sleInt16, VER(20)), - - MKARRAY(ScummEngine, _colorUsedByCycle[0], sleByte, 256, VER(60)), - MKLINE(ScummEngine, _doEffect, sleByte, VER(8)), - MKLINE(ScummEngine, _switchRoomEffect, sleByte, VER(8)), - MKLINE(ScummEngine, _newEffect, sleByte, VER(8)), - MKLINE(ScummEngine, _switchRoomEffect2, sleByte, VER(8)), - MKLINE(ScummEngine, _bgNeedsRedraw, sleByte, VER(8)), - - // The state of palManipulate is stored only since V10 - MKLINE(ScummEngine, _palManipStart, sleByte, VER(10)), - MKLINE(ScummEngine, _palManipEnd, sleByte, VER(10)), - MKLINE(ScummEngine, _palManipCounter, sleUint16, VER(10)), - - // gfxUsageBits grew from 200 to 410 entries. Then 3 * 410 entries: - MKARRAY_OLD(ScummEngine, gfxUsageBits[0], sleUint32, 200, VER(8), VER(9)), - MKARRAY_OLD(ScummEngine, gfxUsageBits[0], sleUint32, 410, VER(10), VER(13)), - MKARRAY(ScummEngine, gfxUsageBits[0], sleUint32, 3 * 410, VER(14)), - - MK_OBSOLETE(ScummEngine, _gdi->_transparentColor, sleByte, VER(8), VER(50)), - MKARRAY(ScummEngine, _currentPalette[0], sleByte, 768, VER(8)), - MKARRAY(ScummEngine, _darkenPalette[0], sleByte, 768, VER(53)), - - // Sam & Max specific palette replaced by _shadowPalette now. - MK_OBSOLETE_ARRAY(ScummEngine, _proc_special_palette[0], sleByte, 256, VER(8), VER(33)), - - MKARRAY(ScummEngine, _charsetBuffer[0], sleByte, 256, VER(8)), - - MKLINE(ScummEngine, _egoPositioned, sleByte, VER(8)), - - // _gdi->_imgBufOffs grew from 4 to 5 entries. Then one day we realized - // that we don't have to store it since initBGBuffers() recomputes it. - MK_OBSOLETE_ARRAY(ScummEngine, _gdi->_imgBufOffs[0], sleUint16, 4, VER(8), VER(9)), - MK_OBSOLETE_ARRAY(ScummEngine, _gdi->_imgBufOffs[0], sleUint16, 5, VER(10), VER(26)), - - // See _imgBufOffs: _numZBuffer is recomputed by initBGBuffers(). - MK_OBSOLETE(ScummEngine, _gdi->_numZBuffer, sleByte, VER(8), VER(26)), - - MKLINE(ScummEngine, _screenEffectFlag, sleByte, VER(8)), - - MK_OBSOLETE(ScummEngine, _randSeed1, sleUint32, VER(8), VER(9)), - MK_OBSOLETE(ScummEngine, _randSeed2, sleUint32, VER(8), VER(9)), - - // Converted _shakeEnabled to boolean and added a _shakeFrame field. - MKLINE_OLD(ScummEngine, _shakeEnabled, sleInt16, VER(8), VER(9)), - MKLINE(ScummEngine, _shakeEnabled, sleByte, VER(10)), - MKLINE(ScummEngine, _shakeFrame, sleUint32, VER(10)), - - MKLINE(ScummEngine, _keepText, sleByte, VER(8)), - - MKLINE(ScummEngine, _screenB, sleUint16, VER(8)), - MKLINE(ScummEngine, _screenH, sleUint16, VER(8)), - - MKLINE(ScummEngine, _NESCostumeSet, sleUint16, VER(47)), - - MK_OBSOLETE(ScummEngine, _cd_track, sleInt16, VER(9), VER(9)), - MK_OBSOLETE(ScummEngine, _cd_loops, sleInt16, VER(9), VER(9)), - MK_OBSOLETE(ScummEngine, _cd_frame, sleInt16, VER(9), VER(9)), - MK_OBSOLETE(ScummEngine, _cd_end, sleInt16, VER(9), VER(9)), - - MKEND() - }; - - const SaveLoadEntry scriptSlotEntries[] = { - MKLINE(ScriptSlot, offs, sleUint32, VER(8)), - MKLINE(ScriptSlot, delay, sleInt32, VER(8)), - MKLINE(ScriptSlot, number, sleUint16, VER(8)), - MKLINE(ScriptSlot, delayFrameCount, sleUint16, VER(8)), - MKLINE(ScriptSlot, status, sleByte, VER(8)), - MKLINE(ScriptSlot, where, sleByte, VER(8)), - MKLINE(ScriptSlot, freezeResistant, sleByte, VER(8)), - MKLINE(ScriptSlot, recursive, sleByte, VER(8)), - MKLINE(ScriptSlot, freezeCount, sleByte, VER(8)), - MKLINE(ScriptSlot, didexec, sleByte, VER(8)), - MKLINE(ScriptSlot, cutsceneOverride, sleByte, VER(8)), - MKLINE(ScriptSlot, cycle, sleByte, VER(46)), - MK_OBSOLETE(ScriptSlot, unk5, sleByte, VER(8), VER(10)), - MKEND() - }; - - const SaveLoadEntry nestedScriptEntries[] = { - MKLINE(NestedScript, number, sleUint16, VER(8)), - MKLINE(NestedScript, where, sleByte, VER(8)), - MKLINE(NestedScript, slot, sleByte, VER(8)), - MKEND() - }; - - const SaveLoadEntry sentenceTabEntries[] = { - MKLINE(SentenceTab, verb, sleUint8, VER(8)), - MKLINE(SentenceTab, preposition, sleUint8, VER(8)), - MKLINE(SentenceTab, objectA, sleUint16, VER(8)), - MKLINE(SentenceTab, objectB, sleUint16, VER(8)), - MKLINE(SentenceTab, freezeCount, sleUint8, VER(8)), - MKEND() - }; - - const SaveLoadEntry stringTabEntries[] = { - // Then _default/restore of a StringTab entry becomes a one liner. - MKLINE(StringTab, xpos, sleInt16, VER(8)), - MKLINE(StringTab, _default.xpos, sleInt16, VER(8)), - MKLINE(StringTab, ypos, sleInt16, VER(8)), - MKLINE(StringTab, _default.ypos, sleInt16, VER(8)), - MKLINE(StringTab, right, sleInt16, VER(8)), - MKLINE(StringTab, _default.right, sleInt16, VER(8)), - MKLINE(StringTab, color, sleInt8, VER(8)), - MKLINE(StringTab, _default.color, sleInt8, VER(8)), - MKLINE(StringTab, charset, sleInt8, VER(8)), - MKLINE(StringTab, _default.charset, sleInt8, VER(8)), - MKLINE(StringTab, center, sleByte, VER(8)), - MKLINE(StringTab, _default.center, sleByte, VER(8)), - MKLINE(StringTab, overhead, sleByte, VER(8)), - MKLINE(StringTab, _default.overhead, sleByte, VER(8)), - MKLINE(StringTab, no_talk_anim, sleByte, VER(8)), - MKLINE(StringTab, _default.no_talk_anim, sleByte, VER(8)), - MKLINE(StringTab, wrapping, sleByte, VER(71)), - MKLINE(StringTab, _default.wrapping, sleByte, VER(71)), - MKEND() - }; - - const SaveLoadEntry colorCycleEntries[] = { - MKLINE(ColorCycle, delay, sleUint16, VER(8)), - MKLINE(ColorCycle, counter, sleUint16, VER(8)), - MKLINE(ColorCycle, flags, sleUint16, VER(8)), - MKLINE(ColorCycle, start, sleByte, VER(8)), - MKLINE(ColorCycle, end, sleByte, VER(8)), - MKEND() - }; - - const SaveLoadEntry scaleSlotsEntries[] = { - MKLINE(ScaleSlot, x1, sleUint16, VER(13)), - MKLINE(ScaleSlot, y1, sleUint16, VER(13)), - MKLINE(ScaleSlot, scale1, sleUint16, VER(13)), - MKLINE(ScaleSlot, x2, sleUint16, VER(13)), - MKLINE(ScaleSlot, y2, sleUint16, VER(13)), - MKLINE(ScaleSlot, scale2, sleUint16, VER(13)), - MKEND() - }; - - // MSVC6 FIX (Jamieson630): - // MSVC6 has a problem with any notation that involves - // more than one set of double colons :: - // The following MKLINE macros expand to such things - // as AudioCDManager::Status::playing, and MSVC6 has - // a fit with that. This typedef simplifies the notation - // to something MSVC6 can grasp. - typedef AudioCDManager::Status AudioCDManager_Status; - const SaveLoadEntry audioCDEntries[] = { - MKLINE(AudioCDManager_Status, playing, sleUint32, VER(24)), - MKLINE(AudioCDManager_Status, track, sleInt32, VER(24)), - MKLINE(AudioCDManager_Status, start, sleUint32, VER(24)), - MKLINE(AudioCDManager_Status, duration, sleUint32, VER(24)), - MKLINE(AudioCDManager_Status, numLoops, sleInt32, VER(24)), - MKEND() - }; +static void syncWithSerializer(Common::Serializer &s, ObjectData &od) { + s.syncAsUint32LE(od.OBIMoffset, VER(8)); + s.syncAsUint32LE(od.OBCDoffset, VER(8)); + s.syncAsUint16LE(od.walk_x, VER(8)); + s.syncAsUint16LE(od.walk_y, VER(8)); + s.syncAsUint16LE(od.obj_nr, VER(8)); + s.syncAsSint16LE(od.x_pos, VER(8)); + s.syncAsSint16LE(od.y_pos, VER(8)); + s.syncAsUint16LE(od.width, VER(8)); + s.syncAsUint16LE(od.height, VER(8)); + s.syncAsByte(od.actordir, VER(8)); + s.syncAsByte(od.parentstate, VER(8)); + s.syncAsByte(od.parent, VER(8)); + s.syncAsByte(od.state, VER(8)); + s.syncAsByte(od.fl_object_index, VER(8)); + s.syncAsByte(od.flags, VER(46)); +} + +static void syncWithSerializer(Common::Serializer &s, VerbSlot &vs) { + s.syncAsSint16LE(vs.curRect.left, VER(8)); + s.syncAsSint16LE(vs.curRect.top, VER(8)); + s.syncAsSint16LE(vs.curRect.right, VER(8)); + s.syncAsSint16LE(vs.curRect.bottom, VER(8)); + s.syncAsSint16LE(vs.oldRect.left, VER(8)); + s.syncAsSint16LE(vs.oldRect.top, VER(8)); + s.syncAsSint16LE(vs.oldRect.right, VER(8)); + s.syncAsSint16LE(vs.oldRect.bottom, VER(8)); + s.syncAsByte(vs.verbid, VER(8), VER(11)); + s.syncAsSint16LE(vs.verbid, VER(12)); + s.syncAsByte(vs.color, VER(8)); + s.syncAsByte(vs.hicolor, VER(8)); + s.syncAsByte(vs.dimcolor, VER(8)); + s.syncAsByte(vs.bkcolor, VER(8)); + s.syncAsByte(vs.type, VER(8)); + s.syncAsByte(vs.charset_nr, VER(8)); + s.syncAsByte(vs.curmode, VER(8)); + s.syncAsByte(vs.saveid, VER(8)); + s.syncAsByte(vs.key, VER(8)); + s.syncAsByte(vs.center, VER(8)); + s.syncAsByte(vs.prep, VER(8)); + s.syncAsUint16LE(vs.imgindex, VER(8)); +} + +static void syncWithSerializer(Common::Serializer &s, ScriptSlot &ss) { + s.syncAsUint32LE(ss.offs, VER(8)); + s.syncAsSint32LE(ss.delay, VER(8)); + s.syncAsUint16LE(ss.number, VER(8)); + s.syncAsUint16LE(ss.delayFrameCount, VER(8)); + s.syncAsByte(ss.status, VER(8)); + s.syncAsByte(ss.where, VER(8)); + s.syncAsByte(ss.freezeResistant, VER(8)); + s.syncAsByte(ss.recursive, VER(8)); + s.syncAsByte(ss.freezeCount, VER(8)); + s.syncAsByte(ss.didexec, VER(8)); + s.syncAsByte(ss.cutsceneOverride, VER(8)); + s.syncAsByte(ss.cycle, VER(46)); + s.skip(1, VER(8), VER(10)); // unk5 +} + +static void syncWithSerializer(Common::Serializer &s, NestedScript &ns) { + s.syncAsUint16LE(ns.number, VER(8)); + s.syncAsByte(ns.where, VER(8)); + s.syncAsByte(ns.slot, VER(8)); +} + +static void syncWithSerializer(Common::Serializer &s, SentenceTab &st) { + s.syncAsByte(st.verb, VER(8)); + s.syncAsByte(st.preposition, VER(8)); + s.syncAsUint16LE(st.objectA, VER(8)); + s.syncAsUint16LE(st.objectB, VER(8)); + s.syncAsByte(st.freezeCount, VER(8)); +} + +static void syncWithSerializer(Common::Serializer &s, StringTab &st) { + s.syncAsSint16LE(st.xpos, VER(8)); + s.syncAsSint16LE(st._default.xpos, VER(8)); + s.syncAsSint16LE(st.ypos, VER(8)); + s.syncAsSint16LE(st._default.ypos, VER(8)); + s.syncAsSint16LE(st.right, VER(8)); + s.syncAsSint16LE(st._default.right, VER(8)); + s.syncAsSByte(st.color, VER(8)); + s.syncAsSByte(st._default.color, VER(8)); + s.syncAsSByte(st.charset, VER(8)); + s.syncAsSByte(st._default.charset, VER(8)); + s.syncAsByte(st.center, VER(8)); + s.syncAsByte(st._default.center, VER(8)); + s.syncAsByte(st.overhead, VER(8)); + s.syncAsByte(st._default.overhead, VER(8)); + s.syncAsByte(st.no_talk_anim, VER(8)); + s.syncAsByte(st._default.no_talk_anim, VER(8)); + s.syncAsByte(st.wrapping, VER(71)); + s.syncAsByte(st._default.wrapping, VER(71)); +} + +static void syncWithSerializer(Common::Serializer &s, ColorCycle &cc) { + s.syncAsUint16LE(cc.delay, VER(8)); + s.syncAsUint16LE(cc.counter, VER(8)); + s.syncAsUint16LE(cc.flags, VER(8)); + s.syncAsByte(cc.start, VER(8)); + s.syncAsByte(cc.end, VER(8)); +} + +void syncWithSerializer(Common::Serializer &s, ScummEngine::ScaleSlot &ss) { + s.syncAsUint16LE(ss.x1, VER(13)); + s.syncAsUint16LE(ss.y1, VER(13)); + s.syncAsUint16LE(ss.scale1, VER(13)); + s.syncAsUint16LE(ss.x2, VER(13)); + s.syncAsUint16LE(ss.y2, VER(13)); + s.syncAsUint16LE(ss.scale2, VER(13)); +} + +static void syncWithSerializer(Common::Serializer &s, AudioCDManager::Status &as) { + s.syncAsUint32LE(as.playing, VER(24)); + s.syncAsSint32LE(as.track, VER(24)); + s.syncAsUint32LE(as.start, VER(24)); + s.syncAsUint32LE(as.duration, VER(24)); + s.syncAsSint32LE(as.numLoops, VER(24)); +} + +static void syncWithSerializer(Common::Serializer &s, Common::Rect &rect) { + s.syncAsSint16LE(rect.left); + s.syncAsSint16LE(rect.top); + s.syncAsSint16LE(rect.right); + s.syncAsSint16LE(rect.bottom); +} + +template +static void sync2DArray(Common::Serializer &s, T (&array)[N][M], const size_t dim1, const size_t dim2, void (*serializer)(Common::Serializer &, T &), Common::Serializer::Version minVersion = 0, Common::Serializer::Version maxVersion = Common::Serializer::kLastVersion) { + + if (s.getVersion() < minVersion || s.getVersion() > maxVersion) { + return; + } + assert(dim1 <= N); + assert(dim2 <= M); + for (size_t i = 0; i < dim1; ++i) { + for (size_t j = 0; j < dim2; ++j) { + serializer(s, array[i][j]); + } + } +} + +void ScummEngine::saveLoadWithSerializer(Common::Serializer &s) { int i; int var120Backup; int var98Backup; uint8 md5Backup[16]; // MD5 Operations: Backup on load, compare, and reset. - if (s->isLoading()) + if (s.isLoading()) memcpy(md5Backup, _gameMD5, 16); // // Save/load main state (many members of class ScummEngine get saved here) // - s->saveLoadEntries(this, mainEntries); + s.syncBytes(_gameMD5, sizeof(_gameMD5), VER(39)); + s.skip(2, VER(8), VER(50)); // _roomWidth + s.skip(2, VER(8), VER(50)); // _roomHeight + s.skip(4, VER(8), VER(50)); // _ENCD_offs + s.skip(4, VER(8), VER(50)); // _EXCD_offs + s.skip(4, VER(8), VER(50)); // _IM00_offs + s.skip(4, VER(8), VER(50)); // _CLUT_offs + s.skip(4, VER(8), VER(9)); // _EPAL_offs + s.skip(4, VER(8), VER(50)); // _PALS_offs + s.syncAsByte(_curPalIndex, VER(8)); + s.syncAsByte(_currentRoom, VER(8)); + s.syncAsByte(_roomResource, VER(8)); + s.syncAsByte(_numObjectsInRoom, VER(8)); + s.syncAsByte(_currentScript, VER(8)); + s.skip(4 * _numLocalScripts, VER(8), VER(50)); // _localScriptOffsets + + // vm.localvar grew from 25 to 40 script entries and then from + // 16 to 32 bit variables (but that wasn't reflect here)... and + // THEN from 16 to 25 variables. + sync2DArray(s, vm.localvar, 25, 17, Common::Serializer::Uint16LE, VER(8), VER(8)); + sync2DArray(s, vm.localvar, 40, 17, Common::Serializer::Uint16LE, VER(9), VER(14)); + + // We used to save 25 * 40 = 1000 blocks; but actually, each 'row consisted of 26 entry, + // i. 26 * 40 = 1040. Thus the last 40 blocks of localvar where not saved at all. To be + // able to load this screwed format, we use a trick: We load 26 * 38 = 988 blocks. + // Then, we mark the followin 12 blocks (24 bytes) as obsolete. + sync2DArray(s, vm.localvar, 38, 26, Common::Serializer::Uint16LE, VER(15), VER(17)); + s.skip(2 * 12, VER(15), VER(17)); + + // This was the first proper multi dimensional version of the localvars, with 32 bit values + sync2DArray(s, vm.localvar, 40, 26, Common::Serializer::Uint32LE, VER(18), VER(19)); + + // Then we doubled the script slots again, from 40 to 80 + sync2DArray(s, vm.localvar, NUM_SCRIPT_SLOT, 26, Common::Serializer::Uint32LE, VER(20)); + + s.syncBytes(_resourceMapper, 128, VER(8)); + s.syncBytes(_charsetColorMap, 16, VER(8)); + + // _charsetData grew from 10*16, to 15*16, to 23*16 bytes + for (int i = 0; i < 10; ++i) { + s.syncBytes(_charsetData[i], 16, VER(8)); + } + for (int i = 10; i < 15; ++i) { + s.syncBytes(_charsetData[i], 16, VER(10)); + } + for (int i = 15; i < 23; ++i) { + s.syncBytes(_charsetData[i], 16, VER(67)); + } + + s.skip(2, VER(8), VER(62)); // _curExecScript + + s.syncAsSint16LE(camera._dest.x, VER(8)); + s.syncAsSint16LE(camera._dest.y, VER(8)); + s.syncAsSint16LE(camera._cur.x, VER(8)); + s.syncAsSint16LE(camera._cur.y, VER(8)); + s.syncAsSint16LE(camera._last.x, VER(8)); + s.syncAsSint16LE(camera._last.y, VER(8)); + s.syncAsSint16LE(camera._accel.x, VER(8)); + s.syncAsSint16LE(camera._accel.y, VER(8)); + s.syncAsSint16LE(_screenStartStrip, VER(8)); + s.syncAsSint16LE(_screenEndStrip, VER(8)); + s.syncAsByte(camera._mode, VER(8)); + s.syncAsByte(camera._follows, VER(8)); + s.syncAsSint16LE(camera._leftTrigger, VER(8)); + s.syncAsSint16LE(camera._rightTrigger, VER(8)); + s.syncAsUint16LE(camera._movingToActor, VER(8)); + + s.syncAsByte(_actorToPrintStrFor, VER(8)); + s.syncAsByte(_charsetColor, VER(8)); + + // _charsetBufPos was changed from byte to int + s.syncAsByte(_charsetBufPos, VER(8), VER(9)); + s.syncAsSint16LE(_charsetBufPos, VER(10)); + + s.syncAsByte(_haveMsg, VER(8)); + s.syncAsByte(_haveActorSpeechMsg, VER(61)); + s.syncAsByte(_useTalkAnims, VER(8)); + + s.syncAsSint16LE(_talkDelay, VER(8)); + s.syncAsSint16LE(_defaultTalkDelay, VER(8)); + s.skip(2, VER(8), VER(27)); // _numInMsgStack + s.syncAsByte(_sentenceNum, VER(8)); + + s.syncAsByte(vm.cutSceneStackPointer, VER(8)); + s.syncArray(vm.cutScenePtr, 5, Common::Serializer::Uint32LE, VER(8)); + s.syncBytes(vm.cutSceneScript, 5, VER(8)); + s.syncArray(vm.cutSceneData, 5, Common::Serializer::Sint16LE, VER(8)); + s.syncAsSint16LE(vm.cutSceneScriptIndex, VER(8)); + + s.syncAsByte(vm.numNestedScripts, VER(8)); + s.syncAsByte(_userPut, VER(8)); + s.syncAsUint16LE(_userState, VER(17)); + s.syncAsByte(_cursor.state, VER(8)); + s.skip(1, VER(8), VER(20)); // _gdi->_cursorActive + s.syncAsByte(_currentCursor, VER(8)); + // TODO: This seems wrong, _grabbedCursor is >8192 bytes and sometimes holds + // 16-bit values + s.syncBytes(_grabbedCursor, 8192, VER(20)); + s.syncAsSint16LE(_cursor.width, VER(20)); + s.syncAsSint16LE(_cursor.height, VER(20)); + s.syncAsSint16LE(_cursor.hotspotX, VER(20)); + s.syncAsSint16LE(_cursor.hotspotY, VER(20)); + s.syncAsByte(_cursor.animate, VER(20)); + s.syncAsByte(_cursor.animateIndex, VER(20)); + s.syncAsSint16LE(_mouse.x, VER(20)); + s.syncAsSint16LE(_mouse.y, VER(20)); + + s.syncBytes(_colorUsedByCycle, 256, VER(60)); + s.syncAsByte(_doEffect, VER(8)); + s.syncAsByte(_switchRoomEffect, VER(8)); + s.syncAsByte(_newEffect, VER(8)); + s.syncAsByte(_switchRoomEffect2, VER(8)); + s.syncAsByte(_bgNeedsRedraw, VER(8)); + + // The state of palManipulate is stored only since V10 + s.syncAsByte(_palManipStart, VER(10)); + s.syncAsByte(_palManipEnd, VER(10)); + s.syncAsUint16LE(_palManipCounter, VER(10)); + + // gfxUsageBits grew from 200 to 410 entries. Then 3 * 410 entries: + s.syncArray(gfxUsageBits, 200, Common::Serializer::Uint32LE, VER(8), VER(9)); + s.syncArray(gfxUsageBits, 410, Common::Serializer::Uint32LE, VER(10), VER(13)); + s.syncArray(gfxUsageBits, 3 * 410, Common::Serializer::Uint32LE, VER(14)); + + s.skip(1, VER(8), VER(50)); // _gdi->_transparentColor + s.syncBytes(_currentPalette, 768, VER(8)); + s.syncBytes(_darkenPalette, 768, VER(53)); + + // Sam & Max specific palette replaced by _shadowPalette now. + s.skip(256, VER(8), VER(33)); // _proc_special_palette + + s.syncBytes(_charsetBuffer, 256, VER(8)); + + s.syncAsByte(_egoPositioned, VER(8)); + + // _gdi->_imgBufOffs grew from 4 to 5 entries. Then one day we realized + // that we don't have to store it since initBGBuffers() recomputes it. + s.skip(2 * 4, VER(8), VER(9)); // _gdi->_imgBufOffs + s.skip(2 * 5, VER(10), VER(26)); // _gdi->_imgBufOffs + + // See _imgBufOffs: _numZBuffer is recomputed by initBGBuffers(). + s.skip(1, VER(8), VER(26)); // _gdi->_numZBuffer + + s.syncAsByte(_screenEffectFlag, VER(8)); + + s.skip(4, VER(8), VER(9)); // _randSeed1 + s.skip(4, VER(8), VER(9)); // _randSeed2 + + // Converted _shakeEnabled to boolean and added a _shakeFrame field. + s.syncAsSint16LE(_shakeEnabled, VER(8), VER(9)); + s.syncAsByte(_shakeEnabled, VER(10)); + s.syncAsUint32LE(_shakeFrame, VER(10)); + + s.syncAsByte(_keepText, VER(8)); + + s.syncAsUint16LE(_screenB, VER(8)); + s.syncAsUint16LE(_screenH, VER(8)); + + s.syncAsUint16LE(_NESCostumeSet, VER(47)); + + s.skip(2, VER(9), VER(9)); // _cd_track + s.skip(2, VER(9), VER(9)); // _cd_loops + s.skip(2, VER(9), VER(9)); // _cd_frame + s.skip(2, VER(9), VER(9)); // _cd_end // MD5 Operations: Backup on load, compare, and reset. - if (s->isLoading()) { + if (s.isLoading()) { char md5str1[32+1], md5str2[32+1]; for (i = 0; i < 16; i++) { sprintf(md5str1 + i*2, "%02x", (int)_gameMD5[i]); sprintf(md5str2 + i*2, "%02x", (int)md5Backup[i]); } - debug(2, "Save version: %d", s->getVersion()); - debug(2, "Saved game MD5: %s", (s->getVersion() >= 39) ? md5str1 : "unknown"); + debug(2, "Save version: %d", s.getVersion()); + debug(2, "Saved game MD5: %s", (s.getVersion() >= 39) ? md5str1 : "unknown"); if (memcmp(md5Backup, _gameMD5, 16) != 0) { warning("Game was saved with different gamedata - you may encounter problems"); @@ -1134,22 +1140,22 @@ void ScummEngine::saveOrLoad(Serializer *s) { // that have more than 30 actors (up to 94 are supported now, in theory). // Since the format of the usage bits was changed by this, we have to // convert them when loading an older savegame. - if (s->isLoading() && s->getVersion() < VER(14)) + if (s.isLoading() && s.getVersion() < VER(14)) upgradeGfxUsageBits(); // When loading, reset the ShakePos. Fixes one part of bug #7141 - if (s->isLoading() && s->getVersion() >= VER(10)) + if (s.isLoading() && s.getVersion() >= VER(10)) _system->setShakePos(0); // When loading, move the mouse to the saved mouse position. - if (s->isLoading() && s->getVersion() >= VER(20)) { + if (s.isLoading() && s.getVersion() >= VER(20)) { updateCursor(); _system->warpMouse(_mouse.x, _mouse.y); } // Before V61, we re-used the _haveMsg flag to handle "alternative" speech // sound files (see charset code 10). - if (s->isLoading() && s->getVersion() < VER(61)) { + if (s.isLoading() && s.getVersion() < VER(61)) { if (_haveMsg == 0xFE) { _haveActorSpeechMsg = false; _haveMsg = 0xFF; @@ -1174,14 +1180,11 @@ void ScummEngine::saveOrLoad(Serializer *s) { // // Save/load script data // - if (s->getVersion() < VER(9)) - s->saveLoadArrayOf(vm.slot, 25, sizeof(vm.slot[0]), scriptSlotEntries); - else if (s->getVersion() < VER(20)) - s->saveLoadArrayOf(vm.slot, 40, sizeof(vm.slot[0]), scriptSlotEntries); - else - s->saveLoadArrayOf(vm.slot, NUM_SCRIPT_SLOT, sizeof(vm.slot[0]), scriptSlotEntries); + s.syncArray(vm.slot, 25, syncWithSerializer, VER(0), VER(8)); + s.syncArray(vm.slot, 40, syncWithSerializer, VER(9), VER(19)); + s.syncArray(vm.slot, NUM_SCRIPT_SLOT, syncWithSerializer, VER(20)); - if (s->getVersion() < VER(46)) { + if (s.getVersion() < VER(46)) { // When loading an old savegame, make sure that the 'cycle' // field is set to something sensible, otherwise the scripts // that were running probably won't be. @@ -1195,13 +1198,13 @@ void ScummEngine::saveOrLoad(Serializer *s) { // // Save/load local objects // - s->saveLoadArrayOf(_objs, _numLocalObjects, sizeof(_objs[0]), objectEntries); - if (s->isLoading()) { - if (s->getVersion() < VER(13)) { + s.syncArray(_objs, _numLocalObjects, syncWithSerializer); + if (s.isLoading()) { + if (s.getVersion() < VER(13)) { // Since roughly v13 of the save games, the objs storage has changed a bit for (i = _numObjectsInRoom; i < _numLocalObjects; i++) _objs[i].obj_nr = 0; - } else if (_game.version == 0 && s->getVersion() < VER(91)) { + } else if (_game.version == 0 && s.getVersion() < VER(91)) { for (i = 0; i < _numLocalObjects; i++) { // Merge object id and type (previously stored in flags) if (_objs[i].obj_nr != 0 && OBJECT_V0_TYPE(_objs[i].obj_nr) == 0 && _objs[i].flags != 0) @@ -1215,13 +1218,12 @@ void ScummEngine::saveOrLoad(Serializer *s) { // // Save/load misc stuff // - s->saveLoadArrayOf(_verbs, _numVerbs, sizeof(_verbs[0]), verbEntries); - s->saveLoadArrayOf(vm.nest, 16, sizeof(vm.nest[0]), nestedScriptEntries); - s->saveLoadArrayOf(_sentence, 6, sizeof(_sentence[0]), sentenceTabEntries); - s->saveLoadArrayOf(_string, 6, sizeof(_string[0]), stringTabEntries); - s->saveLoadArrayOf(_colorCycle, 16, sizeof(_colorCycle[0]), colorCycleEntries); - if (s->getVersion() >= VER(13)) - s->saveLoadArrayOf(_scaleSlots, 20, sizeof(_scaleSlots[0]), scaleSlotsEntries); + s.syncArray(_verbs, _numVerbs, syncWithSerializer); + s.syncArray(vm.nest, 16, syncWithSerializer); + s.syncArray(_sentence, 6, syncWithSerializer); + s.syncArray(_string, 6, syncWithSerializer); + s.syncArray(_colorCycle, 16, syncWithSerializer); + s.syncArray(_scaleSlots, 20, syncWithSerializer, VER(13)); // @@ -1229,30 +1231,31 @@ void ScummEngine::saveOrLoad(Serializer *s) { // ResType type; ResId idx; - if (s->getVersion() >= VER(26)) { + if (s.getVersion() >= VER(26)) { // New, more robust resource save/load system. This stores the type // and index of each resource. Thus if we increase e.g. the maximum // number of script resources, savegames won't break. - if (s->isSaving()) { + if (s.isSaving()) { + uint16 endMarker = 0xFFFF; for (type = rtFirst; type <= rtLast; type = ResType(type + 1)) { if (_res->_types[type]._mode != kStaticResTypeMode && type != rtTemp && type != rtBuffer) { - s->saveUint16(type); // Save the res type... + s.syncAsUint16LE(type); // Save the res type... for (idx = 0; idx < _res->_types[type].size(); idx++) { // Only save resources which actually exist... if (_res->_types[type][idx]._address) { - s->saveUint16(idx); // Save the index of the resource + s.syncAsUint16LE(idx); // Save the index of the resource saveResource(s, type, idx); } } - s->saveUint16(0xFFFF); // End marker + s.syncAsUint16LE(endMarker); } } - s->saveUint16(0xFFFF); // End marker + s.syncAsUint16LE(endMarker); } else { uint16 tmp; - while ((tmp = s->loadUint16()) != 0xFFFF) { + while (s.syncAsUint16LE(tmp), tmp != 0xFFFF) { type = (ResType)tmp; - while ((idx = s->loadUint16()) != 0xFFFF) { + while (s.syncAsUint16LE(idx), idx != 0xFFFF) { assert(idx < _res->_types[type].size()); loadResource(s, type, idx); } @@ -1278,17 +1281,17 @@ void ScummEngine::saveOrLoad(Serializer *s) { // // Save/load global object state // - s->saveLoadArrayOf(_objectOwnerTable, _numGlobalObjects, sizeof(_objectOwnerTable[0]), sleByte); - s->saveLoadArrayOf(_objectStateTable, _numGlobalObjects, sizeof(_objectStateTable[0]), sleByte); + s.syncBytes(_objectOwnerTable, _numGlobalObjects); + s.syncBytes(_objectStateTable, _numGlobalObjects); if (_objectRoomTable) - s->saveLoadArrayOf(_objectRoomTable, _numGlobalObjects, sizeof(_objectRoomTable[0]), sleByte); + s.syncBytes(_objectRoomTable, _numGlobalObjects); // // Save/load palette data // Don't save 16 bit palette in FM-Towns and PCE games, since it gets regenerated afterwards anyway. - if (_16BitPalette && !(_game.platform == Common::kPlatformFMTowns && s->getVersion() < VER(82)) && !((_game.platform == Common::kPlatformFMTowns || _game.platform == Common::kPlatformPCEngine) && s->getVersion() > VER(87))) { - s->saveLoadArrayOf(_16BitPalette, 512, sizeof(_16BitPalette[0]), sleUint16); + if (_16BitPalette && !(_game.platform == Common::kPlatformFMTowns && s.getVersion() < VER(82)) && !((_game.platform == Common::kPlatformFMTowns || _game.platform == Common::kPlatformPCEngine) && s.getVersion() > VER(87))) { + s.syncArray(_16BitPalette, 512, Common::Serializer::Uint16LE); } @@ -1310,82 +1313,71 @@ void ScummEngine::saveOrLoad(Serializer *s) { } #else - byte hasTownsData = ((_game.platform == Common::kPlatformFMTowns && s->getVersion() >= VER(87)) || (s->getVersion() >= VER(82) && s->getVersion() < VER(87))) ? 1 : 0; - if (_game.platform == Common::kPlatformFMTowns && s->getVersion() > VER(87)) - s->saveLoadArrayOf(&hasTownsData, 1, sizeof(byte), sleByte); + byte hasTownsData = ((_game.platform == Common::kPlatformFMTowns && s.getVersion() >= VER(87)) || (s.getVersion() >= VER(82) && s.getVersion() < VER(87))) ? 1 : 0; + if (_game.platform == Common::kPlatformFMTowns && s.getVersion() > VER(87)) + s.syncAsByte(hasTownsData); if (hasTownsData) { - const SaveLoadEntry townsFields[] = { - MKLINE(Common::Rect, left, sleInt16, VER(82)), - MKLINE(Common::Rect, top, sleInt16, VER(82)), - MKLINE(Common::Rect, right, sleInt16, VER(82)), - MKLINE(Common::Rect, bottom, sleInt16, VER(82)), - MKEND() - }; - - const SaveLoadEntry townsExtraEntries[] = { - MKLINE(ScummEngine, _townsOverrideShadowColor, sleUint8, VER(82)), - MKLINE(ScummEngine, _numCyclRects, sleUint8, VER(82)), - MKLINE(ScummEngine, _townsPaletteFlags, sleUint8, VER(82)), - MKLINE(ScummEngine, _townsClearLayerFlag, sleUint8, VER(82)), - MKLINE(ScummEngine, _townsActiveLayerFlags, sleUint8, VER(82)), - MKEND() - }; - - s->saveLoadArrayOf(_textPalette, 48, sizeof(_textPalette[0]), sleUint8); - s->saveLoadArrayOf(_cyclRects, 10, sizeof(_cyclRects[0]), townsFields); - s->saveLoadArrayOf(&_curStringRect, 1, sizeof(_curStringRect), townsFields); - s->saveLoadArrayOf(_townsCharsetColorMap, 16, sizeof(_townsCharsetColorMap[0]), sleUint8); - s->saveLoadEntries(this, townsExtraEntries); - } else if (_game.platform == Common::kPlatformFMTowns && s->getVersion() >= VER(82)) { + s.syncBytes(_textPalette, 48); + // TODO: This seems wrong, there are 16 _cyclRects + s.syncArray(_cyclRects, 10, syncWithSerializer, VER(82)); + if (s.getVersion() >= VER(82)) + syncWithSerializer(s, _curStringRect); + s.syncBytes(_townsCharsetColorMap, 16); + s.syncAsByte(_townsOverrideShadowColor, VER(82)); + s.syncAsByte(_numCyclRects, VER(82)); + s.syncAsByte(_townsPaletteFlags, VER(82)); + s.syncAsByte(_townsClearLayerFlag, VER(82)); + s.syncAsByte(_townsActiveLayerFlags, VER(82)); + } else if (_game.platform == Common::kPlatformFMTowns && s.getVersion() >= VER(82)) { warning("Save file is missing FM-Towns specific graphic data (game was apparently saved on another platform)"); } #endif if (_shadowPaletteSize) { - s->saveLoadArrayOf(_shadowPalette, _shadowPaletteSize, 1, sleByte); + s.syncBytes(_shadowPalette, _shadowPaletteSize); // _roomPalette didn't show up until V21 save games // Note that we also save the room palette for Indy4 Amiga, since it // is used as palette map there too, but we do so slightly a bit // further down to group it with the other special palettes needed. - if (s->getVersion() >= VER(21) && _game.version < 5) - s->saveLoadArrayOf(_roomPalette, sizeof(_roomPalette), 1, sleByte); + if (s.getVersion() >= VER(21) && _game.version < 5) + s.syncBytes(_roomPalette, sizeof(_roomPalette)); } // PalManip data was not saved before V10 save games - if (s->getVersion() < VER(10)) + if (s.getVersion() < VER(10)) _palManipCounter = 0; if (_palManipCounter) { if (!_palManipPalette) _palManipPalette = (byte *)calloc(0x300, 1); if (!_palManipIntermediatePal) _palManipIntermediatePal = (byte *)calloc(0x600, 1); - s->saveLoadArrayOf(_palManipPalette, 0x300, 1, sleByte); - s->saveLoadArrayOf(_palManipIntermediatePal, 0x600, 1, sleByte); + s.syncBytes(_palManipPalette, 0x300); + s.syncBytes(_palManipIntermediatePal, 0x600); } // darkenPalette was not saved before V53 - if (s->isLoading() && s->getVersion() < VER(53)) { + if (s.isLoading() && s.getVersion() < VER(53)) { memcpy(_darkenPalette, _currentPalette, 768); } // _colorUsedByCycle was not saved before V60 - if (s->isLoading() && s->getVersion() < VER(60)) { + if (s.isLoading() && s.getVersion() < VER(60)) { memset(_colorUsedByCycle, 0, sizeof(_colorUsedByCycle)); } // Indy4 Amiga specific palette tables were not saved before V85 if (_game.platform == Common::kPlatformAmiga && _game.id == GID_INDY4) { - if (s->getVersion() >= 85) { - s->saveLoadArrayOf(_roomPalette, 256, 1, sleByte); - s->saveLoadArrayOf(_verbPalette, 256, 1, sleByte); - s->saveLoadArrayOf(_amigaPalette, 3 * 64, 1, sleByte); + if (s.getVersion() >= 85) { + s.syncBytes(_roomPalette, 256); + s.syncBytes(_verbPalette, 256); + s.syncBytes(_amigaPalette, 3 * 64); // Starting from version 86 we also save the first used color in // the palette beyond the verb palette. For old versions we just // look for it again, which hopefully won't cause any troubles. - if (s->getVersion() >= 86) { - s->saveLoadArrayOf(&_amigaFirstUsedColor, 1, 2, sleUint16); + if (s.getVersion() >= VER(86)) { + s.syncAsUint16LE(_amigaFirstUsedColor); } else { amigaPaletteFindFirstUsedColor(); } @@ -1400,7 +1392,7 @@ void ScummEngine::saveOrLoad(Serializer *s) { // // Save/load more global object state // - s->saveLoadArrayOf(_classData, _numGlobalObjects, sizeof(_classData[0]), sleUint32); + s.syncArray(_classData, _numGlobalObjects, Common::Serializer::Uint32LE); // @@ -1409,40 +1401,40 @@ void ScummEngine::saveOrLoad(Serializer *s) { var120Backup = _scummVars[120]; var98Backup = _scummVars[98]; - if (s->getVersion() > VER(37)) - s->saveLoadArrayOf(_roomVars, _numRoomVariables, sizeof(_roomVars[0]), sleInt32); + s.syncArray(_roomVars, _numRoomVariables, Common::Serializer::Sint32LE, VER(38)); // The variables grew from 16 to 32 bit. - if (s->getVersion() < VER(15)) - s->saveLoadArrayOf(_scummVars, _numVariables, sizeof(_scummVars[0]), sleInt16); + if (s.getVersion() < VER(15)) + s.syncArray(_scummVars, _numVariables, Common::Serializer::Sint16LE); else - s->saveLoadArrayOf(_scummVars, _numVariables, sizeof(_scummVars[0]), sleInt32); + s.syncArray(_scummVars, _numVariables, Common::Serializer::Sint32LE); if (_game.id == GID_TENTACLE) // Maybe misplaced, but that's the main idea _scummVars[120] = var120Backup; if (_game.id == GID_INDY4) _scummVars[98] = var98Backup; - s->saveLoadArrayOf(_bitVars, _numBitVariables >> 3, 1, sleByte); + s.syncBytes(_bitVars, _numBitVariables / 8); // // Save/load a list of the locked objects // - if (s->isSaving()) { + if (s.isSaving()) { + byte endMarker = 0xFF; for (type = rtFirst; type <= rtLast; type = ResType(type + 1)) for (idx = 1; idx < _res->_types[type].size(); idx++) { if (_res->isLocked(type, idx)) { - s->saveByte(type); - s->saveUint16(idx); + s.syncAsByte(type); + s.syncAsUint16LE(idx); } } - s->saveByte(0xFF); + s.syncAsByte(endMarker); } else { uint8 tmp; - while ((tmp = s->loadByte()) != 0xFF) { + while (s.syncAsByte(tmp), tmp != 0xFF) { type = (ResType)tmp; - idx = s->loadUint16(); + s.syncAsUint16LE(idx); _res->lock(type, idx); } } @@ -1451,15 +1443,15 @@ void ScummEngine::saveOrLoad(Serializer *s) { // // Save/load the Audio CD status // - if (s->getVersion() >= VER(24)) { + if (s.getVersion() >= VER(24)) { AudioCDManager::Status info; - if (s->isSaving()) + if (s.isSaving()) info = _system->getAudioCDManager()->getStatus(); - s->saveLoadArrayOf(&info, 1, sizeof(info), audioCDEntries); + syncWithSerializer(s, info); // If we are loading, and the music being loaded was supposed to loop // forever, then resume playing it. This helps a lot when the audio CD // is used to provide ambient music (see bug #788195). - if (s->isLoading() && info.playing && info.numLoops < 0) + if (s.isLoading() && info.playing && info.numLoops < 0) _sound->playCDTrackInternal(info.track, info.numLoops, info.start, info.duration); } @@ -1468,7 +1460,7 @@ void ScummEngine::saveOrLoad(Serializer *s) { // Save/load the iMuse status // if (_imuse && (_saveSound || !_saveTemporaryState)) { - _imuse->save_or_load(s, this); + _imuse->saveLoadWithSerializer(s, this); } @@ -1483,11 +1475,13 @@ void ScummEngine::saveOrLoad(Serializer *s) { // // Save/load the charset renderer state // - if (s->getVersion() >= VER(73)) { + if (s.getVersion() >= VER(73)) { _charset->saveLoadWithSerializer(s); - } else if (s->isLoading()) { - if (s->getVersion() == VER(72)) { - _charset->setCurID(s->loadByte()); + } else if (s.isLoading()) { + if (s.getVersion() == VER(72)) { + byte curId; + s.syncAsByte(curId); + _charset->setCurID(curId); } else { // Before V72, the charset id wasn't saved. This used to cause issues such // as the one described in the bug report #1722153. For these savegames, @@ -1497,57 +1491,45 @@ void ScummEngine::saveOrLoad(Serializer *s) { } } -void ScummEngine_v0::saveOrLoad(Serializer *s) { - ScummEngine_v2::saveOrLoad(s); - - const SaveLoadEntry v0Entrys[] = { - MKLINE(ScummEngine_v0, _currentMode, sleByte, VER(78)), - MKLINE(ScummEngine_v0, _currentLights, sleByte, VER(78)), - MKLINE(ScummEngine_v0, _activeVerb, sleByte, VER(92)), - MKLINE(ScummEngine_v0, _activeObject, sleUint16, VER(92)), - MKLINE(ScummEngine_v0, _activeObject2, sleUint16, VER(92)), - MKLINE(ScummEngine_v0, _cmdVerb, sleByte, VER(92)), - MKLINE(ScummEngine_v0, _cmdObject, sleUint16, VER(92)), - MKLINE(ScummEngine_v0, _cmdObject2, sleUint16, VER(92)), - MKLINE(ScummEngine_v0, _walkToObject, sleUint16, VER(92)), - MKLINE(ScummEngine_v0, _walkToObjectState, sleByte, VER(92)), - MKEND() - }; - s->saveLoadEntries(this, v0Entrys); +void ScummEngine_v0::saveLoadWithSerializer(Common::Serializer &s) { + ScummEngine_v2::saveLoadWithSerializer(s); + + s.syncAsByte(_currentMode, VER(78)); + s.syncAsByte(_currentLights, VER(78)); + s.syncAsByte(_activeVerb, VER(92)); + s.syncAsUint16LE(_activeObject, VER(92)); + s.syncAsUint16LE(_activeObject2, VER(92)); + s.syncAsByte(_cmdVerb, VER(92)); + s.syncAsUint16LE(_cmdObject, VER(92)); + s.syncAsUint16LE(_cmdObject2, VER(92)); + s.syncAsUint16LE(_walkToObject, VER(92)); + s.syncAsByte(_walkToObjectState, VER(92)); } -void ScummEngine_v2::saveOrLoad(Serializer *s) { - ScummEngine::saveOrLoad(s); +void ScummEngine_v2::saveLoadWithSerializer(Common::Serializer &s) { + ScummEngine::saveLoadWithSerializer(s); - const SaveLoadEntry v2Entrys[] = { - MKLINE(ScummEngine_v2, _inventoryOffset, sleUint16, VER(79)), - MKEND() - }; - s->saveLoadEntries(this, v2Entrys); + s.syncAsUint16LE(_inventoryOffset, VER(79)); // In old saves we didn't store _inventoryOffset -> reset it to // a sane default when loading one of those. - if (s->getVersion() < 79 && s->isLoading()) { + if (s.getVersion() < VER(79) && s.isLoading()) { _inventoryOffset = 0; } } -void ScummEngine_v5::saveOrLoad(Serializer *s) { - ScummEngine::saveOrLoad(s); - - const SaveLoadEntry cursorEntries[] = { - MKARRAY2(ScummEngine_v5, _cursorImages[0][0], sleUint16, 16, 4, (byte *)_cursorImages[1] - (byte *)_cursorImages[0], VER(44)), - MKARRAY(ScummEngine_v5, _cursorHotspots[0], sleByte, 8, VER(44)), - MKEND() - }; +void ScummEngine_v5::saveLoadWithSerializer(Common::Serializer &s) { + ScummEngine::saveLoadWithSerializer(s); // This is probably only needed for Loom. - s->saveLoadEntries(this, cursorEntries); + // TODO: This looks wrong, _cursorImages is [4][17] + sync2DArray(s, _cursorImages, 4, 16, Common::Serializer::Uint16LE, VER(44)); + s.syncBytes(_cursorHotspots, 8, VER(44)); // Reset cursors for old FM-Towns savegames saved with 256 color setting. // Otherwise the cursor will be messed up when displayed in the new hi color setting. - if (_game.platform == Common::kPlatformFMTowns && _outputPixelFormat.bytesPerPixel == 2 && s->isLoading() && s->getVersion() < VER(82)) { + if (_game.platform == Common::kPlatformFMTowns && _outputPixelFormat.bytesPerPixel == 2 && s.isLoading() && s.getVersion() < VER(82)) { if (_game.id == GID_LOOM) { redefineBuiltinCursorFromChar(1, 1); redefineBuiltinCursorHotspot(1, 0, 0); @@ -1560,7 +1542,7 @@ void ScummEngine_v5::saveOrLoad(Serializer *s) { // This avoids color issues when loading savegames that have been saved with a different ScummVM port // that uses a different 16bit color mode than the ScummVM port which is currently used. #ifdef USE_RGB_COLOR - if (_game.platform == Common::kPlatformPCEngine && s->isLoading()) { + if (_game.platform == Common::kPlatformPCEngine && s.isLoading()) { for (int i = 0; i < 256; ++i) _16BitPalette[i] = get16BitColor(_currentPalette[i * 3 + 0], _currentPalette[i * 3 + 1], _currentPalette[i * 3 + 2]); } @@ -1568,154 +1550,133 @@ void ScummEngine_v5::saveOrLoad(Serializer *s) { } #ifdef ENABLE_SCUMM_7_8 -void ScummEngine_v7::saveOrLoad(Serializer *s) { - ScummEngine::saveOrLoad(s); - - const SaveLoadEntry subtitleQueueEntries[] = { - MKARRAY(SubtitleText, text[0], sleByte, 256, VER(61)), - MKLINE(SubtitleText, charset, sleByte, VER(61)), - MKLINE(SubtitleText, color, sleByte, VER(61)), - MKLINE(SubtitleText, xpos, sleInt16, VER(61)), - MKLINE(SubtitleText, ypos, sleInt16, VER(61)), - MKLINE(SubtitleText, actorSpeechMsg, sleByte, VER(61)), - MKEND() - }; - - const SaveLoadEntry V7Entries[] = { - MKLINE(ScummEngine_v7, _subtitleQueuePos, sleInt32, VER(61)), - MK_OBSOLETE(ScummEngine_v7, _verbCharset, sleInt32, VER(68), VER(68)), - MKLINE(ScummEngine_v7, _verbLineSpacing, sleInt32, VER(68)), - MKEND() - }; - - _imuseDigital->saveOrLoad(s); - - s->saveLoadArrayOf(_subtitleQueue, ARRAYSIZE(_subtitleQueue), sizeof(_subtitleQueue[0]), subtitleQueueEntries); - s->saveLoadEntries(this, V7Entries); - - if (s->getVersion() <= VER(68) && s->isLoading()) { +void syncWithSerializer(Common::Serializer &s, ScummEngine_v7::SubtitleText &st) { + s.syncBytes(st.text, 256, VER(61)); + s.syncAsByte(st.charset, VER(61)); + s.syncAsByte(st.color, VER(61)); + s.syncAsSint16LE(st.xpos, VER(61)); + s.syncAsSint16LE(st.ypos, VER(61)); + s.syncAsByte(st.actorSpeechMsg, VER(61)); +} + +void ScummEngine_v7::saveLoadWithSerializer(Common::Serializer &s) { + ScummEngine::saveLoadWithSerializer(s); + + _imuseDigital->saveLoadEarly(s); + + s.syncArray(_subtitleQueue, ARRAYSIZE(_subtitleQueue), syncWithSerializer); + s.syncAsSint32LE(_subtitleQueuePos, VER(61)); + s.skip(4, VER(68), VER(68)); // _verbCharset + s.syncAsSint32LE(_verbLineSpacing, VER(68)); + + if (s.getVersion() <= VER(68) && s.isLoading()) { // WORKAROUND bug #1846049: Reset the default charset color to a sane value. _string[0]._default.charset = 1; } } #endif -void ScummEngine_v60he::saveOrLoad(Serializer *s) { - ScummEngine::saveOrLoad(s); +void ScummEngine_v60he::saveLoadWithSerializer(Common::Serializer &s) { + ScummEngine::saveLoadWithSerializer(s); - s->saveLoadArrayOf(_arraySlot, _numArray, sizeof(_arraySlot[0]), sleByte); + s.syncBytes(_arraySlot, _numArray); } -void ScummEngine_v70he::saveOrLoad(Serializer *s) { - ScummEngine_v60he::saveOrLoad(s); - - const SaveLoadEntry HE70Entries[] = { - MKLINE(ScummEngine_v70he, _heSndSoundId, sleInt32, VER(51)), - MKLINE(ScummEngine_v70he, _heSndOffset, sleInt32, VER(51)), - MKLINE(ScummEngine_v70he, _heSndChannel, sleInt32, VER(51)), - MKLINE(ScummEngine_v70he, _heSndFlags, sleInt32, VER(51)), - MKEND() - }; +void ScummEngine_v70he::saveLoadWithSerializer(Common::Serializer &s) { + ScummEngine_v60he::saveLoadWithSerializer(s); - s->saveLoadEntries(this, HE70Entries); + s.syncAsSint32LE(_heSndSoundId, VER(51)); + s.syncAsSint32LE(_heSndOffset, VER(51)); + s.syncAsSint32LE(_heSndChannel, VER(51)); + s.syncAsSint32LE(_heSndFlags, VER(51)); } #ifdef ENABLE_HE -void ScummEngine_v71he::saveOrLoad(Serializer *s) { - ScummEngine_v70he::saveOrLoad(s); - - const SaveLoadEntry polygonEntries[] = { - MKLINE(WizPolygon, vert[0].x, sleInt16, VER(40)), - MKLINE(WizPolygon, vert[0].y, sleInt16, VER(40)), - MKLINE(WizPolygon, vert[1].x, sleInt16, VER(40)), - MKLINE(WizPolygon, vert[1].y, sleInt16, VER(40)), - MKLINE(WizPolygon, vert[2].x, sleInt16, VER(40)), - MKLINE(WizPolygon, vert[2].y, sleInt16, VER(40)), - MKLINE(WizPolygon, vert[3].x, sleInt16, VER(40)), - MKLINE(WizPolygon, vert[3].y, sleInt16, VER(40)), - MKLINE(WizPolygon, vert[4].x, sleInt16, VER(40)), - MKLINE(WizPolygon, vert[4].y, sleInt16, VER(40)), - MKLINE(WizPolygon, bound.left, sleInt16, VER(40)), - MKLINE(WizPolygon, bound.top, sleInt16, VER(40)), - MKLINE(WizPolygon, bound.right, sleInt16, VER(40)), - MKLINE(WizPolygon, bound.bottom, sleInt16, VER(40)), - MKLINE(WizPolygon, id, sleInt16, VER(40)), - MKLINE(WizPolygon, numVerts, sleInt16, VER(40)), - MKLINE(WizPolygon, flag, sleByte, VER(40)), - MKEND() - }; - - s->saveLoadArrayOf(_wiz->_polygons, ARRAYSIZE(_wiz->_polygons), sizeof(_wiz->_polygons[0]), polygonEntries); +static void syncWithSerializer(Common::Serializer &s, WizPolygon &wp) { + s.syncAsSint16LE(wp.vert[0].x, VER(40)); + s.syncAsSint16LE(wp.vert[0].y, VER(40)); + s.syncAsSint16LE(wp.vert[1].x, VER(40)); + s.syncAsSint16LE(wp.vert[1].y, VER(40)); + s.syncAsSint16LE(wp.vert[2].x, VER(40)); + s.syncAsSint16LE(wp.vert[2].y, VER(40)); + s.syncAsSint16LE(wp.vert[3].x, VER(40)); + s.syncAsSint16LE(wp.vert[3].y, VER(40)); + s.syncAsSint16LE(wp.vert[4].x, VER(40)); + s.syncAsSint16LE(wp.vert[4].y, VER(40)); + s.syncAsSint16LE(wp.bound.left, VER(40)); + s.syncAsSint16LE(wp.bound.top, VER(40)); + s.syncAsSint16LE(wp.bound.right, VER(40)); + s.syncAsSint16LE(wp.bound.bottom, VER(40)); + s.syncAsSint16LE(wp.id, VER(40)); + s.syncAsSint16LE(wp.numVerts, VER(40)); + s.syncAsByte(wp.flag, VER(40)); } -void ScummEngine_v90he::saveOrLoad(Serializer *s) { - ScummEngine_v71he::saveOrLoad(s); - - const SaveLoadEntry floodFillEntries[] = { - MKLINE(FloodFillParameters, box.left, sleInt32, VER(51)), - MKLINE(FloodFillParameters, box.top, sleInt32, VER(51)), - MKLINE(FloodFillParameters, box.right, sleInt32, VER(51)), - MKLINE(FloodFillParameters, box.bottom, sleInt32, VER(51)), - MKLINE(FloodFillParameters, x, sleInt32, VER(51)), - MKLINE(FloodFillParameters, y, sleInt32, VER(51)), - MKLINE(FloodFillParameters, flags, sleInt32, VER(51)), - MK_OBSOLETE(FloodFillParameters, unk1C, sleInt32, VER(51), VER(62)), - MKEND() - }; - - const SaveLoadEntry HE90Entries[] = { - MKLINE(ScummEngine_v90he, _curMaxSpriteId, sleInt32, VER(51)), - MKLINE(ScummEngine_v90he, _curSpriteId, sleInt32, VER(51)), - MKLINE(ScummEngine_v90he, _curSpriteGroupId, sleInt32, VER(51)), - MK_OBSOLETE(ScummEngine_v90he, _numSpritesToProcess, sleInt32, VER(51), VER(63)), - MKLINE(ScummEngine_v90he, _heObject, sleInt32, VER(51)), - MKLINE(ScummEngine_v90he, _heObjectNum, sleInt32, VER(51)), - MKLINE(ScummEngine_v90he, _hePaletteNum, sleInt32, VER(51)), - MKEND() - }; - - _sprite->saveOrLoadSpriteData(s); - - s->saveLoadArrayOf(&_floodFillParams, 1, sizeof(_floodFillParams), floodFillEntries); - - s->saveLoadEntries(this, HE90Entries); +void ScummEngine_v71he::saveLoadWithSerializer(Common::Serializer &s) { + ScummEngine_v70he::saveLoadWithSerializer(s); + + s.syncArray(_wiz->_polygons, ARRAYSIZE(_wiz->_polygons), syncWithSerializer); } -void ScummEngine_v99he::saveOrLoad(Serializer *s) { - ScummEngine_v90he::saveOrLoad(s); +void syncWithSerializer(Common::Serializer &s, FloodFillParameters &ffp) { + s.syncAsSint32LE(ffp.box.left, VER(51)); + s.syncAsSint32LE(ffp.box.top, VER(51)); + s.syncAsSint32LE(ffp.box.right, VER(51)); + s.syncAsSint32LE(ffp.box.bottom, VER(51)); + s.syncAsSint32LE(ffp.x, VER(51)); + s.syncAsSint32LE(ffp.y, VER(51)); + s.syncAsSint32LE(ffp.flags, VER(51)); + s.skip(4, VER(51), VER(62)); // unk1C +} + +void ScummEngine_v90he::saveLoadWithSerializer(Common::Serializer &s) { + ScummEngine_v71he::saveLoadWithSerializer(s); + + _sprite->saveLoadWithSerializer(s); + + syncWithSerializer(s, _floodFillParams); - s->saveLoadArrayOf(_hePalettes, (_numPalettes + 1) * _hePaletteSlot, sizeof(_hePalettes[0]), sleUint8); + s.syncAsSint32LE(_curMaxSpriteId, VER(51)); + s.syncAsSint32LE(_curSpriteId, VER(51)); + s.syncAsSint32LE(_curSpriteGroupId, VER(51)); + s.skip(4, VER(51), VER(63)); // _numSpritesToProcess + s.syncAsSint32LE(_heObject, VER(51)); + s.syncAsSint32LE(_heObjectNum, VER(51)); + s.syncAsSint32LE(_hePaletteNum, VER(51)); } -void ScummEngine_v100he::saveOrLoad(Serializer *s) { - ScummEngine_v99he::saveOrLoad(s); +void ScummEngine_v99he::saveLoadWithSerializer(Common::Serializer &s) { + ScummEngine_v90he::saveLoadWithSerializer(s); - const SaveLoadEntry HE100Entries[] = { - MKLINE(ScummEngine_v100he, _heResId, sleInt32, VER(51)), - MKLINE(ScummEngine_v100he, _heResType, sleInt32, VER(51)), - MKEND() - }; + s.syncBytes(_hePalettes, (_numPalettes + 1) * _hePaletteSlot); +} + +void ScummEngine_v100he::saveLoadWithSerializer(Common::Serializer &s) { + ScummEngine_v99he::saveLoadWithSerializer(s); - s->saveLoadEntries(this, HE100Entries); + s.syncAsSint32LE(_heResId, VER(51)); + s.syncAsSint32LE(_heResType, VER(51)); } #endif -void ScummEngine::loadResourceOLD(Serializer *ser, ResType type, ResId idx) { +void ScummEngine::loadResourceOLD(Common::Serializer &ser, ResType type, ResId idx) { uint32 size; - if (type == rtSound && ser->getVersion() >= VER(23)) { + if (type == rtSound && ser.getVersion() >= VER(23)) { // Save/load only a list of resource numbers that need to be reloaded. - if (ser->loadUint16()) + uint16 tmp; + ser.syncAsUint16LE(tmp); + if (tmp) ensureResourceLoaded(rtSound, idx); } else if (_res->_types[type]._mode == kDynamicResTypeMode) { - size = ser->loadUint32(); + ser.syncAsUint32LE(size); if (size) { _res->createResource(type, idx, size); - ser->loadBytes(getResourceAddress(type, idx), size); + ser.syncBytes(getResourceAddress(type, idx), size); if (type == rtInventory) { - _inventory[idx] = ser->loadUint16(); + ser.syncAsUint16LE(_inventory[idx]); } - if (type == rtObjectName && ser->getVersion() >= VER(25)) { + if (type == rtObjectName && ser.getVersion() >= VER(25)) { // Paranoia: We increased the possible number of new names // to fix bugs #933610 and #936323. The savegame format // didn't change, but at least during the transition @@ -1723,38 +1684,39 @@ void ScummEngine::loadResourceOLD(Serializer *ser, ResType type, ResId idx) { // more names than we have allocated space for. If so, // discard them. if (idx < _numNewNames) - _newNames[idx] = ser->loadUint16(); + ser.syncAsUint16LE(_newNames[idx]); } } } } -void ScummEngine::saveResource(Serializer *ser, ResType type, ResId idx) { +void ScummEngine::saveResource(Common::Serializer &ser, ResType type, ResId idx) { assert(_res->_types[type][idx]._address); if (_res->_types[type]._mode == kDynamicResTypeMode) { byte *ptr = _res->_types[type][idx]._address; uint32 size = _res->_types[type][idx]._size; - ser->saveUint32(size); - ser->saveBytes(ptr, size); + ser.syncAsUint32LE(size); + ser.syncBytes(ptr, size); if (type == rtInventory) { - ser->saveUint16(_inventory[idx]); + ser.syncAsUint16LE(_inventory[idx]); } if (type == rtObjectName) { - ser->saveUint16(_newNames[idx]); + ser.syncAsUint16LE(_newNames[idx]); } } } -void ScummEngine::loadResource(Serializer *ser, ResType type, ResId idx) { - if (_game.heversion >= 60 && ser->getVersion() <= VER(65) && +void ScummEngine::loadResource(Common::Serializer &ser, ResType type, ResId idx) { + if (_game.heversion >= 60 && ser.getVersion() <= VER(65) && ((type == rtSound && idx == 1) || (type == rtSpoolBuffer))) { - uint32 size = ser->loadUint32(); + uint32 size; + ser.syncAsUint32LE(size); assert(size); _res->createResource(type, idx, size); - ser->loadBytes(getResourceAddress(type, idx), size); + ser.syncBytes(getResourceAddress(type, idx), size); } else if (type == rtSound) { // HE Games use sound resource 1 for speech if (_game.heversion >= 60 && idx == 1) @@ -1762,243 +1724,18 @@ void ScummEngine::loadResource(Serializer *ser, ResType type, ResId idx) { ensureResourceLoaded(rtSound, idx); } else if (_res->_types[type]._mode == kDynamicResTypeMode) { - uint32 size = ser->loadUint32(); + uint32 size; + ser.syncAsUint32LE(size); assert(size); byte *ptr = _res->createResource(type, idx, size); - ser->loadBytes(ptr, size); + ser.syncBytes(ptr, size); if (type == rtInventory) { - _inventory[idx] = ser->loadUint16(); + ser.syncAsUint16LE(_inventory[idx]); } if (type == rtObjectName) { - _newNames[idx] = ser->loadUint16(); - } - } -} - -void Serializer::saveBytes(void *b, int len) { - _saveStream->write(b, len); -} - -void Serializer::loadBytes(void *b, int len) { - _loadStream->read(b, len); -} - -void Serializer::saveUint32(uint32 d) { - _saveStream->writeUint32LE(d); -} - -void Serializer::saveUint16(uint16 d) { - _saveStream->writeUint16LE(d); -} - -void Serializer::saveByte(byte b) { - _saveStream->writeByte(b); -} - -uint32 Serializer::loadUint32() { - return _loadStream->readUint32LE(); -} - -uint16 Serializer::loadUint16() { - return _loadStream->readUint16LE(); -} - -byte Serializer::loadByte() { - return _loadStream->readByte(); -} - -void Serializer::saveArrayOf(void *b, int len, int datasize, byte filetype) { - byte *at = (byte *)b; - uint32 data; - - // speed up byte arrays - if (datasize == 1 && filetype == sleByte) { - if (len > 0) { - saveBytes(b, len); - } - return; - } - - while (--len >= 0) { - if (datasize == 0) { - // Do nothing for obsolete data - data = 0; - } else if (datasize == 1) { - data = *(byte *)at; - at += 1; - } else if (datasize == 2) { - data = *(uint16 *)at; - at += 2; - } else if (datasize == 4) { - data = *(uint32 *)at; - at += 4; - } else { - error("saveArrayOf: invalid size %d", datasize); - } - switch (filetype) { - case sleByte: - saveByte((byte)data); - break; - case sleUint16: - case sleInt16: - saveUint16((int16)data); - break; - case sleInt32: - case sleUint32: - saveUint32(data); - break; - default: - error("saveArrayOf: invalid filetype %d", filetype); - } - } -} - -void Serializer::loadArrayOf(void *b, int len, int datasize, byte filetype) { - byte *at = (byte *)b; - uint32 data; - - // speed up byte arrays - if (datasize == 1 && filetype == sleByte) { - loadBytes(b, len); - return; - } - - while (--len >= 0) { - switch (filetype) { - case sleByte: - data = loadByte(); - break; - case sleUint16: - data = loadUint16(); - break; - case sleInt16: - data = (int16)loadUint16(); - break; - case sleUint32: - data = loadUint32(); - break; - case sleInt32: - data = (int32)loadUint32(); - break; - default: - error("loadArrayOf: invalid filetype %d", filetype); - } - if (datasize == 0) { - // Do nothing for obsolete data - } else if (datasize == 1) { - *(byte *)at = (byte)data; - at += 1; - } else if (datasize == 2) { - *(uint16 *)at = (uint16)data; - at += 2; - } else if (datasize == 4) { - *(uint32 *)at = data; - at += 4; - } else { - error("loadArrayOf: invalid size %d", datasize); - } - } -} - -void Serializer::saveLoadArrayOf(void *b, int num, int datasize, const SaveLoadEntry *sle) { - byte *data = (byte *)b; - - if (isSaving()) { - while (--num >= 0) { - saveEntries(data, sle); - data += datasize; - } - } else { - while (--num >= 0) { - loadEntries(data, sle); - data += datasize; - } - } -} - -void Serializer::saveLoadArrayOf(void *b, int len, int datasize, byte filetype) { - if (isSaving()) - saveArrayOf(b, len, datasize, filetype); - else - loadArrayOf(b, len, datasize, filetype); -} - -void Serializer::saveLoadEntries(void *d, const SaveLoadEntry *sle) { - if (isSaving()) - saveEntries(d, sle); - else - loadEntries(d, sle); -} - -void Serializer::saveEntries(void *d, const SaveLoadEntry *sle) { - byte type; - byte *at; - int size; - - while (sle->offs != 0xFFFF) { - at = (byte *)d + sle->offs; - size = sle->size; - type = (byte) sle->type; - - if (sle->maxVersion != CURRENT_VER) { - // Skip obsolete entries - if (type & 128) - sle++; - } else { - // save entry - int columns = 1; - int rows = 1; - int rowlen = 0; - if (type & 128) { - sle++; - columns = sle->offs; - rows = sle->type; - rowlen = sle->size; - type &= ~128; - } - while (rows--) { - saveArrayOf(at, columns, size, type); - at += rowlen; - } - } - sle++; - } -} - -void Serializer::loadEntries(void *d, const SaveLoadEntry *sle) { - byte type; - byte *at; - int size; - - while (sle->offs != 0xFFFF) { - at = (byte *)d + sle->offs; - size = sle->size; - type = (byte) sle->type; - - if (_savegameVersion < sle->minVersion || _savegameVersion > sle->maxVersion) { - // Skip entries which are not present in this save game version - if (type & 128) - sle++; - } else { - // load entry - int columns = 1; - int rows = 1; - int rowlen = 0; - - if (type & 128) { - sle++; - columns = sle->offs; - rows = sle->type; - rowlen = sle->size; - type &= ~128; - } - while (rows--) { - loadArrayOf(at, columns, size, type); - at += rowlen; - } + ser.syncAsUint16LE(_newNames[idx]); } - sle++; } } diff --git a/engines/scumm/saveload.h b/engines/scumm/saveload.h index fb2d45df8c..a0f45a32fc 100644 --- a/engines/scumm/saveload.h +++ b/engines/scumm/saveload.h @@ -24,16 +24,10 @@ #define SCUMM_SAVELOAD_H #include "common/scummsys.h" -#include // for ptrdiff_t - -namespace Common { -class SeekableReadStream; -class WriteStream; -} +#include "common/serializer.h" namespace Scumm { - /** * The current savegame format version. * Our save/load system uses an elaborate scheme to allow us to modify the @@ -54,117 +48,7 @@ namespace Scumm { * of just writing the raw version, because this way they stand out more to * the reading eye, making it a bit easier to navigate through the code. */ -#define VER(x) x - - -/** - * The OFFS macro essentially provides the functionality of offsetof(), that - * is, it determines the offset of a struct/class member within instances of - * that class. - * - * This is a place where we cheat a bit and sacrifice some potential portability - * (although so far we haven't encountered any platform where this matters). - * - * To work around a warning in GCC 3.2 (and 3.1 ?) regarding non-POD types, - * we use a small trick: instead of 0 we use 42. Why? Well, it seems newer GCC - * versions have a heuristic built in to detect "offset-of" patterns - which is exactly - * what our OFFS macro does. Now, for non-POD types this is not really legal, because - * member need not be at a fixed offset relative to the variable, even if they are in - * current reality (many of our complex structs are non-POD; for an explanation of - * what POD means refer to or - * to ) - */ -#define OFFS(type,item) ((uint32)(((ptrdiff_t)(&((type *)42)->type::item))-42)) - -/** - * Similar to the OFFS macro, this macro computes the size (in bytes) of a - * member of a given struct/class type. - */ -#define SIZE(type,item) sizeof(((type *)42)->type::item) - -// Any item that is still in use automatically gets a maxVersion equal to CURRENT_VER -#define MKLINE(type,item,saveas,minVer) {OFFS(type,item),saveas,SIZE(type,item),minVer,CURRENT_VER} -#define MKARRAY(type,item,saveas,dim,minVer) {OFFS(type,item),128|saveas,SIZE(type,item),minVer,CURRENT_VER}, {(uint32)(dim),1,0,0,0} -#define MKARRAY2(type,item,saveas,dim,dim2,rowlen,minVer) {OFFS(type,item),128|saveas,SIZE(type,item),minVer,CURRENT_VER}, {(uint32)(dim),(uint32)(dim2),(uint16)(rowlen),0,0} - -// Use this if you have an entry that used to be smaller: -#define MKLINE_OLD(type,item,saveas,minVer,maxVer) {OFFS(type,item),saveas,SIZE(type,item),minVer,maxVer} -#define MKARRAY_OLD(type,item,saveas,dim,minVer,maxVer) {OFFS(type,item),128|saveas,SIZE(type,item),minVer,maxVer}, {(uint32)(dim),1,0,0,0} -#define MKARRAY2_OLD(type,item,saveas,dim,dim2,rowlen,minVer,maxVer) {OFFS(type,item),128|saveas,SIZE(type,item),minVer,maxVer}, {(uint32)(dim),(uint32)(dim2),(uint16)(rowlen),0,0} - -// An obsolete item/array, to be ignored upon load. We retain the type/item params to make it easier to debug. -// Obsolete items have size == 0. -#define MK_OBSOLETE(type,item,saveas,minVer,maxVer) {0,saveas,0,minVer,maxVer} -#define MK_OBSOLETE_ARRAY(type,item,saveas,dim,minVer,maxVer) {0,128|saveas,0,minVer,maxVer}, {(uint32)(dim),1,0,0,0} -#define MK_OBSOLETE_ARRAY2(type,item,saveas,dim,dim2,rowlen,minVer,maxVer) {0,128|saveas,0,minVer,maxVer}, {(uint32)(dim),(uint32)(dim2),(uint16)(rowlen),0,0} - -// End marker -#define MKEND() {0xFFFF,0xFF,0xFF,0,0} - - -enum { - sleByte = 1, - sleUint8 = 1, - sleInt8 = 1, - sleInt16 = 2, - sleUint16 = 3, - sleInt32 = 4, - sleUint32 = 5 -}; - -struct SaveLoadEntry { - uint32 offs; // or: array dimension - uint16 type; // or: array dimension 2 - uint16 size; // or: array row length - uint8 minVersion; - uint8 maxVersion; -}; - -class Serializer { -public: - Serializer(Common::SeekableReadStream *in, Common::WriteStream *out, uint32 savegameVersion) - : _loadStream(in), _saveStream(out), - _savegameVersion(savegameVersion) - { } - - void saveLoadArrayOf(void *b, int len, int datasize, byte filetype); - void saveLoadArrayOf(void *b, int num, int datasize, const SaveLoadEntry *sle); - void saveLoadEntries(void *d, const SaveLoadEntry *sle); - - bool isSaving() { return (_saveStream != 0); } - bool isLoading() { return (_loadStream != 0); } - uint32 getVersion() { return _savegameVersion; } - - void saveUint32(uint32 d); - void saveUint16(uint16 d); - void saveByte(byte b); - - byte loadByte(); - uint16 loadUint16(); - uint32 loadUint32(); - - void saveBytes(void *b, int len); - void loadBytes(void *b, int len); - -protected: - Common::SeekableReadStream *_loadStream; - Common::WriteStream *_saveStream; - uint32 _savegameVersion; - - void saveArrayOf(void *b, int len, int datasize, byte filetype); - void loadArrayOf(void *b, int len, int datasize, byte filetype); - - void saveEntries(void *d, const SaveLoadEntry *sle); - void loadEntries(void *d, const SaveLoadEntry *sle); -}; - - -// Mixin class / interface. Maybe call it ISerializable or SerializableMixin ? -class Serializable { -public: - virtual ~Serializable() {} - virtual void saveLoadWithSerializer(Serializer *ser) = 0; -}; +#define VER(x) Common::Serializer::Version(x) } // End of namespace Scumm diff --git a/engines/scumm/scumm.h b/engines/scumm/scumm.h index caa1f84704..ad3a3c161a 100644 --- a/engines/scumm/scumm.h +++ b/engines/scumm/scumm.h @@ -33,6 +33,7 @@ #include "common/random.h" #include "common/rect.h" #include "common/rendermode.h" +#include "common/serializer.h" #include "common/str.h" #include "common/textconsole.h" #include "graphics/surface.h" @@ -88,7 +89,6 @@ class MusicEngine; class Player_Towns; class ScummEngine; class ScummDebugger; -class Serializer; class Sound; struct Box; @@ -375,7 +375,7 @@ class ResourceManager; /** * Base class for all SCUMM engines. */ -class ScummEngine : public Engine { +class ScummEngine : public Engine, public Common::Serializable { friend class ScummDebugger; friend class CharsetRenderer; friend class CharsetRendererTownsClassic; @@ -608,10 +608,10 @@ protected: bool saveState(int slot, bool compat, Common::String &fileName); bool loadState(int slot, bool compat); bool loadState(int slot, bool compat, Common::String &fileName); - virtual void saveOrLoad(Serializer *s); - void saveResource(Serializer *ser, ResType type, ResId idx); - void loadResource(Serializer *ser, ResType type, ResId idx); - void loadResourceOLD(Serializer *ser, ResType type, ResId idx); // "Obsolete" + virtual void saveLoadWithSerializer(Common::Serializer &s); + void saveResource(Common::Serializer &ser, ResType type, ResId idx); + void loadResource(Common::Serializer &ser, ResType type, ResId idx); + void loadResourceOLD(Common::Serializer &ser, ResType type, ResId idx); // "Obsolete" virtual Common::SeekableReadStream *openSaveFileForReading(int slot, bool compat, Common::String &fileName); virtual Common::WriteStream *openSaveFileForWriting(int slot, bool compat, Common::String &fileName); @@ -1166,6 +1166,7 @@ protected: int x1, y1, scale1; int x2, y2, scale2; }; + friend void syncWithSerializer(Common::Serializer &, ScaleSlot &); ScaleSlot _scaleSlots[20]; void setScaleSlot(int slot, int x1, int y1, int scale1, int x2, int y2, int scale2); void setBoxScaleSlot(int box, int slot); diff --git a/engines/scumm/scumm_v0.h b/engines/scumm/scumm_v0.h index 5f40940166..dd2142dac5 100644 --- a/engines/scumm/scumm_v0.h +++ b/engines/scumm/scumm_v0.h @@ -86,7 +86,7 @@ protected: virtual void processInput(); - virtual void saveOrLoad(Serializer *s); + virtual void saveLoadWithSerializer(Common::Serializer &s); virtual bool objIsActor(int obj); virtual int objToActor(int obj); diff --git a/engines/scumm/scumm_v2.h b/engines/scumm/scumm_v2.h index 2a9e7a96e6..43226b8386 100644 --- a/engines/scumm/scumm_v2.h +++ b/engines/scumm/scumm_v2.h @@ -60,7 +60,7 @@ protected: virtual void resetScummVars(); virtual void decodeParseString(); - virtual void saveOrLoad(Serializer *s); + virtual void saveLoadWithSerializer(Common::Serializer &s); virtual void processKeyboard(Common::KeyState lastKeyHit); diff --git a/engines/scumm/scumm_v5.h b/engines/scumm/scumm_v5.h index 1bd38d68f2..76b6c12e36 100644 --- a/engines/scumm/scumm_v5.h +++ b/engines/scumm/scumm_v5.h @@ -66,7 +66,7 @@ protected: virtual void resetScummVars(); virtual void decodeParseString(); - virtual void saveOrLoad(Serializer *s); + virtual void saveLoadWithSerializer(Common::Serializer &s); virtual void readMAXS(int blockSize); diff --git a/engines/scumm/scumm_v7.h b/engines/scumm/scumm_v7.h index b8830be810..822ef7ca76 100644 --- a/engines/scumm/scumm_v7.h +++ b/engines/scumm/scumm_v7.h @@ -84,6 +84,7 @@ protected: struct SubtitleText : TextObject { bool actorSpeechMsg; }; + friend void syncWithSerializer(Common::Serializer &, SubtitleText &); #endif int _subtitleQueuePos; @@ -111,7 +112,7 @@ protected: virtual void akos_processQueue(); - virtual void saveOrLoad(Serializer *s); + virtual void saveLoadWithSerializer(Common::Serializer &s); virtual void readMAXS(int blockSize); virtual void readGlobalObjects(); diff --git a/engines/scumm/sound.cpp b/engines/scumm/sound.cpp index 599871b0e7..8099dd250a 100644 --- a/engines/scumm/sound.cpp +++ b/engines/scumm/sound.cpp @@ -1116,14 +1116,9 @@ AudioCDManager::Status Sound::getCDStatus() { } } -void Sound::saveLoadWithSerializer(Serializer *ser) { - static const SaveLoadEntry soundEntries[] = { - MKLINE(Sound, _currentCDSound, sleInt16, VER(35)), - MKLINE(Sound, _currentMusic, sleInt16, VER(35)), - MKEND() - }; - - ser->saveLoadEntries(this, soundEntries); +void Sound::saveLoadWithSerializer(Common::Serializer &s) { + s.syncAsSint16LE(_currentCDSound, VER(35)); + s.syncAsSint16LE(_currentMusic, VER(35)); } diff --git a/engines/scumm/sound.h b/engines/scumm/sound.h index bc1e88f76b..440570307d 100644 --- a/engines/scumm/sound.h +++ b/engines/scumm/sound.h @@ -24,6 +24,7 @@ #define SCUMM_SOUND_H #include "common/scummsys.h" +#include "common/serializer.h" #include "common/str.h" #include "audio/mididrv.h" #include "backends/audiocd/audiocd.h" @@ -46,7 +47,7 @@ enum { // TODO: Consider splitting Sound into even more subclasses. // E.g. for v1-v4, v5, v6+, ... -class Sound : public Serializable { +class Sound : public Common::Serializable { public: enum SoundMode { kVOCMode, @@ -132,8 +133,7 @@ public: AudioCDManager::Status getCDStatus(); int getCurrentCDSound() const { return _currentCDSound; } - // Used by the save/load system: - void saveLoadWithSerializer(Serializer *ser); + void saveLoadWithSerializer(Common::Serializer &ser); protected: void setupSfxFile(); -- cgit v1.2.3