SCUMM: Replace UB-triggering serialization code with Common::Serializer

Fixes Trac#10342.
This commit is contained in:
Colin Snover 2017-11-29 00:06:12 -06:00 committed by Eugene Sandulenko
parent 157ee95f64
commit 9916b26383
32 changed files with 1035 additions and 1507 deletions

View File

@ -3437,43 +3437,38 @@ void Actor_v0::actorSetWalkTo() {
}
}
void Actor_v0::saveLoadWithSerializer(Serializer *ser) {
Actor::saveLoadWithSerializer(ser);
void Actor_v0::saveLoadWithSerializer(Common::Serializer &s) {
Actor::saveLoadWithSerializer(s);
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)),
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));
MKARRAY(Actor_v0, _walkboxQueue[0], sleByte, 16, VER(98)),
MKLINE(Actor_v0, _walkboxQueueIndex, sleByte, VER(98)),
MKEND()
};
ser->saveLoadEntries(this, actorEntries);
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);
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));
if (ser->isLoading() && _vm->_game.version <= 2 && ser->getVersion() < VER(70)) {
// 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;

View File

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

View File

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

View File

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

View File

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

View File

@ -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 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 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()
};
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));
}
if (s->getVersion() >= VER(64)) {
s->saveLoadArrayOf(_spriteTable, _varNumSprites + 1, sizeof(_spriteTable[0]), spriteEntries);
s->saveLoadArrayOf(_spriteGroups, _varNumSpriteGroups + 1, sizeof(_spriteGroups[0]), spriteGroupEntries);
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

View File

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

View File

@ -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()
};
static void syncWithSerializer(Common::Serializer &s, CommandQueue &cq) {
s.syncArray(cq.array, 8, Common::Serializer::Uint16LE, VER(23));
}
const SaveLoadEntry cmdQueueEntries[] = {
MKARRAY(CommandQueue, array[0], sleUint16, 8, VER(23)),
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));
}
// 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()
};
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 {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -103,61 +103,55 @@ void IMuseDigital::resetState() {
_triggerUsed = false;
}
void IMuseDigital::saveOrLoad(Serializer *ser) {
Common::StackLock lock(_mutex, "IMuseDigital::saveOrLoad()");
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));
}
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()
};
void IMuseDigital::saveLoadEarly(Common::Serializer &s) {
Common::StackLock lock(_mutex, "IMuseDigital::saveLoadEarly()");
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);
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;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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()
};
s.syncAsByte(_eupCurrentSound, VER(81));
s.syncAsByte(_eupLooping, VER(81));
s.syncAsByte(_eupVolLeft, VER(81));
s.syncAsByte(_eupVolRight, VER(81));
ser->saveLoadEntries(this, eupEntries);
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) {

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -24,16 +24,10 @@
#define SCUMM_SAVELOAD_H
#include "common/scummsys.h"
#include <stddef.h> // 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 <http://en.wikipedia.org/wiki/Plain_Old_Data_Structures> or
* to <http://www.informit.com/guides/content.asp?g=cplusplus&seqNum=32&rl=1>)
*/
#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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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