aboutsummaryrefslogtreecommitdiff
path: root/engines/gob
diff options
context:
space:
mode:
authorVicent Marti2008-06-14 14:44:29 +0000
committerVicent Marti2008-06-14 14:44:29 +0000
commitd0b27cf9c66b9281899acf826cb205e19dcb7260 (patch)
tree74e813b1d1f081f35f41ca7a95da5d048951b9e7 /engines/gob
parentd51a0cab3fe494698f001d81d5d86cea7cd0395b (diff)
parent91d3ea31359950b59ee46af8355cc0f5790257e5 (diff)
downloadscummvm-rg350-d0b27cf9c66b9281899acf826cb205e19dcb7260.tar.gz
scummvm-rg350-d0b27cf9c66b9281899acf826cb205e19dcb7260.tar.bz2
scummvm-rg350-d0b27cf9c66b9281899acf826cb205e19dcb7260.zip
Merged trunk into the GUI branch.
Fixed MSVS9 project files. svn-id: r32702
Diffstat (limited to 'engines/gob')
-rw-r--r--engines/gob/coktelvideo.cpp39
-rw-r--r--engines/gob/coktelvideo.h20
-rw-r--r--engines/gob/dataio.cpp5
-rw-r--r--engines/gob/detection.cpp66
-rw-r--r--engines/gob/draw.cpp1
-rw-r--r--engines/gob/draw_v1.cpp6
-rw-r--r--engines/gob/draw_v2.cpp56
-rw-r--r--engines/gob/driver_vga.cpp20
-rw-r--r--engines/gob/game.cpp51
-rw-r--r--engines/gob/game.h13
-rw-r--r--engines/gob/game_v1.cpp25
-rw-r--r--engines/gob/game_v2.cpp39
-rw-r--r--engines/gob/global.cpp2
-rw-r--r--engines/gob/global.h64
-rw-r--r--engines/gob/gob.cpp96
-rw-r--r--engines/gob/gob.h97
-rw-r--r--engines/gob/goblin.cpp19
-rw-r--r--engines/gob/goblin.h2
-rw-r--r--engines/gob/goblin_v1.cpp13
-rw-r--r--engines/gob/goblin_v2.cpp2
-rw-r--r--engines/gob/goblin_v4.cpp1
-rw-r--r--engines/gob/init.cpp28
-rw-r--r--engines/gob/init_v1.cpp1
-rw-r--r--engines/gob/init_v2.cpp5
-rw-r--r--engines/gob/inter.cpp27
-rw-r--r--engines/gob/inter.h11
-rw-r--r--engines/gob/inter_bargon.cpp17
-rw-r--r--engines/gob/inter_v1.cpp104
-rw-r--r--engines/gob/inter_v2.cpp254
-rw-r--r--engines/gob/inter_v4.cpp120
-rw-r--r--engines/gob/map.cpp2
-rw-r--r--engines/gob/map_v1.cpp7
-rw-r--r--engines/gob/map_v2.cpp14
-rw-r--r--engines/gob/map_v4.cpp15
-rw-r--r--engines/gob/module.mk16
-rw-r--r--engines/gob/mult.cpp25
-rw-r--r--engines/gob/mult.h4
-rw-r--r--engines/gob/mult_v1.cpp1
-rw-r--r--engines/gob/mult_v2.cpp125
-rw-r--r--engines/gob/parse.cpp5
-rw-r--r--engines/gob/parse_v1.cpp7
-rw-r--r--engines/gob/parse_v2.cpp7
-rw-r--r--engines/gob/saveload.cpp917
-rw-r--r--engines/gob/saveload.h427
-rw-r--r--engines/gob/saveload_v2.cpp403
-rw-r--r--engines/gob/saveload_v3.cpp682
-rw-r--r--engines/gob/saveload_v4.cpp439
-rw-r--r--engines/gob/scenery.cpp185
-rw-r--r--engines/gob/scenery.h27
-rw-r--r--engines/gob/scenery_v1.cpp9
-rw-r--r--engines/gob/scenery_v2.cpp1
-rw-r--r--engines/gob/sound.cpp374
-rw-r--r--engines/gob/sound.h172
-rw-r--r--engines/gob/sound/adlib.cpp (renamed from engines/gob/music.cpp)130
-rw-r--r--engines/gob/sound/adlib.h (renamed from engines/gob/music.h)66
-rw-r--r--engines/gob/sound/bgatmosphere.cpp128
-rw-r--r--engines/gob/sound/bgatmosphere.h75
-rw-r--r--engines/gob/sound/cdrom.cpp (renamed from engines/gob/cdrom.cpp)128
-rw-r--r--engines/gob/sound/cdrom.h (renamed from engines/gob/cdrom.h)36
-rw-r--r--engines/gob/sound/infogrames.cpp103
-rw-r--r--engines/gob/sound/infogrames.h60
-rw-r--r--engines/gob/sound/pcspeaker.cpp55
-rw-r--r--engines/gob/sound/pcspeaker.h52
-rw-r--r--engines/gob/sound/sound.cpp582
-rw-r--r--engines/gob/sound/sound.h147
-rw-r--r--engines/gob/sound/soundblaster.cpp126
-rw-r--r--engines/gob/sound/soundblaster.h71
-rw-r--r--engines/gob/sound/sounddesc.cpp116
-rw-r--r--engines/gob/sound/sounddesc.h85
-rw-r--r--engines/gob/sound/soundmixer.cpp204
-rw-r--r--engines/gob/sound/soundmixer.h95
-rw-r--r--engines/gob/util.cpp5
-rw-r--r--engines/gob/variables.cpp311
-rw-r--r--engines/gob/variables.h147
-rw-r--r--engines/gob/video.cpp26
-rw-r--r--engines/gob/video.h12
-rw-r--r--engines/gob/video_v1.cpp1
-rw-r--r--engines/gob/video_v2.cpp1
-rw-r--r--engines/gob/videoplayer.cpp102
-rw-r--r--engines/gob/videoplayer.h6
80 files changed, 5569 insertions, 2369 deletions
diff --git a/engines/gob/coktelvideo.cpp b/engines/gob/coktelvideo.cpp
index d508dc75f9..415790e67b 100644
--- a/engines/gob/coktelvideo.cpp
+++ b/engines/gob/coktelvideo.cpp
@@ -123,8 +123,9 @@ bool Imd::load(Common::SeekableReadStream &stream) {
return false;
}
- _soundSliceLength = 1000 / (_soundFreq / _soundSliceSize);
- _frameLength = _soundSliceLength;
+ _soundSliceLength = (uint32) (((double) (1000 << 16)) /
+ ((double) _soundFreq / (double) _soundSliceSize));
+ _frameLength = _soundSliceLength >> 16;
_soundStage = 1;
_hasSound = true;
@@ -270,6 +271,13 @@ void Imd::disableSound() {
_mixer = 0;
}
+bool Imd::isSoundPlaying() const {
+ if (_audioStream && _mixer->isSoundHandleActive(_audioHandle))
+ return true;
+
+ return false;
+}
+
void Imd::seekFrame(int32 frame, int16 whence, bool restart) {
if (!_stream)
// Nothing to do
@@ -318,11 +326,11 @@ void Imd::waitEndFrame() {
return;
if (_skipFrames == 0) {
- int32 waitTime = (_curFrame * _soundSliceLength) -
- (g_system->getMillis() - _soundStartTime);
+ int32 waitTime = (int16) (((_curFrame * _soundSliceLength) -
+ ((g_system->getMillis() - _soundStartTime) << 16)) >> 16);
if (waitTime < 0) {
- _skipFrames = -waitTime / _soundSliceLength;
+ _skipFrames = -waitTime / (_soundSliceLength >> 16);
warning("Video A/V sync broken, skipping %d frame(s)", _skipFrames + 1);
} else if (waitTime > 0)
g_system->delayMillis(waitTime);
@@ -333,6 +341,11 @@ void Imd::waitEndFrame() {
g_system->delayMillis(_frameLength);
}
+void Imd::notifyPaused(uint32 duration) {
+ if (_soundStage == 2)
+ _soundStartTime += duration;
+}
+
void Imd::copyCurrentFrame(byte *dest,
uint16 left, uint16 top, uint16 width, uint16 height,
uint16 x, uint16 y, uint16 pitch, int16 transp) {
@@ -931,10 +944,9 @@ bool Vmd::load(Common::SeekableReadStream &stream) {
_soundSliceSize = -_soundSliceSize;
}
- _soundSliceLength = (uint16) (1000.0 /
+ _soundSliceLength = (uint32) (((double) (1000 << 16)) /
((double) _soundFreq / (double) _soundSliceSize));
-
- _frameLength = _soundSliceLength;
+ _frameLength = _soundSliceLength >> 16;
_soundStage = 1;
_audioStream = Audio::makeAppendableAudioStream(_soundFreq,
@@ -1066,8 +1078,8 @@ CoktelVideo::State Vmd::processFrame(uint16 frame) {
state.flags |= kStateNoVideoData;
state.left = 0x7FFF;
- state.right = 0x7FFF;
- state.top = 0;
+ state.top = 0x7FFF;
+ state.right = 0;
state.bottom = 0;
if (!_vidMem)
@@ -1121,6 +1133,8 @@ CoktelVideo::State Vmd::processFrame(uint16 frame) {
} else if (part.type == kPartTypeVideo) {
state.flags &= ~kStateNoVideoData;
+ uint32 size = part.size;
+
// New palette
if (part.flags & 2) {
uint8 index = _stream->readByte();
@@ -1130,9 +1144,12 @@ CoktelVideo::State Vmd::processFrame(uint16 frame) {
_stream->skip((255 - count) * 3);
state.flags |= kStatePalette;
+
+ size -= (768 + 2);
}
- _stream->read(_frameData, part.size);
+ _stream->read(_frameData, size);
+
if (renderFrame(part.left, part.top, part.right, part.bottom)) {
// Rendering succeeded, merging areas
state.left = MIN(state.left, part.left);
diff --git a/engines/gob/coktelvideo.h b/engines/gob/coktelvideo.h
index 4f9543e8d0..348e5e3ab1 100644
--- a/engines/gob/coktelvideo.h
+++ b/engines/gob/coktelvideo.h
@@ -134,11 +134,14 @@ public:
/** Use an own memory block as video memory. */
virtual void setVideoMemory() = 0;
- /** Play sound (if the IMD has sound). */
+ /** Play sound (if the video has sound). */
virtual void enableSound(Audio::Mixer &mixer) = 0;
/** Don't play sound or stop currently playing sound. */
virtual void disableSound() = 0;
+ /** Is sound currently playing? */
+ virtual bool isSoundPlaying() const = 0;
+
/** Seek to a specific frame.
*
* @param frame The frame to which to seek.
@@ -152,6 +155,9 @@ public:
/** Wait for the frame to end. */
virtual void waitEndFrame() = 0;
+ /** Notifies the video that it was paused for duration ms. */
+ virtual void notifyPaused(uint32 duration) = 0;
+
/** Copy the current frame.
*
* @param dest The memory to which to copy the current frame.
@@ -184,7 +190,11 @@ public:
int16 getHeight() const { return _height; }
uint16 getFramesCount() const { return _framesCount; }
uint16 getCurrentFrame() const { return _curFrame; }
- int16 getFrameRate() const { if (_hasSound) return 1000 / _soundSliceLength; return _frameRate; }
+ int16 getFrameRate() const {
+ if (_hasSound)
+ return 1000 / (_soundSliceLength >> 16);
+ return _frameRate;
+ }
uint32 getSyncLag() const { return _skipFrames; }
const byte *getPalette() const { return _palette; }
@@ -203,11 +213,15 @@ public:
void enableSound(Audio::Mixer &mixer);
void disableSound();
+ bool isSoundPlaying() const;
+
void seekFrame(int32 frame, int16 whence = SEEK_SET, bool restart = false);
State nextFrame();
void waitEndFrame();
+ void notifyPaused(uint32 duration);
+
void copyCurrentFrame(byte *dest,
uint16 left, uint16 top, uint16 width, uint16 height,
uint16 x, uint16 y, uint16 pitch, int16 transp = -1);
@@ -250,7 +264,7 @@ protected:
int16 _soundFreq;
int16 _soundSliceSize;
int16 _soundSlicesCount;
- uint16 _soundSliceLength;
+ uint32 _soundSliceLength;
Audio::AppendableAudioStream *_audioStream;
Audio::SoundHandle _audioHandle;
diff --git a/engines/gob/dataio.cpp b/engines/gob/dataio.cpp
index 1fb43e96bb..8ae11b8755 100644
--- a/engines/gob/dataio.cpp
+++ b/engines/gob/dataio.cpp
@@ -23,7 +23,6 @@
*
*/
-
#include "common/endian.h"
#include "gob/gob.h"
@@ -233,8 +232,10 @@ int16 DataIO::getChunk(const char *chunkName) {
if (_chunkPos[file * MAX_SLOT_COUNT + slot] == -1)
break;
- if (slot == MAX_SLOT_COUNT)
+ if (slot == MAX_SLOT_COUNT) {
+ warning("Chunk slots full");
return -1;
+ }
dataDesc = _dataFiles[file];
for (int16 chunk = 0; chunk < _numDataChunks[file]; chunk++, dataDesc++) {
diff --git a/engines/gob/detection.cpp b/engines/gob/detection.cpp
index 7637605dcd..8351f2ecfb 100644
--- a/engines/gob/detection.cpp
+++ b/engines/gob/detection.cpp
@@ -23,7 +23,6 @@
*
*/
-
#include "base/plugins.h"
#include "common/advancedDetector.h"
@@ -1685,6 +1684,71 @@ static const GOBGameDescription gameDescriptions[] = {
kFeatures640,
"intro"
},
+ { // Supplied by DjDiabolik in bug report #1971294
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "60348a87651f92e8492ee070556a96d8", 7069736),
+ EN_GRB,
+ kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeWoodruff,
+ kFeatures640,
+ "intro"
+ },
+ { // Supplied by DjDiabolik in bug report #1971294
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "60348a87651f92e8492ee070556a96d8", 7069736),
+ DE_DEU,
+ kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeWoodruff,
+ kFeatures640,
+ "intro"
+ },
+ { // Supplied by DjDiabolik in bug report #1971294
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "60348a87651f92e8492ee070556a96d8", 7069736),
+ FR_FRA,
+ kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeWoodruff,
+ kFeatures640,
+ "intro"
+ },
+ { // Supplied by DjDiabolik in bug report #1971294
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "60348a87651f92e8492ee070556a96d8", 7069736),
+ IT_ITA,
+ kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeWoodruff,
+ kFeatures640,
+ "intro"
+ },
+ { // Supplied by DjDiabolik in bug report #1971294
+ {
+ "woodruff",
+ "",
+ AD_ENTRY1s("intro.stk", "60348a87651f92e8492ee070556a96d8", 7069736),
+ ES_ESP,
+ kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ kGameTypeWoodruff,
+ kFeatures640,
+ "intro"
+ },
{
{
"dynasty",
diff --git a/engines/gob/draw.cpp b/engines/gob/draw.cpp
index 2a4732954c..8a7de9bdaa 100644
--- a/engines/gob/draw.cpp
+++ b/engines/gob/draw.cpp
@@ -23,7 +23,6 @@
*
*/
-
#include "common/endian.h"
#include "gob/gob.h"
diff --git a/engines/gob/draw_v1.cpp b/engines/gob/draw_v1.cpp
index 959a064b7d..b5bc56b6f5 100644
--- a/engines/gob/draw_v1.cpp
+++ b/engines/gob/draw_v1.cpp
@@ -23,7 +23,6 @@
*
*/
-
#include "common/endian.h"
#include "graphics/cursorman.h"
@@ -31,9 +30,10 @@
#include "gob/draw.h"
#include "gob/global.h"
#include "gob/util.h"
-#include "gob/cdrom.h"
#include "gob/game.h"
#include "gob/scenery.h"
+#include "gob/inter.h"
+#include "gob/sound/sound.h"
namespace Gob {
@@ -170,7 +170,7 @@ void Draw_v1::printTotText(int16 id) {
int16 spriteRight, spriteBottom;
char buf[20];
- _vm->_cdrom->playMultMusic();
+ _vm->_sound->cdPlayMultMusic();
if (!_vm->_game->_totTextData || !_vm->_game->_totTextData->dataPtr)
return;
diff --git a/engines/gob/draw_v2.cpp b/engines/gob/draw_v2.cpp
index 8f7d5b325b..378ff0dcdf 100644
--- a/engines/gob/draw_v2.cpp
+++ b/engines/gob/draw_v2.cpp
@@ -23,7 +23,6 @@
*
*/
-
#include "common/endian.h"
#include "graphics/cursorman.h"
@@ -33,6 +32,7 @@
#include "gob/util.h"
#include "gob/game.h"
#include "gob/scenery.h"
+#include "gob/inter.h"
#include "gob/video.h"
namespace Gob {
@@ -178,13 +178,13 @@ void Draw_v2::animateCursor(int16 cursor) {
_vm->_util->delay(5);
}
}
- } else
+ } else {
blitCursor();
+ _cursorX = newX;
+ _cursorY = newY;
+ }
_showCursor &= ~1;
-
- _cursorX = newX;
- _cursorY = newY;
}
void Draw_v2::printTotText(int16 id) {
@@ -246,22 +246,29 @@ void Draw_v2::printTotText(int16 id) {
}
if (_renderFlags & RENDERFLAG_FROMSPLIT) {
- destY = _vm->_video->_splitStart;
+ int16 start;
+
+ start = _vm->_video->_splitStart;
+
+ destY = start;
spriteBottom = READ_LE_UINT16(ptr + 6) - READ_LE_UINT16(ptr + 2);
+
if (_renderFlags & RENDERFLAG_DOUBLECOORDS)
spriteBottom *= 3;
- spriteBottom += _vm->_video->_splitStart;
+
+ spriteBottom += start;
+
if (_renderFlags & RENDERFLAG_DOUBLECOORDS) {
- spriteBottom += _backDeltaX;
- destY += _backDeltaX;
+ spriteBottom += _backDeltaY;
+ destY += _backDeltaY;
}
} else {
+ destY = READ_LE_UINT16(ptr + 2);
+ spriteBottom = READ_LE_UINT16(ptr + 6);
+
if (_renderFlags & RENDERFLAG_DOUBLECOORDS) {
- destY = READ_LE_UINT16(ptr + 2) * 2;
- spriteBottom = READ_LE_UINT16(ptr + 6) * 2;
- } else {
- destY = READ_LE_UINT16(ptr + 2);
- spriteBottom = READ_LE_UINT16(ptr + 6);
+ destY *= 2;
+ spriteBottom *= 2;
}
}
@@ -629,8 +636,7 @@ void Draw_v2::spriteOperation(int16 operation) {
_destSpriteX += _backDeltaX;
_destSpriteY += _backDeltaY;
if ((operation == DRAW_DRAWLINE) ||
- ((operation >= DRAW_DRAWBAR) &&
- (operation <= DRAW_FILLRECTABS))) {
+ ((operation >= DRAW_DRAWBAR) && (operation <= DRAW_FILLRECTABS))) {
_spriteRight += _backDeltaX;
_spriteBottom += _backDeltaY;
}
@@ -646,6 +652,24 @@ void Draw_v2::spriteOperation(int16 operation) {
int16 destSurface = _destSurface;
int16 sourceSurface = _sourceSurface;
+ if (_vm->_video->_splitSurf && ((_destSurface == 20) || (_destSurface == 21))) {
+ if ((_destSpriteY >= _vm->_video->_splitStart)) {
+ _destSpriteY -= _vm->_video->_splitStart;
+ if ((operation == DRAW_DRAWLINE) ||
+ ((operation >= DRAW_DRAWBAR) && (operation <= DRAW_FILLRECTABS)))
+ _spriteBottom -= _vm->_video->_splitStart;
+
+ _destSurface += 4;
+ }
+
+ if ((_spriteTop >= _vm->_video->_splitStart) && (operation == DRAW_BLITSURF)) {
+ _spriteTop -= _vm->_video->_splitStart;
+ if (_destSurface < 24)
+ _destSurface += 4;
+ }
+
+ }
+
adjustCoords(0, &_destSpriteX, &_destSpriteY);
if ((operation != DRAW_LOADSPRITE) && (_needAdjust != 2)) {
adjustCoords(0, &_spriteRight, &_spriteBottom);
diff --git a/engines/gob/driver_vga.cpp b/engines/gob/driver_vga.cpp
index 08235f16e2..f68ce47783 100644
--- a/engines/gob/driver_vga.cpp
+++ b/engines/gob/driver_vga.cpp
@@ -23,7 +23,6 @@
*
*/
-
#include "common/endian.h"
#include "graphics/primitives.h"
@@ -110,10 +109,16 @@ void VGAVideoDriver::drawSprite(SurfaceDesc *source, SurfaceDesc *dest,
int16 width = MIN((right - left) + 1, (int) dest->getWidth());
int16 height = MIN((bottom - top) + 1, (int) dest->getHeight());
+ if ((width < 1) || (height < 1))
+ return;
+
byte *srcPos = source->getVidMem() + (top * source->getWidth()) + left;
byte *destPos = dest->getVidMem() + (y * dest->getWidth()) + x;
+ uint32 size = width * height;
+
if (transp) {
+
while (height--) {
for (int16 i = 0; i < width; ++i) {
if (srcPos[i])
@@ -123,13 +128,26 @@ void VGAVideoDriver::drawSprite(SurfaceDesc *source, SurfaceDesc *dest,
srcPos += source->getWidth();
destPos += dest->getWidth();
}
+
+ } else if (((srcPos >= destPos) && (srcPos <= (destPos + size))) ||
+ ((destPos >= srcPos) && (destPos <= (srcPos + size)))) {
+
+ while (height--) {
+ memmove(destPos, srcPos, width);
+
+ srcPos += source->getWidth();
+ destPos += dest->getWidth();
+ }
+
} else {
+
while (height--) {
memcpy(destPos, srcPos, width);
srcPos += source->getWidth();
destPos += dest->getWidth();
}
+
}
}
diff --git a/engines/gob/game.cpp b/engines/gob/game.cpp
index 666f46fde1..73fa820fa0 100644
--- a/engines/gob/game.cpp
+++ b/engines/gob/game.cpp
@@ -23,7 +23,6 @@
*
*/
-
#include "common/endian.h"
#include "gob/gob.h"
@@ -35,7 +34,7 @@
#include "gob/parse.h"
#include "gob/draw.h"
#include "gob/mult.h"
-#include "gob/music.h"
+#include "gob/sound/sound.h"
namespace Gob {
@@ -60,9 +59,6 @@ Game::Game(GobEngine *vm) : _vm(vm) {
_collStackElemSizes[i] = 0;
}
- _infIns = 0;
- _infogrames = 0;
-
_curTotFile[0] = 0;
_curExtFile[0] = 0;
_totToLoad[0] = 0;
@@ -105,10 +101,6 @@ Game::Game(GobEngine *vm) : _vm(vm) {
}
Game::~Game() {
- delete _infIns;
-
- for (int i = 0; i < 60; i++)
- _soundSamples[i].free();
}
byte *Game::loadExtData(int16 itemId, int16 *pResWidth,
@@ -295,16 +287,7 @@ void Game::freeSoundSlot(int16 slot) {
if (slot == -1)
slot = _vm->_parse->parseValExpr();
- if ((slot < 0) || (slot >= 60) || _soundSamples[slot].empty())
- return;
-
- SoundDesc &sample = _soundSamples[slot];
-
- if (sample.getType() == SOUND_ADL)
- if (_vm->_adlib && (_vm->_adlib->getIndex() == slot))
- _vm->_adlib->stopPlay();
-
- _vm->_snd->freeSample(sample);
+ _vm->_sound->sampleFree(_vm->_sound->sampleGetBySlot(slot));
}
void Game::evaluateScroll(int16 x, int16 y) {
@@ -367,7 +350,7 @@ int16 Game::checkKeys(int16 *pMouseX, int16 *pMouseY,
_vm->_util->processInput(true);
- if (_vm->_mult->_multData && _vm->_global->_inter_variables &&
+ if (_vm->_mult->_multData && _vm->_inter->_variables &&
(VAR(58) != 0)) {
if (_vm->_mult->_multData->frameStart != (int) VAR(58) - 1)
_vm->_mult->_multData->frameStart++;
@@ -380,7 +363,7 @@ int16 Game::checkKeys(int16 *pMouseX, int16 *pMouseY,
if ((_vm->_inter->_soundEndTimeKey != 0) &&
(_vm->_util->getTimeKey() >= _vm->_inter->_soundEndTimeKey)) {
- _vm->_snd->stopSound(_vm->_inter->_soundStopVal);
+ _vm->_sound->blasterStop(_vm->_inter->_soundStopVal);
_vm->_inter->_soundEndTimeKey = 0;
}
@@ -497,8 +480,7 @@ void Game::totSub(int8 flags, const char *newTotFile) {
_extTableArray[_backupedCount] = _extTable;
_extHandleArray[_backupedCount] = _extHandle;
_imFileDataArray[_backupedCount] = _imFileData;
- _variablesArray[_backupedCount] = _vm->_global->_inter_variables;
- _variablesSizesArray[_backupedCount] = _vm->_global->_inter_variablesSizes;
+ _variablesArray[_backupedCount] = _vm->_inter->_variables;
strcpy(_curTotFileArray[_backupedCount], _curTotFile);
curBackupPos = _curBackupPos;
@@ -508,10 +490,8 @@ void Game::totSub(int8 flags, const char *newTotFile) {
_totTextData = 0;
_totFileData = 0;
_totResourceTable = 0;
- if (flags & 1) {
- _vm->_global->_inter_variables = 0;
- _vm->_global->_inter_variablesSizes = 0;
- }
+ if (flags & 1)
+ _vm->_inter->_variables = 0;
strncpy0(_curTotFile, newTotFile, 9);
strcat(_curTotFile, ".TOT");
@@ -531,9 +511,8 @@ void Game::totSub(int8 flags, const char *newTotFile) {
popCollisions();
- if ((flags & 1) && _vm->_global->_inter_variables) {
- delete[] _vm->_global->_inter_variables;
- delete[] _vm->_global->_inter_variablesSizes;
+ if ((flags & 1) && _vm->_inter->_variables) {
+ _vm->_inter->delocateVars();
}
_backupedCount--;
@@ -547,8 +526,7 @@ void Game::totSub(int8 flags, const char *newTotFile) {
_extTable = _extTableArray[_backupedCount];
_extHandle = _extHandleArray[_backupedCount];
_imFileData = _imFileDataArray[_backupedCount];
- _vm->_global->_inter_variables = _variablesArray[_backupedCount];
- _vm->_global->_inter_variablesSizes = _variablesSizesArray[_backupedCount];
+ _vm->_inter->_variables = _variablesArray[_backupedCount];
strcpy(_curTotFile, _curTotFileArray[_backupedCount]);
strcpy(_curExtFile, _curTotFile);
_curExtFile[strlen(_curExtFile) - 4] = '\0';
@@ -580,8 +558,7 @@ void Game::switchTotSub(int16 index, int16 skipPlay) {
_extTableArray[_backupedCount] = _extTable;
_extHandleArray[_backupedCount] = _extHandle;
_imFileDataArray[_backupedCount] = _imFileData;
- _variablesArray[_backupedCount] = _vm->_global->_inter_variables;
- _variablesSizesArray[_backupedCount] = _vm->_global->_inter_variablesSizes;
+ _variablesArray[_backupedCount] = _vm->_inter->_variables;
strcpy(_curTotFileArray[_backupedCount], _curTotFile);
_backupedCount++;
}
@@ -597,8 +574,7 @@ void Game::switchTotSub(int16 index, int16 skipPlay) {
_imFileData = _imFileDataArray[_curBackupPos];
_extTable = _extTableArray[_curBackupPos];
_extHandle = _extHandleArray[_curBackupPos];
- _vm->_global->_inter_variables = _variablesArray[_curBackupPos];
- _vm->_global->_inter_variablesSizes = _variablesSizesArray[_curBackupPos];
+ _vm->_inter->_variables = _variablesArray[_curBackupPos];
strcpy(_curTotFile, _curTotFileArray[_curBackupPos]);
strcpy(_curExtFile, _curTotFile);
_curExtFile[strlen(_curExtFile) - 4] = '\0';
@@ -625,8 +601,7 @@ void Game::switchTotSub(int16 index, int16 skipPlay) {
_extTable = _extTableArray[_curBackupPos];
_extHandle = _extHandleArray[_curBackupPos];
_imFileData = _imFileDataArray[_curBackupPos];
- _vm->_global->_inter_variables = _variablesArray[_curBackupPos];
- _vm->_global->_inter_variablesSizes = _variablesSizesArray[_curBackupPos];
+ _vm->_inter->_variables = _variablesArray[_curBackupPos];
strcpy(_curTotFile, _curTotFileArray[_curBackupPos]);
strcpy(_curExtFile, _curTotFile);
_curExtFile[strlen(_curExtFile) - 4] = '\0';
diff --git a/engines/gob/game.h b/engines/gob/game.h
index 5cf5e1bea6..15f6ab963a 100644
--- a/engines/gob/game.h
+++ b/engines/gob/game.h
@@ -26,9 +26,7 @@
#ifndef GOB_GAME_H
#define GOB_GAME_H
-#include "sound/mods/infogrames.h"
-
-#include "gob/sound.h"
+#include "gob/variables.h"
namespace Gob {
@@ -119,12 +117,6 @@ public:
int16 _extHandle;
- SoundDesc _soundSamples[60];
-
- Audio::Infogrames::Instruments *_infIns;
- Audio::Infogrames *_infogrames;
- Audio::SoundHandle _infHandle;
-
char _totToLoad[20];
int32 _startTimeKey;
@@ -210,9 +202,8 @@ protected:
ExtTable *_extTableArray[5];
int16 _extHandleArray[5];
byte *_imFileDataArray[5];
- byte *_variablesArray[5];
+ Variables *_variablesArray[5];
char _curTotFileArray[5][14];
- byte *_variablesSizesArray[5];
GobEngine *_vm;
diff --git a/engines/gob/game_v1.cpp b/engines/gob/game_v1.cpp
index e9e37a027b..66deea8ec4 100644
--- a/engines/gob/game_v1.cpp
+++ b/engines/gob/game_v1.cpp
@@ -23,7 +23,6 @@
*
*/
-
#include "common/endian.h"
#include "common/stream.h"
@@ -32,15 +31,13 @@
#include "gob/global.h"
#include "gob/util.h"
#include "gob/dataio.h"
-#include "gob/music.h"
-#include "gob/cdrom.h"
#include "gob/draw.h"
#include "gob/inter.h"
#include "gob/mult.h"
#include "gob/video.h"
#include "gob/parse.h"
-#include "gob/sound.h"
#include "gob/scenery.h"
+#include "gob/sound/sound.h"
namespace Gob {
@@ -74,11 +71,11 @@ void Game_v1::playTot(int16 skipPlay) {
_vm->_draw->_fontToSprite[i].height = -1;
}
- if (_vm->_platform == Common::kPlatformMacintosh) {
- if (_vm->_adlib)
- _vm->_adlib->stopPlay();
- } else
- _vm->_cdrom->stopPlaying();
+ if (_vm->getPlatform() == Common::kPlatformMacintosh)
+ _vm->_sound->adlibStop();
+ else
+ _vm->_sound->cdStop();
+
_vm->_draw->animateCursor(4);
_vm->_inter->initControlVars(1);
_vm->_mult->initAll();
@@ -169,12 +166,8 @@ void Game_v1::playTot(int16 skipPlay) {
_vm->_global->_inter_animDataSize =
READ_LE_UINT16(_totFileData + 0x38);
- if (!_vm->_global->_inter_variables) {
- variablesCount = READ_LE_UINT16(_totFileData + 0x2C);
- _vm->_global->_inter_variables = new byte[variablesCount * 4];
- _vm->_global->_inter_variablesSizes = new byte[variablesCount * 4];
- _vm->_global->clearVars(variablesCount);
- }
+ if (!_vm->_inter->_variables)
+ _vm->_inter->allocateVars(READ_LE_UINT16(_totFileData + 0x2C));
_vm->_global->_inter_execPtr = _totFileData;
_vm->_global->_inter_execPtr += READ_LE_UINT32(_totFileData + 0x64);
@@ -229,7 +222,7 @@ void Game_v1::playTot(int16 skipPlay) {
for (int i = 0; i < SPRITES_COUNT; i++)
_vm->_draw->freeSprite(i);
- _vm->_snd->stopSound(0);
+ _vm->_sound->blasterStop(0);
for (int i = 0; i < 20; i++)
freeSoundSlot(i);
diff --git a/engines/gob/game_v2.cpp b/engines/gob/game_v2.cpp
index 45542541e3..adf75176ab 100644
--- a/engines/gob/game_v2.cpp
+++ b/engines/gob/game_v2.cpp
@@ -23,7 +23,6 @@
*
*/
-
#include "common/endian.h"
#include "common/stream.h"
@@ -38,9 +37,9 @@
#include "gob/mult.h"
#include "gob/parse.h"
#include "gob/scenery.h"
-#include "gob/sound.h"
#include "gob/video.h"
#include "gob/videoplayer.h"
+#include "gob/sound/sound.h"
namespace Gob {
@@ -55,7 +54,6 @@ void Game_v2::playTot(int16 skipPlay) {
int16 _captureCounter;
int16 breakFrom;
int16 nestLevel;
- int32 variablesCount;
int32 totSize;
byte *filePtr;
byte *savedIP;
@@ -73,7 +71,7 @@ void Game_v2::playTot(int16 skipPlay) {
if (skipPlay <= 0) {
while (!_vm->_quitRequested) {
- if (_vm->_global->_inter_variables)
+ if (_vm->_inter->_variables)
_vm->_draw->animateCursor(4);
if (skipPlay != -1) {
@@ -205,12 +203,8 @@ void Game_v2::playTot(int16 skipPlay) {
_vm->_global->_inter_animDataSize =
READ_LE_UINT16(_totFileData + 0x38);
- if (!_vm->_global->_inter_variables) {
- variablesCount = READ_LE_UINT16(_totFileData + 0x2C);
- _vm->_global->_inter_variables = new byte[variablesCount * 4];
- _vm->_global->_inter_variablesSizes = new byte[variablesCount * 4];
- _vm->_global->clearVars(variablesCount);
- }
+ if (!_vm->_inter->_variables)
+ _vm->_inter->allocateVars(READ_LE_UINT16(_totFileData + 0x2C));
_vm->_global->_inter_execPtr = _totFileData;
_vm->_global->_inter_execPtr +=
@@ -265,11 +259,14 @@ void Game_v2::playTot(int16 skipPlay) {
if (skipPlay != -1) {
_vm->_goblin->freeObjects();
- _vm->_snd->stopSound(0);
+ _vm->_sound->blasterStop(0);
+
+ for (int i = 0; i < Sound::kSoundsCount; i++) {
+ SoundDesc *sound = _vm->_sound->sampleGetBySlot(i);
- for (int i = 0; i < 60; i++)
- if (_soundSamples[i].getType() == SOUND_SND)
- _vm->_snd->freeSample(_soundSamples[i]);
+ if (sound && (sound->getType() == SOUND_SND))
+ _vm->_sound->sampleFree(sound);
+ }
}
_vm->_vidPlayer->primaryClose();
@@ -630,13 +627,15 @@ void Game_v2::collisionsBlock(void) {
Collision *collArea;
int16 timeKey;
byte *savedIP;
+ byte collAreaStart;
if (_shouldPushColls)
pushCollisions(0);
- collArea = _collisionAreas;
- while (collArea->left != 0xFFFF)
- collArea++;
+ collAreaStart = 0;
+ while (_collisionAreas[collAreaStart].left != 0xFFFF)
+ collAreaStart++;
+ collArea = &_collisionAreas[collAreaStart];
_shouldPushColls = 0;
collResId = -1;
@@ -962,7 +961,7 @@ void Game_v2::collisionsBlock(void) {
continue;
_activeCollResId = collPtr->id;
- _activeCollIndex = i;
+ _activeCollIndex = i + collAreaStart;
_vm->_inter->storeMouse();
if (VAR(16) != 0)
break;
@@ -1004,7 +1003,7 @@ void Game_v2::collisionsBlock(void) {
if ((collPtr->id & 0xF000) == 0x8000)
if (++counter == descIndex) {
_activeCollResId = collPtr->id;
- _activeCollIndex = i;
+ _activeCollIndex = i + collAreaStart;
break;
}
}
@@ -1404,7 +1403,7 @@ int16 Game_v2::inputArea(int16 xPos, int16 yPos, int16 width, int16 height,
flag = 1;
- if (_vm->_global->_inter_variables)
+ if (_vm->_inter->_variables)
WRITE_VAR(56, pos);
while (1) {
diff --git a/engines/gob/global.cpp b/engines/gob/global.cpp
index 1445601017..acca5564dd 100644
--- a/engines/gob/global.cpp
+++ b/engines/gob/global.cpp
@@ -123,8 +123,6 @@ Global::Global(GobEngine *vm) : _vm(vm) {
_inter_resStr[0] = 0;
_inter_resVal = 0;
- _inter_variablesSizes = 0;
- _inter_variables = 0;
_inter_execPtr = 0;
_inter_animDataSize = 10;
diff --git a/engines/gob/global.h b/engines/gob/global.h
index 45c179d277..32651cf15d 100644
--- a/engines/gob/global.h
+++ b/engines/gob/global.h
@@ -123,8 +123,6 @@ public:
char _inter_resStr[200];
int32 _inter_resVal;
- byte *_inter_variablesSizes; // 0: single byte, 1: two bytes, 3: four bytes
- byte *_inter_variables;
byte *_inter_execPtr;
int16 _inter_animDataSize;
@@ -134,73 +132,11 @@ public:
// Can be 1, 2 or 3 for normal, double and triple speed, respectively
uint8 _speedFactor;
- void clearVars(uint32 count) {
- uint32 size = count * 4;
-
- memset(_inter_variables, 0, size);
- memset(_inter_variablesSizes, 0, size);
- for (uint32 i = 0; i < size; i += 4)
- _inter_variablesSizes[i] = 3;
- }
-
- void writeVarSizeStr(uint32 offset, uint32 len) {
- uint32 i;
- uint32 inVar;
- uint32 varOff;
-
- inVar = offset % 4;
- varOff = (offset >> 2) << 2;
- for (i = 0; i < 4; i++) {
- if (_inter_variablesSizes[varOff + i] == 3)
- _inter_variablesSizes[varOff + i] = 0;
- else if ((inVar == (i+1)) && (_inter_variablesSizes[varOff + i] == 1))
- _inter_variablesSizes[varOff + i] = 0;
- }
- memset(_inter_variablesSizes + offset, 0, len);
- }
-
- void writeVar(uint32 offset, uint32 val) {
- WRITE_UINT32(_inter_variables + offset, val);
- writeVarSize(offset, 3);
- }
- void writeVar(uint32 offset, uint16 val) {
- WRITE_UINT16(_inter_variables + offset, val);
- writeVarSize(offset, 1);
- }
- void writeVar(uint32 offset, uint8 val) {
- (*(uint8 *)(_inter_variables + offset)) = val;
- writeVarSize(offset, 0);
- }
- void writeVar(uint32 offset, const char *str) {
- writeVarSizeStr(offset, strlen(str));
- strcpy((char *) (_inter_variables + offset), str);
- }
-
Global(GobEngine *vm);
~Global();
protected:
GobEngine *_vm;
-
- void writeVarSize(uint32 offset, byte n) {
- uint32 i;
- uint32 inVar;
- uint32 varOff;
-
- inVar = offset % 4;
- varOff = (offset >> 2) << 2;
- for (i = 0; i < 4; i++) {
- if (_inter_variablesSizes[varOff + i] == 3)
- _inter_variablesSizes[varOff + i] = 0;
- else if ((inVar == (i+1)) && (_inter_variablesSizes[varOff + i] == 1))
- _inter_variablesSizes[varOff + i] = 0;
- }
-
- _inter_variablesSizes[offset] = n;
- for (; n > 0; n--)
- _inter_variablesSizes[offset + n] = 0;
- }
-
};
} // End of namespace Gob
diff --git a/engines/gob/gob.cpp b/engines/gob/gob.cpp
index 863665357b..a3fe0ebbe2 100644
--- a/engines/gob/gob.cpp
+++ b/engines/gob/gob.cpp
@@ -23,7 +23,6 @@
*
*/
-
#include "common/endian.h"
#include "common/events.h"
@@ -37,18 +36,16 @@
#include "gob/util.h"
#include "gob/dataio.h"
#include "gob/game.h"
-#include "gob/sound.h"
+#include "gob/sound/sound.h"
#include "gob/init.h"
#include "gob/inter.h"
#include "gob/draw.h"
-#include "gob/cdrom.h"
#include "gob/goblin.h"
#include "gob/map.h"
#include "gob/mult.h"
#include "gob/palanim.h"
#include "gob/parse.h"
#include "gob/scenery.h"
-#include "gob/music.h"
#include "gob/videoplayer.h"
#include "gob/saveload.h"
@@ -71,13 +68,14 @@ const Common::Language GobEngine::_gobToScummVMLang[] = {
GobEngine::GobEngine(OSystem *syst) : Engine(syst) {
_vm = this;
- _snd = 0; _adlib = 0; _mult = 0;
- _game = 0; _global = 0; _cdrom = 0;
- _dataIO = 0; _goblin = 0; _vidPlayer = 0;
- _init = 0; _inter = 0; _map = 0;
- _palAnim = 0; _parse = 0; _scenery = 0;
- _draw = 0; _util = 0; _video = 0;
- _saveLoad = 0;
+ _sound = 0; _mult = 0; _game = 0;
+ _global = 0; _dataIO = 0; _goblin = 0;
+ _vidPlayer = 0; _init = 0; _inter = 0;
+ _map = 0; _palAnim = 0; _parse = 0;
+ _scenery = 0; _draw = 0; _util = 0;
+ _video = 0; _saveLoad = 0;
+
+ _pauseStart = 0;
// Setup mixer
_mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume"));
@@ -89,21 +87,24 @@ GobEngine::GobEngine(OSystem *syst) : Engine(syst) {
Common::addSpecialDebugLevel(kDebugFuncOp, "FuncOpcodes", "Script FuncOpcodes debug level");
Common::addSpecialDebugLevel(kDebugDrawOp, "DrawOpcodes", "Script DrawOpcodes debug level");
Common::addSpecialDebugLevel(kDebugGobOp, "GoblinOpcodes", "Script GoblinOpcodes debug level");
- Common::addSpecialDebugLevel(kDebugMusic, "Music", "CD, Adlib and Infogrames music debug level");
+ Common::addSpecialDebugLevel(kDebugSound, "Sound", "Sound output debug level");
Common::addSpecialDebugLevel(kDebugParser, "Parser", "Parser debug level");
Common::addSpecialDebugLevel(kDebugGameFlow, "Gameflow", "Gameflow debug level");
Common::addSpecialDebugLevel(kDebugFileIO, "FileIO", "File Input/Output debug level");
+ Common::addSpecialDebugLevel(kDebugSaveLoad, "SaveLoad", "Saving/Loading debug level");
Common::addSpecialDebugLevel(kDebugGraphics, "Graphics", "Graphics debug level");
+ Common::addSpecialDebugLevel(kDebugVideo, "Video", "IMD/VMD video debug level");
Common::addSpecialDebugLevel(kDebugCollisions, "Collisions", "Collisions debug level");
syst->getEventManager()->registerRandomSource(_rnd, "gob");
}
GobEngine::~GobEngine() {
+ deinitGameParts();
+
// Stop all mixer streams (except for the permanent ones).
_vm->_mixer->stopAll();
- deinitGameParts();
delete[] _startTot;
delete[] _startTot0;
}
@@ -118,6 +119,12 @@ void GobEngine::shutdown() {
_quitRequested = true;
}
+const char *GobEngine::getLangDesc(int16 language) const {
+ if ((language < 0) || (language > 8))
+ language = 2;
+ return Common::getLanguageDescription(_gobToScummVMLang[language]);
+}
+
void GobEngine::validateLanguage() {
if (_vm->_global->_languageWanted != _vm->_global->_language) {
warning("Your game version doesn't support the requested language %s",
@@ -140,6 +147,30 @@ void GobEngine::validateVideoMode(int16 videoMode) {
error("Video mode 0x%X is not supported!", videoMode);
}
+Common::Platform GobEngine::getPlatform() const {
+ return _platform;
+}
+
+GameType GobEngine::getGameType() const {
+ return _gameType;
+}
+
+bool GobEngine::isCD() const {
+ return (_features & kFeaturesCD) != 0;
+}
+
+bool GobEngine::isEGA() const {
+ return (_features & kFeaturesEGA) != 0;
+}
+
+bool GobEngine::is640() const {
+ return (_features & kFeatures640) != 0;
+}
+
+bool GobEngine::hasAdlib() const {
+ return (_features & kFeaturesAdlib) != 0;
+}
+
int GobEngine::init() {
if (!initGameParts()) {
GUIErrorMessage("GobEngine::init(): Unknown version of game engine");
@@ -219,8 +250,26 @@ int GobEngine::init() {
return 0;
}
+void GobEngine::pauseEngineIntern(bool pause) {
+ if (pause) {
+ _pauseStart = _system->getMillis();
+ } else {
+ uint32 duration = _system->getMillis() - _pauseStart;
+
+ _vm->_vidPlayer->notifyPaused(duration);
+
+ _vm->_game->_startTimeKey += duration;
+ _vm->_draw->_cursorTimeKey += duration;
+ if (_vm->_inter->_soundEndTimeKey != 0)
+ _vm->_inter->_soundEndTimeKey += duration;
+ }
+
+ _mixer->pauseAll(pause);
+}
+
bool GobEngine::initGameParts() {
- _adlib = 0;
+ _noMusic = MidiDriver::parseMusicDriver(ConfMan.get("music_driver")) == MD_NULL;
+
_saveLoad = 0;
_global = new Global(this);
@@ -228,8 +277,7 @@ bool GobEngine::initGameParts() {
_dataIO = new DataIO(this);
_palAnim = new PalAnim(this);
_vidPlayer = new VideoPlayer(this);
- _cdrom = new CDROM(this);
- _snd = new Snd(this);
+ _sound = new Sound(this);
switch (_gameType) {
case kGameTypeGob1:
@@ -327,7 +375,7 @@ bool GobEngine::initGameParts() {
_map = new Map_v4(this);
_goblin = new Goblin_v4(this);
_scenery = new Scenery_v2(this);
- _saveLoad = new SaveLoad_v3(this, _targetName.c_str());
+ _saveLoad = new SaveLoad_v4(this, _targetName.c_str());
break;
default:
@@ -336,10 +384,6 @@ bool GobEngine::initGameParts() {
break;
}
- _noMusic = MidiDriver::parseMusicDriver(ConfMan.get("music_driver")) == MD_NULL;
- if (!_noMusic && hasAdlib())
- _adlib = new Adlib(this);
-
if (is640()) {
_video->_surfWidth = _width = 640;
_video->_surfHeight = _video->_splitHeight1 = _height = 480;
@@ -360,15 +404,12 @@ bool GobEngine::initGameParts() {
}
void GobEngine::deinitGameParts() {
- delete _snd; _snd = 0;
- delete _adlib; _adlib = 0;
+ delete _saveLoad; _saveLoad = 0;
delete _mult; _mult = 0;
+ delete _vidPlayer; _vidPlayer = 0;
delete _game; _game = 0;
delete _global; _global = 0;
- delete _cdrom; _cdrom = 0;
- delete _dataIO; _dataIO = 0;
delete _goblin; _goblin = 0;
- delete _vidPlayer; _vidPlayer = 0;
delete _init; _init = 0;
delete _inter; _inter = 0;
delete _map; _map = 0;
@@ -378,7 +419,8 @@ void GobEngine::deinitGameParts() {
delete _draw; _draw = 0;
delete _util; _util = 0;
delete _video; _video = 0;
- delete _saveLoad; _saveLoad = 0;
+ delete _sound; _sound = 0;
+ delete _dataIO; _dataIO = 0;
}
} // End of namespace Gob
diff --git a/engines/gob/gob.h b/engines/gob/gob.h
index e23e917a7c..ae2b53bc31 100644
--- a/engines/gob/gob.h
+++ b/engines/gob/gob.h
@@ -35,11 +35,10 @@
namespace Gob {
class Game;
-class Snd;
+class Sound;
class Video;
class Global;
class Draw;
-class CDROM;
class DataIO;
class Goblin;
class VideoPlayer;
@@ -52,31 +51,33 @@ class Parse;
class Scenery;
class Util;
class SaveLoad;
-class Adlib;
-
-#define VARP(offs) (_vm->_global->_inter_variables + (offs))
-#define WRITE_VARO_UINT32(offs, val) _vm->_global->writeVar(offs, (uint32) (val))
-#define WRITE_VARO_UINT16(offs, val) _vm->_global->writeVar(offs, (uint16) (val))
-#define WRITE_VARO_UINT8(offs, val) _vm->_global->writeVar(offs, (uint8) (val))
-#define WRITE_VARO_STR(offs, str) _vm->_global->writeVar(offs, (const char *) (str))
-#define WRITE_VAR_UINT32(var, val) WRITE_VARO_UINT32((var) << 2, (val))
-#define WRITE_VAR_UINT16(var, val) WRITE_VARO_UINT16((var) << 2, (val))
-#define WRITE_VAR_UINT8(var, val) WRITE_VARO_UINT8((var) << 2, (val))
-#define WRITE_VAR_STR(var, str) WRITE_VARO_STR((var) << 2, (str))
-#define READ_VARO_UINT32(offs) READ_UINT32(VARP(offs))
-#define READ_VARO_UINT16(offs) READ_UINT16(VARP(offs))
-#define READ_VARO_UINT8(offs) (*((uint8 *) VARP(offs)))
-#define READ_VAR_UINT32(var) READ_VARO_UINT32((var) << 2)
-#define READ_VAR_UINT16(var) READ_VARO_UINT16((var) << 2)
-#define READ_VAR_UINT8(var) READ_VARO_UINT8((var) << 2)
-#define GET_VARO_STR(offs) ((char *) VARP(offs))
-#define GET_VAR_STR(var) GET_VARO_STR((var) << 2)
-
-#define WRITE_VAR_OFFSET(offs, val) WRITE_VARO_UINT32((offs), (val))
-#define WRITE_VAR(var, val) WRITE_VAR_UINT32((var), (val))
-#define VAR_OFFSET(offs) READ_VARO_UINT32(offs)
-#define VAR(var) READ_VAR_UINT32(var)
-#define VAR_ADDRESS(var) ((uint32 *) VARP((var) << 2))
+
+#define WRITE_VAR_UINT32(var, val) _vm->_inter->_variables->writeVar32(var, val)
+#define WRITE_VAR_UINT16(var, val) _vm->_inter->_variables->writeVar16(var, val)
+#define WRITE_VAR_UINT8(var, val) _vm->_inter->_variables->writeVar8(var, val)
+#define WRITE_VAR_STR(var, str) _vm->_inter->_variables->writeVarString(var, str)
+#define WRITE_VARO_UINT32(off, val) _vm->_inter->_variables->writeOff32(off, val)
+#define WRITE_VARO_UINT16(off, val) _vm->_inter->_variables->writeOff16(off, val)
+#define WRITE_VARO_UINT8(off, val) _vm->_inter->_variables->writeOff8(off, val)
+#define WRITE_VARO_STR(off, str) _vm->_inter->_variables->writeOffString(off, str)
+#define READ_VAR_UINT32(var) _vm->_inter->_variables->readVar32(var)
+#define READ_VAR_UINT16(var) _vm->_inter->_variables->readVar16(var)
+#define READ_VAR_UINT8(var) _vm->_inter->_variables->readVar8(var)
+#define READ_VARO_UINT32(off) _vm->_inter->_variables->readOff32(off)
+#define READ_VARO_UINT16(off) _vm->_inter->_variables->readOff16(off)
+#define READ_VARO_UINT8(off) _vm->_inter->_variables->readOff8(off)
+#define GET_VAR_STR(var) _vm->_inter->_variables->getAddressVarString(var, 0)
+#define GET_VARO_STR(off) _vm->_inter->_variables->getAddressOffString(off, 0)
+#define GET_VAR_FSTR(var) _vm->_inter->_variables->getAddressVarString(var)
+#define GET_VARO_FSTR(off) _vm->_inter->_variables->getAddressOffString(off)
+
+#define VAR_ADDRESS(var) _vm->_inter->_variables->getAddressVar32(var)
+
+#define WRITE_VAR_OFFSET(off, val) WRITE_VARO_UINT32((off), (val))
+#define WRITE_VAR(var, val) WRITE_VAR_UINT32((var), (val))
+#define VAR_OFFSET(off) READ_VARO_UINT32(off)
+#define VAR(var) READ_VAR_UINT32(var)
+
enum GameType {
kGameTypeNone = 0,
@@ -102,12 +103,14 @@ enum {
kDebugFuncOp = 1 << 0,
kDebugDrawOp = 1 << 1,
kDebugGobOp = 1 << 2,
- kDebugMusic = 1 << 3, // CD, Adlib and Infogrames music
+ kDebugSound = 1 << 3,
kDebugParser = 1 << 4,
kDebugGameFlow = 1 << 5,
kDebugFileIO = 1 << 6,
- kDebugGraphics = 1 << 7,
- kDebugCollisions = 1 << 8
+ kDebugSaveLoad = 1 << 7,
+ kDebugGraphics = 1 << 8,
+ kDebugVideo = 1 << 9,
+ kDebugCollisions = 1 << 10
};
inline char *strncpy0(char *dest, const char *src, size_t n) {
@@ -171,12 +174,19 @@ private:
struct GOBGameDescription;
class GobEngine : public Engine {
-protected:
+private:
GobEngine *_vm;
+ GameType _gameType;
+ int32 _features;
+ Common::Platform _platform;
+
+ uint32 _pauseStart;
+
int go();
int init();
+ void pauseEngineIntern(bool pause);
bool initGameParts();
void deinitGameParts();
@@ -185,11 +195,7 @@ public:
Common::RandomSource _rnd;
- GameType _gameType;
- int32 _features;
Common::Language _language;
- Common::Platform _platform;
-
uint16 _width;
uint16 _height;
uint8 _mode;
@@ -204,10 +210,9 @@ public:
Util *_util;
DataIO *_dataIO;
Game *_game;
- Snd *_snd;
+ Sound *_sound;
Video *_video;
Draw *_draw;
- CDROM *_cdrom;
Goblin *_goblin;
Init *_init;
Map *_map;
@@ -217,24 +222,20 @@ public:
Scenery *_scenery;
Inter *_inter;
SaveLoad *_saveLoad;
- Adlib *_adlib;
VideoPlayer *_vidPlayer;
void shutdown();
- const char *getLangDesc(int16 language) {
- if ((language < 0) || (language > 8))
- language = 2;
- return Common::getLanguageDescription(_gobToScummVMLang[language]);
- }
+ const char *getLangDesc(int16 language) const;
void validateLanguage();
void validateVideoMode(int16 videoMode);
- GameType getGameType() { return _gameType; }
- bool isCD() { return (_features & kFeaturesCD) != 0; }
- bool isEGA() { return (_features & kFeaturesEGA) != 0; }
- bool is640() { return (_features & kFeatures640) != 0; }
- bool hasAdlib() { return (_features & kFeaturesAdlib) != 0; }
+ Common::Platform getPlatform() const;
+ GameType getGameType() const;
+ bool isCD() const;
+ bool isEGA() const;
+ bool is640() const;
+ bool hasAdlib() const;
GobEngine(OSystem *syst);
virtual ~GobEngine();
diff --git a/engines/gob/goblin.cpp b/engines/gob/goblin.cpp
index 64a2b15ef4..e7aed0790e 100644
--- a/engines/gob/goblin.cpp
+++ b/engines/gob/goblin.cpp
@@ -32,7 +32,8 @@
#include "gob/map.h"
#include "gob/mult.h"
#include "gob/scenery.h"
-#include "gob/sound.h"
+#include "gob/inter.h"
+#include "gob/sound/sound.h"
namespace Gob {
@@ -164,7 +165,7 @@ Goblin::~Goblin() {
for (col = 0; col < 6; col++)
if (_goblins[i]->realStateMach[state][col])
delete _goblins[i]->realStateMach[state][col];
- delete []_goblins[i]->realStateMach;
+ delete[] _goblins[i]->realStateMach;
}
delete _goblins[i];
}
@@ -176,7 +177,7 @@ Goblin::~Goblin() {
for (col = 0; col < 6; col++)
if (_objects[i]->realStateMach[state][col])
delete _objects[i]->realStateMach[state][col];
- delete []_objects[i]->realStateMach;
+ delete[] _objects[i]->realStateMach;
}
delete _objects[i];
}
@@ -255,8 +256,8 @@ void Goblin::sortByOrder(Util::List *list) {
void Goblin::playSound(SoundDesc &snd, int16 repCount, int16 freq) {
if (!snd.empty()) {
- _vm->_snd->stopSound(0);
- _vm->_snd->playSample(snd, repCount, freq);
+ _vm->_sound->blasterStop(0);
+ _vm->_sound->blasterPlay(&snd, repCount, freq);
}
}
@@ -1216,7 +1217,7 @@ void Goblin::zeroObjects(void) {
_objects[i] = 0;
for (int i = 0; i < 16; i++)
- _vm->_snd->freeSample(_soundData[i]);
+ _vm->_sound->sampleFree(&_soundData[i]);
}
void Goblin::freeAllObjects(void) {
@@ -1717,12 +1718,12 @@ void Goblin::playSounds(Mult::Mult_Object *obj) {
if (!speaker) {
sndSlot = obj->goblinStates[animData->state][i].sndItem;
- _vm->_snd->stopSound(0);
+ _vm->_sound->blasterStop(0);
if (sndSlot < _soundSlotsCount)
- _vm->_snd->playSample(_vm->_game->_soundSamples[_soundSlots[sndSlot] & 0x7FFF],
+ _vm->_sound->blasterPlay(_vm->_sound->sampleGetBySlot(_soundSlots[sndSlot] & 0x7FFF),
repCount, frequency);
} else
- _vm->_snd->speakerOn(frequency, repCount * 10);
+ _vm->_sound->speakerOn(frequency, repCount * 10);
}
}
diff --git a/engines/gob/goblin.h b/engines/gob/goblin.h
index f7ac4aa549..3fd8a9f93b 100644
--- a/engines/gob/goblin.h
+++ b/engines/gob/goblin.h
@@ -27,8 +27,8 @@
#define GOB_GOBLIN_H
#include "gob/util.h"
-#include "gob/sound.h"
#include "gob/mult.h"
+#include "gob/sound/sounddesc.h"
namespace Gob {
diff --git a/engines/gob/goblin_v1.cpp b/engines/gob/goblin_v1.cpp
index f7bdbf10a5..6ac086767b 100644
--- a/engines/gob/goblin_v1.cpp
+++ b/engines/gob/goblin_v1.cpp
@@ -23,7 +23,6 @@
*
*/
-
#include "common/endian.h"
#include "gob/gob.h"
@@ -32,7 +31,7 @@
#include "gob/map.h"
#include "gob/mult.h"
#include "gob/scenery.h"
-#include "gob/sound.h"
+#include "gob/sound/sound.h"
namespace Gob {
@@ -48,7 +47,7 @@ void Goblin_v1::freeObjects(void) {
int16 col;
for (int i = 0; i < 16; i++)
- _vm->_snd->freeSample(_soundData[i]);
+ _vm->_sound->sampleFree(&_soundData[i]);
for (int i = 0; i < 4; i++) {
if (_goblins[i] == 0)
@@ -488,19 +487,19 @@ void Goblin_v1::moveAdvance(Mult::Mult_Object *obj, Gob_Object *gobDesc,
if ((gobDesc->state >= 0) && (gobDesc->state < 10) &&
(gobDesc->stateMach == gobDesc->realStateMach) &&
((gobDesc->curFrame == 3) || (gobDesc->curFrame == 6))) {
- _vm->_snd->speakerOn(10 * _vm->_util->getRandom(3) + 50, 5);
+ _vm->_sound->speakerOn(10 * _vm->_util->getRandom(3) + 50, 5);
}
if ((_currentGoblin == 0) &&
(gobDesc->stateMach == gobDesc->realStateMach) &&
((gobDesc->state == 10) || (gobDesc->state == 11)) &&
(gobDesc->curFrame == 9)) {
- _vm->_snd->stopSound(0);
+ _vm->_sound->blasterStop(0);
if (_itemIndInPocket != -1)
- _vm->_snd->playSample(_soundData[14], 1, 9000);
+ _vm->_sound->blasterPlay(&_soundData[14], 1, 9000);
else
- _vm->_snd->playSample(_soundData[14], 1, 5000);
+ _vm->_sound->blasterPlay(&_soundData[14], 1, 5000);
}
if (_boreCounter++ == 120) {
diff --git a/engines/gob/goblin_v2.cpp b/engines/gob/goblin_v2.cpp
index c9e155ad08..9144e35070 100644
--- a/engines/gob/goblin_v2.cpp
+++ b/engines/gob/goblin_v2.cpp
@@ -23,7 +23,6 @@
*
*/
-
#include "common/endian.h"
#include "gob/gob.h"
@@ -34,6 +33,7 @@
#include "gob/map.h"
#include "gob/mult.h"
#include "gob/scenery.h"
+#include "gob/inter.h"
namespace Gob {
diff --git a/engines/gob/goblin_v4.cpp b/engines/gob/goblin_v4.cpp
index 167946e30d..1df5aab606 100644
--- a/engines/gob/goblin_v4.cpp
+++ b/engines/gob/goblin_v4.cpp
@@ -29,6 +29,7 @@
#include "gob/mult.h"
#include "gob/map.h"
#include "gob/scenery.h"
+#include "gob/inter.h"
namespace Gob {
diff --git a/engines/gob/init.cpp b/engines/gob/init.cpp
index 4d184c53d3..c2f8b48626 100644
--- a/engines/gob/init.cpp
+++ b/engines/gob/init.cpp
@@ -23,7 +23,6 @@
*
*/
-
#include "common/endian.h"
#include "gob/gob.h"
@@ -31,13 +30,13 @@
#include "gob/global.h"
#include "gob/util.h"
#include "gob/dataio.h"
-#include "gob/cdrom.h"
#include "gob/draw.h"
#include "gob/game.h"
#include "gob/palanim.h"
-#include "gob/sound.h"
+#include "gob/inter.h"
#include "gob/video.h"
#include "gob/videoplayer.h"
+#include "gob/sound/sound.h"
namespace Gob {
@@ -51,8 +50,8 @@ void Init::cleanup(void) {
_vm->_video->freeDriver();
_vm->_global->_primarySurfDesc = 0;
- _vm->_snd->speakerOff();
- _vm->_snd->stopSound(0);
+ _vm->_sound->speakerOff();
+ _vm->_sound->blasterStop(0);
_vm->_dataIO->closeDataFile();
}
@@ -64,7 +63,6 @@ void Init::initGame(const char *totName) {
char *infPtr;
char *infEnd;
char buffer[128];
- int32 varsCount;
initVideo();
@@ -92,8 +90,6 @@ void Init::initGame(const char *totName) {
_vm->_game->_totTextData = 0;
_vm->_game->_totFileData = 0;
_vm->_game->_totResourceTable = 0;
- _vm->_global->_inter_variables = 0;
- _vm->_global->_inter_variablesSizes = 0;
_palDesc = new Video::PalDesc;
_vm->validateVideoMode(_vm->_global->_videoMode);
@@ -159,18 +155,14 @@ void Init::initGame(const char *totName) {
DataStream *stream = _vm->_dataIO->openAsStream(handle, true);
stream->seek(0x2C);
- varsCount = stream->readUint16LE();
+ _vm->_inter->allocateVars(stream->readUint16LE());
delete stream;
- _vm->_global->_inter_variables = new byte[varsCount * 4];
- _vm->_global->_inter_variablesSizes = new byte[varsCount * 4];
- _vm->_global->clearVars(varsCount);
-
strcpy(_vm->_game->_curTotFile, buffer);
- _vm->_cdrom->testCD(1, "GOB");
- _vm->_cdrom->readLIC("gob.lic");
+ _vm->_sound->cdTest(1, "GOB");
+ _vm->_sound->cdLoadLIC("gob.lic");
// Search for a Coktel logo animation or image to display
imdHandle = _vm->_dataIO->openData("coktel.imd");
@@ -213,11 +205,9 @@ void Init::initGame(const char *totName) {
_vm->_game->start();
- _vm->_cdrom->stopPlaying();
- _vm->_cdrom->freeLICbuffer();
+ _vm->_sound->cdStop();
+ _vm->_sound->cdUnloadLIC();
- delete[] _vm->_global->_inter_variables;
- delete[] _vm->_global->_inter_variablesSizes;
delete[] _vm->_game->_totFileData;
if (_vm->_game->_totTextData) {
if (_vm->_game->_totTextData->items)
diff --git a/engines/gob/init_v1.cpp b/engines/gob/init_v1.cpp
index 8065c4dc8c..90456f927c 100644
--- a/engines/gob/init_v1.cpp
+++ b/engines/gob/init_v1.cpp
@@ -23,7 +23,6 @@
*
*/
-
#include "common/endian.h"
#include "gob/gob.h"
diff --git a/engines/gob/init_v2.cpp b/engines/gob/init_v2.cpp
index bb29f4e8fd..b468c15c25 100644
--- a/engines/gob/init_v2.cpp
+++ b/engines/gob/init_v2.cpp
@@ -23,7 +23,6 @@
*
*/
-
#include "common/endian.h"
#include "gob/gob.h"
@@ -50,8 +49,8 @@ void Init_v2::initVideo() {
_vm->_global->_inVM = 0;
_vm->_global->_colorCount = 16;
- if (((_vm->_platform == Common::kPlatformPC) ||
- (_vm->_platform == Common::kPlatformMacintosh)) &&
+ if (((_vm->getPlatform() == Common::kPlatformPC) ||
+ (_vm->getPlatform() == Common::kPlatformMacintosh)) &&
((_vm->_global->_videoMode == 0x13) ||
(_vm->_global->_videoMode == 0x14)))
_vm->_global->_colorCount = 256;
diff --git a/engines/gob/inter.cpp b/engines/gob/inter.cpp
index de3ac4b1f5..9c39653a1d 100644
--- a/engines/gob/inter.cpp
+++ b/engines/gob/inter.cpp
@@ -23,6 +23,7 @@
*
*/
+#include <time.h> // FIXME: for Inter::renewTimeInVars()
#include "common/endian.h"
@@ -34,9 +35,7 @@
#include "gob/game.h"
#include "gob/parse.h"
#include "gob/scenery.h"
-#include "gob/sound.h"
-
-#include <time.h> // FIXME: for Inter::renewTimeInVars()
+#include "gob/sound/sound.h"
namespace Gob {
@@ -61,6 +60,12 @@ Inter::Inter(GobEngine *vm) : _vm(vm) {
_pastePos = 0;
_noBusyWait = false;
+
+ _variables = 0;
+}
+
+Inter::~Inter() {
+ delocateVars();
}
void Inter::initControlVars(char full) {
@@ -154,7 +159,7 @@ void Inter::storeKey(int16 key) {
WRITE_VAR(12, _vm->_util->getTimeKey() - _vm->_game->_startTimeKey);
storeMouse();
- WRITE_VAR(1, _vm->_snd->_playingSound);
+ WRITE_VAR(1, _vm->_sound->blasterPlayingSound());
if (key == 0x4800)
key = 0x0B;
@@ -280,4 +285,18 @@ void Inter::callSub(int16 retFlag) {
_terminate = 1;
}
+void Inter::allocateVars(uint32 count) {
+ if ((_vm->getPlatform() == Common::kPlatformAmiga) ||
+ (_vm->getPlatform() == Common::kPlatformMacintosh) ||
+ (_vm->getPlatform() == Common::kPlatformAtariST))
+ _variables = new VariablesBE(count * 4);
+ else
+ _variables = new VariablesLE(count * 4);
+}
+
+void Inter::delocateVars() {
+ delete _variables;
+ _variables = 0;
+}
+
} // End of namespace Gob
diff --git a/engines/gob/inter.h b/engines/gob/inter.h
index 582e57a2d4..60b3974d6d 100644
--- a/engines/gob/inter.h
+++ b/engines/gob/inter.h
@@ -27,6 +27,7 @@
#define GOB_INTER_H
#include "gob/goblin.h"
+#include "gob/variables.h"
namespace Gob {
@@ -48,6 +49,8 @@ public:
uint32 _soundEndTimeKey;
int16 _soundStopVal;
+ Variables *_variables;
+
void initControlVars(char full);
int16 load16();
char evalExpr(int16 *pRes);
@@ -59,11 +62,14 @@ public:
void funcBlock(int16 retFlag);
void callSub(int16 retFlag);
+ void allocateVars(uint32 count);
+ void delocateVars();
+
virtual int16 loadSound(int16 slot) = 0;
virtual void animPalette() = 0;
Inter(GobEngine *vm);
- virtual ~Inter() {}
+ virtual ~Inter();
protected:
struct OpFuncParams {
@@ -83,7 +89,7 @@ protected:
int16 _animPalHighIndex[8];
int16 _animPalDir[8];
- char _pasteBuf[300];
+ byte _pasteBuf[300];
byte _pasteSizeBuf[300];
int16 _pastePos;
@@ -519,6 +525,7 @@ protected:
virtual const char *getOpcodeFuncDesc(byte i, byte j);
virtual const char *getOpcodeGoblinDesc(int i);
+ void o4_initScreen();
void o4_playVmdOrMusic();
};
diff --git a/engines/gob/inter_bargon.cpp b/engines/gob/inter_bargon.cpp
index 702950d539..d493fb00d3 100644
--- a/engines/gob/inter_bargon.cpp
+++ b/engines/gob/inter_bargon.cpp
@@ -23,7 +23,6 @@
*
*/
-
#include "common/endian.h"
#include "gob/gob.h"
@@ -34,9 +33,9 @@
#include "gob/draw.h"
#include "gob/game.h"
#include "gob/palanim.h"
-#include "gob/sound.h"
#include "gob/video.h"
#include "gob/videoplayer.h"
+#include "gob/sound/sound.h"
namespace Gob {
@@ -768,9 +767,9 @@ void Inter_Bargon::oBargon_intro2(OpGobParams &params) {
return;
for (i = 0; i < 4; i++)
- _vm->_snd->loadSample(samples[i], sndFiles[i]);
- _vm->_snd->playComposition(comp, 0, samples, 4);
- _vm->_snd->waitEndPlay(true, false);
+ _vm->_sound->sampleLoad(&samples[i], sndFiles[i]);
+ _vm->_sound->blasterPlayComposition(comp, 0, samples, 4);
+ _vm->_sound->blasterWaitEndPlay(true, false);
_vm->_palAnim->fade(0, 0, 0);
_vm->_video->clearSurf(_vm->_draw->_frontSurface);
}
@@ -787,12 +786,12 @@ void Inter_Bargon::oBargon_intro3(OpGobParams &params) {
static const char *palFiles[] = {"2ou2.clt", "2ou3.clt", "2ou4.clt", "2ou5.clt"};
for (int i = 0; i < 2; i++)
- _vm->_snd->loadSample(samples[i], sndFiles[i]);
+ _vm->_sound->sampleLoad(&samples[i], sndFiles[i]);
for (int i = 0; i < 4; i++)
palettes[i] = _vm->_dataIO->getData(palFiles[i]);
palBak = _vm->_global->_pPaletteDesc->vgaPal;
- _vm->_snd->playComposition(comp, 0, samples, 2);
+ _vm->_sound->blasterPlayComposition(comp, 0, samples, 2);
for (int i = 0; i < 20; i++) {
for (int j = 0; j < 4; j++) {
_vm->_global->_pPaletteDesc->vgaPal = (Video::Color *) palettes[j];
@@ -801,7 +800,7 @@ void Inter_Bargon::oBargon_intro3(OpGobParams &params) {
}
if ((_vm->_game->checkKeys(&mouseX, &mouseY, &buttons, 0) == 0x11B) ||
_vm->_quitRequested) {
- _vm->_snd->stopSound(10);
+ _vm->_sound->blasterStop(10);
_vm->_palAnim->fade(0, -2, 0);
_vm->_video->clearSurf(_vm->_draw->_frontSurface);
memset((char *) _vm->_draw->_vgaPalette, 0, 768);
@@ -811,7 +810,7 @@ void Inter_Bargon::oBargon_intro3(OpGobParams &params) {
break;
}
}
- _vm->_snd->waitEndPlay(false, false);
+ _vm->_sound->blasterWaitEndPlay(false, false);
_vm->_global->_pPaletteDesc->vgaPal = palBak;
for (int i = 0; i < 4; i++)
diff --git a/engines/gob/inter_v1.cpp b/engines/gob/inter_v1.cpp
index 9707a628b4..e2b8d65112 100644
--- a/engines/gob/inter_v1.cpp
+++ b/engines/gob/inter_v1.cpp
@@ -23,7 +23,6 @@
*
*/
-
#include "common/endian.h"
#include "common/file.h"
@@ -32,8 +31,6 @@
#include "gob/global.h"
#include "gob/util.h"
#include "gob/dataio.h"
-#include "gob/music.h"
-#include "gob/cdrom.h"
#include "gob/draw.h"
#include "gob/game.h"
#include "gob/goblin.h"
@@ -43,8 +40,8 @@
#include "gob/palanim.h"
#include "gob/parse.h"
#include "gob/scenery.h"
-#include "gob/sound.h"
#include "gob/video.h"
+#include "gob/sound/sound.h"
namespace Gob {
@@ -932,16 +929,16 @@ void Inter_v1::o1_initMult() {
_vm->_mult->_objCount * sizeof(Mult::Mult_Object));
for (int i = 0; i < _vm->_mult->_objCount; i++) {
- _vm->_mult->_objects[i].pPosX =
- (int32 *)(_vm->_global->_inter_variables +
- i * 4 + (posXVar / 4) * 4);
- _vm->_mult->_objects[i].pPosY =
- (int32 *)(_vm->_global->_inter_variables +
- i * 4 + (posYVar / 4) * 4);
+ uint32 offPosX = i * 4 + (posXVar / 4) * 4;
+ uint32 offPosY = i * 4 + (posYVar / 4) * 4;
+ uint32 offAnim = animDataVar + i * 4 * _vm->_global->_inter_animDataSize;
+
+ _vm->_mult->_objects[i].pPosX = (int32 *) _variables->getAddressOff32(offPosX);
+ _vm->_mult->_objects[i].pPosY = (int32 *) _variables->getAddressOff32(offPosY);
_vm->_mult->_objects[i].pAnimData =
- (Mult::Mult_AnimData *) (_vm->_global->_inter_variables +
- animDataVar + i * 4 * _vm->_global->_inter_animDataSize);
+ (Mult::Mult_AnimData *) _variables->getAddressOff8(offAnim,
+ _vm->_global->_inter_animDataSize);
_vm->_mult->_objects[i].pAnimData->isStatic = 1;
_vm->_mult->_objects[i].tick = 0;
@@ -1071,12 +1068,8 @@ void Inter_v1::o1_loadCurLayer() {
void Inter_v1::o1_playCDTrack() {
evalExpr(0);
- if (_vm->_platform == Common::kPlatformMacintosh) {
- if (_vm->_adlib)
- _vm->_adlib->playTrack(_vm->_global->_inter_resStr);
- } else
- // Used in gob1 CD
- _vm->_cdrom->startTrack(_vm->_global->_inter_resStr);
+ _vm->_sound->adlibPlayBgMusic(); // Mac version
+ _vm->_sound->cdPlay(_vm->_global->_inter_resStr); // PC CD version
}
void Inter_v1::o1_getCDTrackPos() {
@@ -1088,19 +1081,15 @@ void Inter_v1::o1_getCDTrackPos() {
_vm->_util->longDelay(1);
- int pos = _vm->_cdrom->getTrackPos();
+ int pos = _vm->_sound->cdGetTrackPos();
if (pos == -1)
pos = 32767;
WRITE_VAR(5, pos);
}
void Inter_v1::o1_stopCD() {
- if (_vm->_platform == Common::kPlatformMacintosh) {
- if (_vm->_adlib)
- _vm->_adlib->stopPlay();
- } else
- // Used in gob1 CD
- _vm->_cdrom->stopPlaying();
+ _vm->_sound->adlibStop(); // Mac version
+ _vm->_sound->cdStop(); // PC CD version
}
void Inter_v1::o1_loadFontToSprite() {
@@ -1685,7 +1674,7 @@ bool Inter_v1::o1_keyFunc(OpFuncParams &params) {
break;
default:
- _vm->_snd->speakerOnUpdate(cmd);
+ _vm->_sound->speakerOnUpdate(cmd);
if (cmd < 20) {
_vm->_util->delay(cmd);
_noBusyWait = true;
@@ -1759,12 +1748,12 @@ bool Inter_v1::o1_renewTimeInVars(OpFuncParams &params) {
}
bool Inter_v1::o1_speakerOn(OpFuncParams &params) {
- _vm->_snd->speakerOn(_vm->_parse->parseValExpr(), -1);
+ _vm->_sound->speakerOn(_vm->_parse->parseValExpr(), -1);
return false;
}
bool Inter_v1::o1_speakerOff(OpFuncParams &params) {
- _vm->_snd->speakerOff();
+ _vm->_sound->speakerOff();
return false;
}
@@ -1978,10 +1967,10 @@ bool Inter_v1::o1_playSound(OpFuncParams &params) {
repCount = _vm->_parse->parseValExpr();
frequency = _vm->_parse->parseValExpr();
- SoundDesc &sample = _vm->_game->_soundSamples[index];
+ SoundDesc *sample = _vm->_sound->sampleGetBySlot(index);
_soundEndTimeKey = 0;
- if (sample.empty())
+ if (!sample || sample->empty())
return false;
if (repCount < 0) {
@@ -1991,31 +1980,28 @@ bool Inter_v1::o1_playSound(OpFuncParams &params) {
repCount = -repCount;
_soundEndTimeKey = _vm->_util->getTimeKey();
- freq2 = frequency ? frequency : sample._frequency;
+ freq2 = frequency ? frequency : sample->_frequency;
endRep = MAX(repCount - 1, 1);
- _soundStopVal = sample.calcFadeOutLength(freq2);
- _soundEndTimeKey += sample.calcLength(endRep, freq2, true);
+ _soundStopVal = sample->calcFadeOutLength(freq2);
+ _soundEndTimeKey += sample->calcLength(endRep, freq2, true);
}
- if (sample.getType() == SOUND_ADL) {
- if (_vm->_adlib) {
- _vm->_adlib->load(sample.getData(), sample.size(), index);
- _vm->_adlib->setRepeating(repCount - 1);
- _vm->_adlib->startPlay();
- }
+ if (sample->getType() == SOUND_ADL) {
+ _vm->_sound->adlibLoad(sample->getData(), sample->size(), index);
+ _vm->_sound->adlibSetRepeating(repCount - 1);
+ _vm->_sound->adlibPlay();
} else {
- _vm->_snd->stopSound(0);
- _vm->_snd->playSample(sample, repCount - 1, frequency);
+ _vm->_sound->blasterStop(0);
+ _vm->_sound->blasterPlay(sample, repCount - 1, frequency);
}
return false;
}
bool Inter_v1::o1_stopSound(OpFuncParams &params) {
- if (_vm->_adlib)
- _vm->_adlib->stopPlay();
- _vm->_snd->stopSound(_vm->_parse->parseValExpr());
+ _vm->_sound->adlibStop();
+ _vm->_sound->blasterStop(_vm->_parse->parseValExpr());
_soundEndTimeKey = 0;
return false;
@@ -2032,7 +2018,7 @@ bool Inter_v1::o1_freeSoundSlot(OpFuncParams &params) {
}
bool Inter_v1::o1_waitEndPlay(OpFuncParams &params) {
- _vm->_snd->waitEndPlay();
+ _vm->_sound->blasterWaitEndPlay();
return false;
}
@@ -2046,7 +2032,7 @@ bool Inter_v1::o1_playComposition(OpFuncParams &params) {
for (int i = 0; i < 50; i++)
composition[i] = (int16) VAR_OFFSET(dataVar + i * 4);
- _vm->_snd->playComposition(composition, freqVal);
+ _vm->_sound->blasterPlayComposition(composition, freqVal);
return false;
}
@@ -2083,8 +2069,7 @@ bool Inter_v1::o1_prepareStr(OpFuncParams &params) {
int16 strVar;
strVar = _vm->_parse->parseVarIndex();
- _vm->_util->prepareStr(GET_VARO_STR(strVar));
- _vm->_global->writeVarSizeStr(strVar, strlen(GET_VARO_STR(strVar)));
+ _vm->_util->prepareStr(GET_VARO_FSTR(strVar));
return false;
}
@@ -2095,8 +2080,9 @@ bool Inter_v1::o1_insertStr(OpFuncParams &params) {
strVar = _vm->_parse->parseVarIndex();
evalExpr(0);
pos = _vm->_parse->parseValExpr();
- _vm->_util->insertStr(_vm->_global->_inter_resStr, GET_VARO_STR(strVar), pos);
- _vm->_global->writeVarSizeStr(strVar, strlen(GET_VARO_STR(strVar)));
+
+ char *str = GET_VARO_FSTR(strVar);
+ _vm->_util->insertStr(_vm->_global->_inter_resStr, str, pos);
return false;
}
@@ -2236,7 +2222,7 @@ bool Inter_v1::o1_readData(OpFuncParams &params) {
if (((dataVar >> 2) == 59) && (size == 4))
WRITE_VAR(59, stream->readUint32LE());
else
- retSize = stream->read(_vm->_global->_inter_variables + dataVar, size);
+ retSize = stream->read((byte *) _variables->getAddressOff8(dataVar, size), size);
if (retSize == size)
WRITE_VAR(1, 0);
@@ -2803,11 +2789,9 @@ void Inter_v1::o1_animateObjects(OpGobParams &params) {
void Inter_v1::o1_drawObjects(OpGobParams &params) {
_vm->_goblin->drawObjects();
- if (_vm->_platform == Common::kPlatformMacintosh) {
- if (_vm->_adlib)
- _vm->_adlib->playBgMusic();
- } else if (_vm->_cdrom->getTrackPos() == -1)
- _vm->_cdrom->playBgMusic();
+ _vm->_sound->adlibPlayBgMusic(); // Mac version
+ if (_vm->_sound->cdGetTrackPos() == -1)
+ _vm->_sound->cdPlayBgMusic(); // PC CD version
}
void Inter_v1::o1_loadMap(OpGobParams &params) {
@@ -2993,9 +2977,11 @@ int16 Inter_v1::loadSound(int16 slot) {
dataSize = (uint32) ((int32) totSize);
}
- if (dataPtr)
- _vm->_game->_soundSamples[slot].load(SOUND_SND, source,
- dataPtr, dataSize);
+ if (dataPtr) {
+ SoundDesc *sample = _vm->_sound->sampleGetBySlot(slot);
+ if (sample)
+ sample->load(SOUND_SND, source, dataPtr, dataSize);
+ }
return 0;
}
diff --git a/engines/gob/inter_v2.cpp b/engines/gob/inter_v2.cpp
index be510df08a..d8c33fcce6 100644
--- a/engines/gob/inter_v2.cpp
+++ b/engines/gob/inter_v2.cpp
@@ -23,7 +23,6 @@
*
*/
-
#include "common/endian.h"
#include "sound/mixer.h"
#include "sound/mods/infogrames.h"
@@ -33,8 +32,6 @@
#include "gob/global.h"
#include "gob/util.h"
#include "gob/dataio.h"
-#include "gob/music.h"
-#include "gob/cdrom.h"
#include "gob/draw.h"
#include "gob/game.h"
#include "gob/goblin.h"
@@ -42,10 +39,10 @@
#include "gob/mult.h"
#include "gob/parse.h"
#include "gob/scenery.h"
-#include "gob/sound.h"
#include "gob/video.h"
#include "gob/saveload.h"
#include "gob/videoplayer.h"
+#include "gob/sound/sound.h"
namespace Gob {
@@ -899,26 +896,23 @@ void Inter_v2::o2_initMult() {
if (_terminate)
return;
- _vm->_mult->_orderArray = new uint8[_vm->_mult->_objCount];
+ _vm->_mult->_orderArray = new int8[_vm->_mult->_objCount];
memset(_vm->_mult->_orderArray, 0, _vm->_mult->_objCount * sizeof(int8));
_vm->_mult->_objects = new Mult::Mult_Object[_vm->_mult->_objCount];
memset(_vm->_mult->_objects, 0,
_vm->_mult->_objCount * sizeof(Mult::Mult_Object));
for (int i = 0; i < _vm->_mult->_objCount; i++) {
- _vm->_mult->_objects[i].pPosX =
- (int32 *)(_vm->_global->_inter_variables +
- i * 4 + (posXVar / 4) * 4);
- _vm->_mult->_objects[i].pPosY =
- (int32 *)(_vm->_global->_inter_variables +
- i * 4 + (posYVar / 4) * 4);
+ uint32 offPosX = i * 4 + (posXVar / 4) * 4;
+ uint32 offPosY = i * 4 + (posYVar / 4) * 4;
+ uint32 offAnim = animDataVar + i * 4 * _vm->_global->_inter_animDataSize;
+
+ _vm->_mult->_objects[i].pPosX = (int32 *) _variables->getAddressOff32(offPosX);
+ _vm->_mult->_objects[i].pPosY = (int32 *) _variables->getAddressOff32(offPosY);
_vm->_mult->_objects[i].pAnimData =
- (Mult::Mult_AnimData *) (_vm->_global->_inter_variables +
- animDataVar + i * 4 * _vm->_global->_inter_animDataSize);
- memset(_vm->_global->_inter_variablesSizes +
- i * 4 * _vm->_global->_inter_animDataSize, 0,
- _vm->_global->_inter_animDataSize);
+ (Mult::Mult_AnimData *) _variables->getAddressOff8(offAnim,
+ _vm->_global->_inter_animDataSize);
_vm->_mult->_objects[i].pAnimData->isStatic = 1;
_vm->_mult->_objects[i].tick = 0;
@@ -1086,16 +1080,18 @@ void Inter_v2::o2_playCDTrack() {
_vm->_draw->blitInvalidated();
evalExpr(0);
- _vm->_cdrom->startTrack(_vm->_global->_inter_resStr);
+ _vm->_sound->cdPlay(_vm->_global->_inter_resStr);
}
void Inter_v2::o2_waitCDTrackEnd() {
- while (_vm->_cdrom->getTrackPos() >= 0)
+ debugC(1, kDebugSound, "CDROM: Waiting for playback to end");
+
+ while (_vm->_sound->cdGetTrackPos() >= 0)
_vm->_util->longDelay(1);
}
void Inter_v2::o2_stopCD() {
- _vm->_cdrom->stopPlaying();
+ _vm->_sound->cdStop();
}
void Inter_v2::o2_readLIC() {
@@ -1105,11 +1101,11 @@ void Inter_v2::o2_readLIC() {
strncpy0(path, _vm->_global->_inter_resStr, 35);
strcat(path, ".LIC");
- _vm->_cdrom->readLIC(path);
+ _vm->_sound->cdLoadLIC(path);
}
void Inter_v2::o2_freeLIC() {
- _vm->_cdrom->freeLICbuffer();
+ _vm->_sound->cdUnloadLIC();
}
void Inter_v2::o2_getCDTrackPos() {
@@ -1121,8 +1117,8 @@ void Inter_v2::o2_getCDTrackPos() {
varPos = _vm->_parse->parseVarIndex();
varName = _vm->_parse->parseVarIndex();
- WRITE_VAR_OFFSET(varPos, _vm->_cdrom->getTrackPos(GET_VARO_STR(varName)));
- WRITE_VARO_STR(varName, _vm->_cdrom->getCurTrack());
+ WRITE_VAR_OFFSET(varPos, _vm->_sound->cdGetTrackPos(GET_VARO_STR(varName)));
+ WRITE_VARO_STR(varName, _vm->_sound->cdGetCurrentTrack());
}
void Inter_v2::o2_loadFontToSprite() {
@@ -1187,10 +1183,7 @@ void Inter_v2::o2_copyVars() {
varOff = _vm->_parse->parseVarIndex();
_vm->_global->_inter_execPtr++;
- memcpy(_pasteBuf + _pastePos, _vm->_global->_inter_variables + varOff,
- _vm->_global->_inter_animDataSize * 4);
- memcpy(_pasteSizeBuf + _pastePos,
- _vm->_global->_inter_variablesSizes + varOff,
+ _variables->copyTo(varOff, _pasteBuf + _pastePos, _pasteSizeBuf + _pastePos,
_vm->_global->_inter_animDataSize * 4);
_pastePos += _vm->_global->_inter_animDataSize * 4;
@@ -1200,6 +1193,7 @@ void Inter_v2::o2_copyVars() {
} else {
if (evalExpr(&varOff) == 20)
_vm->_global->_inter_resVal = 0;
+
memcpy(_pasteBuf + _pastePos, &_vm->_global->_inter_resVal, 4);
memcpy(_pasteSizeBuf + _pastePos, &_vm->_global->_inter_resVal, 4);
_pastePos += 4;
@@ -1223,8 +1217,7 @@ void Inter_v2::o2_pasteVars() {
assert(sizeV == sizeS);
_pastePos -= sizeV;
- memcpy(_vm->_global->_inter_variables + varOff, _pasteBuf + _pastePos, sizeV);
- memcpy(_vm->_global->_inter_variablesSizes + varOff, _pasteSizeBuf + _pastePos, sizeS);
+ _variables->copyFrom(varOff, _pasteBuf + _pastePos, _pasteSizeBuf + _pastePos, sizeV);
}
}
@@ -1434,46 +1427,17 @@ void Inter_v2::o2_initScreen() {
if (height > 0)
_vm->_video->_surfHeight = height;
- if (videoMode == 0x18) {
-
- if (_vm->_video->_surfWidth < _vm->_width)
- _vm->_video->_screenDeltaX = (_vm->_width - _vm->_video->_surfWidth) / 2;
- else
- _vm->_video->_screenDeltaX = 0;
-
- _vm->_global->_mouseMinX = _vm->_video->_screenDeltaX;
- _vm->_global->_mouseMaxX = _vm->_video->_screenDeltaX + _vm->_video->_surfWidth - 1;
-
-
- int16 screenHeight = _vm->_video->_surfHeight;
-
- _vm->_video->_surfHeight += offY;
+ _vm->_video->_splitHeight1 = MIN<int16>(_vm->_height, _vm->_video->_surfHeight - offY);
+ _vm->_video->_splitHeight2 = offY;
+ _vm->_video->_splitStart = _vm->_video->_surfHeight - offY;
- _vm->_video->_splitHeight1 = MIN<int16>(_vm->_height, screenHeight - offY);
- _vm->_video->_splitHeight2 = offY;
- _vm->_video->_splitStart = screenHeight;
+ _vm->_video->_screenDeltaX = 0;
+ _vm->_video->_screenDeltaY = 0;
- if ((_vm->_video->_surfHeight + offY) < _vm->_height)
- _vm->_video->_screenDeltaY = (_vm->_height - (screenHeight + offY)) / 2;
- else
- _vm->_video->_screenDeltaY = 0;
-
- _vm->_global->_mouseMaxY = (screenHeight + _vm->_video->_screenDeltaY) - offY - 1;
- _vm->_global->_mouseMinY = _vm->_video->_screenDeltaY;
-
- } else {
- _vm->_video->_splitHeight1 = MIN<int16>(_vm->_height, _vm->_video->_surfHeight - offY);
- _vm->_video->_splitHeight2 = offY;
- _vm->_video->_splitStart = _vm->_video->_surfHeight - offY;
-
- _vm->_video->_screenDeltaX = 0;
- _vm->_video->_screenDeltaY = 0;
-
- _vm->_global->_mouseMinX = 0;
- _vm->_global->_mouseMinY = 0;
- _vm->_global->_mouseMaxX = _vm->_width;
- _vm->_global->_mouseMaxY = _vm->_height - _vm->_video->_splitHeight2 - 1;
- }
+ _vm->_global->_mouseMinX = 0;
+ _vm->_global->_mouseMinY = 0;
+ _vm->_global->_mouseMaxX = _vm->_width;
+ _vm->_global->_mouseMaxY = _vm->_height - _vm->_video->_splitHeight2 - 1;
_vm->_draw->closeScreen();
_vm->_util->clearPalette();
@@ -1532,18 +1496,27 @@ void Inter_v2::o2_scroll() {
}
void Inter_v2::o2_setScrollOffset() {
- int16 offset;
+ int16 offsetX, offsetY;
- offset = _vm->_parse->parseValExpr();
+ offsetX = _vm->_parse->parseValExpr();
+ offsetY = _vm->_parse->parseValExpr();
- if (offset == -1) {
- _vm->_parse->parseValExpr();
+ if (offsetX == -1) {
WRITE_VAR(2, _vm->_draw->_scrollOffsetX);
WRITE_VAR(3, _vm->_draw->_scrollOffsetY);
} else {
- _vm->_draw->_scrollOffsetX = offset;
- _vm->_draw->_scrollOffsetY = _vm->_parse->parseValExpr();
+ int16 screenW = _vm->_video->_surfWidth;
+ int16 screenH = _vm->_video->_surfHeight;
+
+ if (screenW > _vm->_width)
+ screenW -= _vm->_width;
+ if (screenH > _vm->_height)
+ screenH -= _vm->_height;
+
+ _vm->_draw->_scrollOffsetX = CLIP<int16>(offsetX, 0, screenW);
+ _vm->_draw->_scrollOffsetY = CLIP<int16>(offsetY, 0, screenH);
}
+
_vm->_util->setScrollOffset();
_noBusyWait = true;
}
@@ -1574,8 +1547,12 @@ void Inter_v2::o2_playImd() {
palEnd = _vm->_parse->parseValExpr();
palCmd = 1 << (flags & 0x3F);
+ debugC(1, kDebugVideo, "Playing video \"%s\" @ %d+%d, frames %d - %d, "
+ "paletteCmd %d (%d - %d), flags %X", _vm->_global->_inter_resStr, x, y,
+ startFrame, lastFrame, palCmd, palStart, palEnd, flags);
+
if ((imd[0] != 0) && !_vm->_vidPlayer->primaryOpen(imd, x, y, flags)) {
- WRITE_VAR(11, -1);
+ WRITE_VAR(11, (uint32) -1);
return;
}
@@ -1607,6 +1584,12 @@ void Inter_v2::o2_getImdInfo() {
varWidth = _vm->_parse->parseVarIndex();
varHeight = _vm->_parse->parseVarIndex();
+ // WORKAROUND: The nut rolling animation in the administration center
+ // in Woodruff is called "noixroul", but the scripts think it's "noixroule".
+ if ((_vm->getGameType() == kGameTypeWoodruff) &&
+ (!scumm_stricmp(_vm->_global->_inter_resStr, "noixroule")))
+ strcpy(_vm->_global->_inter_resStr, "noixroul");
+
_vm->_vidPlayer->writeVideoInfo(_vm->_global->_inter_resStr, varX, varY,
varFrames, varWidth, varHeight);
}
@@ -1883,10 +1866,9 @@ bool Inter_v2::o2_stopSound(OpFuncParams &params) {
expr = _vm->_parse->parseValExpr();
if (expr < 0) {
- if (_vm->_adlib)
- _vm->_adlib->stopPlay();
+ _vm->_sound->adlibStop();
} else
- _vm->_snd->stopSound(expr);
+ _vm->_sound->blasterStop(expr);
_soundEndTimeKey = 0;
return false;
@@ -1915,7 +1897,7 @@ bool Inter_v2::o2_checkData(OpFuncParams &params) {
int16 handle;
int16 varOff;
int32 size;
- SaveType type;
+ SaveLoad::SaveMode mode;
evalExpr(0);
varOff = _vm->_parse->parseVarIndex();
@@ -1923,8 +1905,8 @@ bool Inter_v2::o2_checkData(OpFuncParams &params) {
size = -1;
handle = 1;
- type = _vm->_saveLoad->getSaveType(_vm->_global->_inter_resStr);
- if (type == kSaveNone) {
+ mode = _vm->_saveLoad->getSaveMode(_vm->_global->_inter_resStr);
+ if (mode == SaveLoad::kSaveModeNone) {
handle = _vm->_dataIO->openData(_vm->_global->_inter_resStr);
if (handle >= 0) {
@@ -1932,8 +1914,8 @@ bool Inter_v2::o2_checkData(OpFuncParams &params) {
size = _vm->_dataIO->getDataSize(_vm->_global->_inter_resStr);
} else
warning("File \"%s\" not found", _vm->_global->_inter_resStr);
- } else
- size = _vm->_saveLoad->getSize(type);
+ } else if (mode == SaveLoad::kSaveModeSave)
+ size = _vm->_saveLoad->getSize(_vm->_global->_inter_resStr);
if (size == -1)
handle = -1;
@@ -1954,7 +1936,7 @@ bool Inter_v2::o2_readData(OpFuncParams &params) {
int16 dataVar;
int16 handle;
byte *buf;
- SaveType type;
+ SaveLoad::SaveMode mode;
evalExpr(0);
dataVar = _vm->_parse->parseVarIndex();
@@ -1966,13 +1948,14 @@ bool Inter_v2::o2_readData(OpFuncParams &params) {
debugC(2, kDebugFileIO, "Read from file \"%s\" (%d, %d bytes at %d)",
_vm->_global->_inter_resStr, dataVar, size, offset);
- type = _vm->_saveLoad->getSaveType(_vm->_global->_inter_resStr);
- if (type != kSaveNone) {
+ mode = _vm->_saveLoad->getSaveMode(_vm->_global->_inter_resStr);
+ if (mode == SaveLoad::kSaveModeSave) {
WRITE_VAR(1, 1);
- if (_vm->_saveLoad->load(type, dataVar, size, offset))
+ if (_vm->_saveLoad->load(_vm->_global->_inter_resStr, dataVar, size, offset))
WRITE_VAR(1, 0);
return false;
- }
+ } else if (mode == SaveLoad::kSaveModeIgnore)
+ return false;
if (size < 0) {
warning("Attempted to read a raw sprite from file \"%s\"",
@@ -1983,8 +1966,7 @@ bool Inter_v2::o2_readData(OpFuncParams &params) {
size = READ_LE_UINT32(_vm->_game->_totFileData + 0x2C) * 4;
}
- buf = _vm->_global->_inter_variables + dataVar;
- memset(_vm->_global->_inter_variablesSizes + dataVar, 0, size);
+ buf = _variables->getAddressOff8(dataVar, size);
if (_vm->_global->_inter_resStr[0] == 0) {
WRITE_VAR(1, size);
@@ -2009,7 +1991,7 @@ bool Inter_v2::o2_readData(OpFuncParams &params) {
WRITE_VAR(59, stream->readUint32LE());
// The scripts in some versions divide through 256^3 then,
// effectively doing a LE->BE conversion
- if ((_vm->_platform != Common::kPlatformPC) && (VAR(59) < 256))
+ if ((_vm->getPlatform() != Common::kPlatformPC) && (VAR(59) < 256))
WRITE_VAR(59, SWAP_BYTES_32(VAR(59)));
} else
retSize = stream->read(buf, size);
@@ -2025,7 +2007,7 @@ bool Inter_v2::o2_writeData(OpFuncParams &params) {
int32 offset;
int32 size;
int16 dataVar;
- SaveType type;
+ SaveLoad::SaveMode mode;
evalExpr(0);
dataVar = _vm->_parse->parseVarIndex();
@@ -2038,11 +2020,11 @@ bool Inter_v2::o2_writeData(OpFuncParams &params) {
WRITE_VAR(1, 1);
- type = _vm->_saveLoad->getSaveType(_vm->_global->_inter_resStr);
- if (type != kSaveNone) {
- if (_vm->_saveLoad->save(type, dataVar, size, offset))
+ mode = _vm->_saveLoad->getSaveMode(_vm->_global->_inter_resStr);
+ if (mode == SaveLoad::kSaveModeSave) {
+ if (_vm->_saveLoad->save(_vm->_global->_inter_resStr, dataVar, size, offset))
WRITE_VAR(1, 0);
- } else
+ } else if (mode == SaveLoad::kSaveModeNone)
warning("Attempted to write to file \"%s\"", _vm->_global->_inter_resStr);
return false;
@@ -2054,29 +2036,10 @@ void Inter_v2::o2_loadInfogramesIns(OpGobParams &params) {
varName = load16();
- if (_vm->_noMusic)
- return;
-
strncpy0(fileName, GET_VAR_STR(varName), 15);
strcat(fileName, ".INS");
- debugC(1, kDebugMusic, "Loading Infogrames instrument file \"%s\"",
- fileName);
-
- if (_vm->_game->_infogrames) {
- _vm->_mixer->stopHandle(_vm->_game->_infHandle);
- delete _vm->_game->_infogrames;
- _vm->_game->_infogrames = 0;
- }
-
- if (_vm->_game->_infIns)
- delete _vm->_game->_infIns;
- _vm->_game->_infIns = new Audio::Infogrames::Instruments;
- if (!_vm->_game->_infIns->load(fileName)) {
- warning("Couldn't load instruments file");
- delete _vm->_game->_infIns;
- _vm->_game->_infIns = 0;
- }
+ _vm->_sound->infogramesLoadInstruments(fileName);
}
void Inter_v2::o2_playInfogrames(OpGobParams &params) {
@@ -2085,58 +2048,23 @@ void Inter_v2::o2_playInfogrames(OpGobParams &params) {
varName = load16();
- if (_vm->_noMusic)
- return;
-
strncpy0(fileName, GET_VAR_STR(varName), 15);
strcat(fileName, ".DUM");
- debugC(1, kDebugMusic, "Playing Infogrames music file \"%s\"", fileName);
- if (!_vm->_game->_infIns) {
- _vm->_game->_infIns = new Audio::Infogrames::Instruments;
-
- if (!_vm->_game->_infIns->load("i1.ins")) {
- warning("Couldn't load instruments file");
- delete _vm->_game->_infIns;
- _vm->_game->_infIns = 0;
- }
- }
-
- if (_vm->_game->_infIns) {
- _vm->_mixer->stopHandle(_vm->_game->_infHandle);
- delete _vm->_game->_infogrames;
- _vm->_game->_infogrames =
- new Audio::Infogrames(*_vm->_game->_infIns, true,
- _vm->_mixer->getOutputRate(),
- _vm->_mixer->getOutputRate() / 75);
-
- if (!_vm->_game->_infogrames->load(fileName)) {
- warning("Couldn't load infogrames music");
- delete _vm->_game->_infogrames;
- _vm->_game->_infogrames = 0;
- } else
- _vm->_mixer->playInputStream(Audio::Mixer::kMusicSoundType,
- &_vm->_game->_infHandle, _vm->_game->_infogrames,
- -1, 255, 0, false);
- }
+ _vm->_sound->infogramesLoadSong(fileName);
+ _vm->_sound->infogramesPlay();
}
void Inter_v2::o2_startInfogrames(OpGobParams &params) {
load16();
- if (_vm->_game->_infogrames &&
- !_vm->_mixer->isSoundHandleActive(_vm->_game->_infHandle)) {
- _vm->_game->_infogrames->restart();
- _vm->_mixer->playInputStream(Audio::Mixer::kMusicSoundType,
- &_vm->_game->_infHandle, _vm->_game->_infogrames,
- -1, 255, 0, false);
- }
+ _vm->_sound->infogramesPlay();
}
void Inter_v2::o2_stopInfogrames(OpGobParams &params) {
load16();
- _vm->_mixer->stopHandle(_vm->_game->_infHandle);
+ _vm->_sound->infogramesStop();
}
void Inter_v2::o2_handleGoblins(OpGobParams &params) {
@@ -2172,15 +2100,15 @@ int16 Inter_v2::loadSound(int16 search) {
} else {
id = load16();
- for (slot = 0; slot < 60; slot++)
- if (_vm->_game->_soundSamples[slot].isId(id)) {
+ for (slot = 0; slot < Sound::kSoundsCount; slot++)
+ if (_vm->_sound->sampleGetBySlot(slot)->isId(id)) {
slotIdMask = 0x8000;
break;
}
- if (slot == 60) {
- for (slot = 59; slot >= 0; slot--) {
- if (_vm->_game->_soundSamples[slot].empty())
+ if (slot == Sound::kSoundsCount) {
+ for (slot = (Sound::kSoundsCount - 1); slot >= 0; slot--) {
+ if (_vm->_sound->sampleGetBySlot(slot)->empty())
break;
}
@@ -2192,7 +2120,9 @@ int16 Inter_v2::loadSound(int16 search) {
}
}
- _vm->_game->freeSoundSlot(slot);
+ SoundDesc *sample = _vm->_sound->sampleGetBySlot(slot);
+
+ _vm->_sound->sampleFree(sample, true, slot);
if (id == -1) {
char sndfile[14];
@@ -2224,8 +2154,8 @@ int16 Inter_v2::loadSound(int16 search) {
}
if (dataPtr) {
- _vm->_game->_soundSamples[slot].load(type, source, dataPtr, dataSize);
- _vm->_game->_soundSamples[slot]._id = id;
+ sample->load(type, source, dataPtr, dataSize);
+ sample->_id = id;
}
return slot | slotIdMask;
diff --git a/engines/gob/inter_v4.cpp b/engines/gob/inter_v4.cpp
index b24e54ffbd..fb895dd5b2 100644
--- a/engines/gob/inter_v4.cpp
+++ b/engines/gob/inter_v4.cpp
@@ -29,9 +29,11 @@
#include "gob/gob.h"
#include "gob/inter.h"
#include "gob/global.h"
+#include "gob/draw.h"
#include "gob/game.h"
#include "gob/parse.h"
#include "gob/videoplayer.h"
+#include "gob/sound/sound.h"
namespace Gob {
@@ -278,7 +280,7 @@ void Inter_v4::setupOpcodes() {
{NULL, ""},
{NULL, ""},
/* 80 */
- OPCODE(o2_initScreen),
+ OPCODE(o4_initScreen),
OPCODE(o2_scroll),
OPCODE(o2_setScrollOffset),
OPCODE(o4_playVmdOrMusic),
@@ -503,7 +505,7 @@ void Inter_v4::setupOpcodes() {
/* 30 */
OPCODE(o1_returnTo),
OPCODE(o1_loadSpriteContent),
- OPCODE(o3_copySprite),
+ OPCODE(o1_copySprite),
OPCODE(o1_fillRect),
/* 34 */
OPCODE(o1_drawLine),
@@ -641,7 +643,7 @@ void Inter_v4::setupOpcodes() {
void Inter_v4::executeDrawOpcode(byte i) {
debugC(1, kDebugDrawOp, "opcodeDraw %d [0x%X] (%s)",
- i, i, getOpcodeDrawDesc(i));
+ i, i, getOpcodeDrawDesc(i));
OpcodeDrawProcV4 op = _opcodesDrawV4[i].proc;
@@ -652,8 +654,10 @@ void Inter_v4::executeDrawOpcode(byte i) {
}
bool Inter_v4::executeFuncOpcode(byte i, byte j, OpFuncParams &params) {
- debugC(1, kDebugFuncOp, "opcodeFunc %d.%d [0x%X.0x%X] (%s)",
- i, j, i, j, getOpcodeFuncDesc(i, j));
+ debugC(1, kDebugFuncOp, "opcodeFunc %d.%d [0x%X.0x%X] (%s) - %s, %d, %d",
+ i, j, i, j, getOpcodeFuncDesc(i, j), _vm->_game->_curTotFile,
+ (uint) (_vm->_global->_inter_execPtr - _vm->_game->_totFileData),
+ (uint) (_vm->_global->_inter_execPtr - _vm->_game->_totFileData - params.counter - 4));
if ((i > 4) || (j > 15)) {
warning("unimplemented opcodeFunc: %d.%d", i, j);
@@ -672,7 +676,7 @@ bool Inter_v4::executeFuncOpcode(byte i, byte j, OpFuncParams &params) {
void Inter_v4::executeGoblinOpcode(int i, OpGobParams &params) {
debugC(1, kDebugGobOp, "opcodeGoblin %d [0x%X] (%s)",
- i, i, getOpcodeGoblinDesc(i));
+ i, i, getOpcodeGoblinDesc(i));
OpcodeGoblinProcV4 op = NULL;
@@ -683,6 +687,8 @@ void Inter_v4::executeGoblinOpcode(int i, OpGobParams &params) {
}
if (op == NULL) {
+ warning("unimplemented opcodeGoblin: %d", i);
+
int16 val;
_vm->_global->_inter_execPtr -= 2;
@@ -710,6 +716,86 @@ const char *Inter_v4::getOpcodeGoblinDesc(int i) {
return "";
}
+void Inter_v4::o4_initScreen() {
+ int16 offY;
+ int16 videoMode;
+ int16 width, height;
+
+ offY = load16();
+
+ videoMode = offY & 0xFF;
+ offY = (offY >> 8) & 0xFF;
+
+ width = _vm->_parse->parseValExpr();
+ height = _vm->_parse->parseValExpr();
+
+ _vm->_video->clearScreen();
+
+ _vm->_global->_fakeVideoMode = videoMode;
+
+ // Some versions require this
+ if (videoMode == 0xD)
+ videoMode = _vm->_mode;
+
+ if ((videoMode == _vm->_global->_videoMode) && (width == -1))
+ return;
+
+ if (width > 0)
+ _vm->_video->_surfWidth = width;
+ if (height > 0)
+ _vm->_video->_surfHeight = height;
+
+ _vm->_video->_screenDeltaX = 0;
+ if (_vm->_video->_surfWidth < _vm->_width)
+ _vm->_video->_screenDeltaX = (_vm->_width - _vm->_video->_surfWidth) / 2;
+
+ _vm->_global->_mouseMinX = _vm->_video->_screenDeltaX;
+ _vm->_global->_mouseMaxX = _vm->_video->_screenDeltaX + _vm->_video->_surfWidth - 1;
+
+ _vm->_video->_splitStart = _vm->_video->_surfHeight - offY;
+
+ _vm->_video->_splitHeight1 = MIN<int16>(_vm->_height, _vm->_video->_surfHeight);
+ _vm->_video->_splitHeight2 = offY;
+
+ if ((_vm->_video->_surfHeight + offY) < _vm->_height)
+ _vm->_video->_screenDeltaY = (_vm->_height - (_vm->_video->_surfHeight + offY)) / 2;
+ else
+ _vm->_video->_screenDeltaY = 0;
+
+ _vm->_global->_mouseMaxY = (_vm->_video->_surfHeight + _vm->_video->_screenDeltaY) - offY - 1;
+ _vm->_global->_mouseMinY = _vm->_video->_screenDeltaY;
+
+ _vm->_draw->closeScreen();
+ _vm->_util->clearPalette();
+ memset(_vm->_global->_redPalette, 0, 256);
+ memset(_vm->_global->_greenPalette, 0, 256);
+ memset(_vm->_global->_bluePalette, 0, 256);
+
+ _vm->_video->_splitSurf = 0;
+ _vm->_draw->_spritesArray[24] = 0;
+ _vm->_draw->_spritesArray[25] = 0;
+
+ _vm->_global->_videoMode = videoMode;
+ _vm->_video->initPrimary(videoMode);
+ WRITE_VAR(15, _vm->_global->_fakeVideoMode);
+
+ _vm->_global->_setAllPalette = true;
+
+ _vm->_util->setMousePos(_vm->_global->_inter_mouseX,
+ _vm->_global->_inter_mouseY);
+ _vm->_util->clearPalette();
+
+ _vm->_draw->initScreen();
+
+ _vm->_util->setScrollOffset();
+
+ if (offY > 0) {
+ _vm->_draw->_spritesArray[24] = new SurfaceDesc(videoMode, _vm->_width, offY);
+ _vm->_draw->_spritesArray[25] = new SurfaceDesc(videoMode, _vm->_width, offY);
+ _vm->_video->_splitSurf = _vm->_draw->_spritesArray[25];
+ }
+}
+
void Inter_v4::o4_playVmdOrMusic() {
char fileName[128];
int16 x, y;
@@ -725,6 +811,12 @@ void Inter_v4::o4_playVmdOrMusic() {
evalExpr(0);
strncpy0(fileName, _vm->_global->_inter_resStr, 127);
+ // WORKAROUND: The nut rolling animation in the administration center
+ // in Woodruff is called "noixroul", but the scripts think it's "noixroule".
+ if ((_vm->getGameType() == kGameTypeWoodruff) &&
+ (!scumm_stricmp(fileName, "noixroule")))
+ strcpy(fileName, "noixroul");
+
x = _vm->_parse->parseValExpr();
y = _vm->_parse->parseValExpr();
startFrame = _vm->_parse->parseValExpr();
@@ -735,11 +827,14 @@ void Inter_v4::o4_playVmdOrMusic() {
palEnd = _vm->_parse->parseValExpr();
palCmd = 1 << (flags & 0x3F);
+ debugC(1, kDebugVideo, "Playing video \"%s\" @ %d+%d, frames %d - %d, "
+ "paletteCmd %d (%d - %d), flags %X", fileName, x, y, startFrame, lastFrame,
+ palCmd, palStart, palEnd, flags);
+
close = false;
if (lastFrame == -1) {
close = true;
} else if (lastFrame == -3) {
- warning("Woodruff Stub: Video/Music command -3: Play background video %s, %d, %d, %d, %d", fileName, startFrame, x, y, VAR_OFFSET(7872));
_vm->_mult->_objects[startFrame].pAnimData->animation = -startFrame - 1;
@@ -763,16 +858,19 @@ void Inter_v4::o4_playVmdOrMusic() {
warning("Woodruff Stub: Video/Music command -4: Play background video %s", fileName);
return;
} else if (lastFrame == -5) {
- warning("Woodruff Stub: Video/Music command -5: Stop background music");
+ _vm->_sound->bgStop();
return;
} else if (lastFrame == -6) {
- warning("Woodruff Stub: Video/Music command -6: Load background video %s", fileName);
+ return;
+ } else if (lastFrame == -7) {
return;
} else if (lastFrame == -8) {
warning("Woodruff Stub: Video/Music command -8: Play background video %s", fileName);
return;
} else if (lastFrame == -9) {
- warning("Woodruff Stub: Video/Music command -9: Play background music %s (%d-%d)", fileName, palEnd, palStart);
+ _vm->_sound->bgStop();
+ _vm->_sound->bgSetPlayMode(BackgroundAtmosphere::kPlayModeRandom);
+ _vm->_sound->bgPlay(fileName, palStart);
return;
} else if (lastFrame < 0) {
warning("Unknown Video/Music command: %d, %s", lastFrame, fileName);
@@ -785,7 +883,7 @@ void Inter_v4::o4_playVmdOrMusic() {
}
if ((fileName[0] != 0) && !_vm->_vidPlayer->primaryOpen(fileName, x, y, flags)) {
- WRITE_VAR(11, -1);
+ WRITE_VAR(11, (uint32) -1);
return;
}
diff --git a/engines/gob/map.cpp b/engines/gob/map.cpp
index cd8f9e3758..75867aaa6c 100644
--- a/engines/gob/map.cpp
+++ b/engines/gob/map.cpp
@@ -23,8 +23,6 @@
*
*/
-
-
#include "gob/gob.h"
#include "gob/map.h"
#include "gob/goblin.h"
diff --git a/engines/gob/map_v1.cpp b/engines/gob/map_v1.cpp
index c4b68fad85..4ac99d2465 100644
--- a/engines/gob/map_v1.cpp
+++ b/engines/gob/map_v1.cpp
@@ -23,15 +23,14 @@
*
*/
-
#include "common/stream.h"
#include "gob/gob.h"
#include "gob/map.h"
#include "gob/dataio.h"
#include "gob/goblin.h"
-#include "gob/sound.h"
#include "gob/mult.h"
+#include "gob/sound/sound.h"
namespace Gob {
@@ -160,7 +159,7 @@ void Map_v1::loadSounds(Common::SeekableReadStream &data) {
strcpy(sndNames[i], buf);
}
- _vm->_snd->loadSample(_vm->_goblin->_soundData[14], "diamant1.snd");
+ _vm->_sound->sampleLoad(&_vm->_goblin->_soundData[14], "diamant1.snd");
for (int i = 0; i < count; i++) {
handle = _vm->_dataIO->openData(sndNames[i]);
@@ -168,7 +167,7 @@ void Map_v1::loadSounds(Common::SeekableReadStream &data) {
continue;
_vm->_dataIO->closeData(handle);
- _vm->_snd->loadSample(_vm->_goblin->_soundData[i], sndNames[i]);
+ _vm->_sound->sampleLoad(&_vm->_goblin->_soundData[i], sndNames[i]);
}
}
diff --git a/engines/gob/map_v2.cpp b/engines/gob/map_v2.cpp
index 2c383f5bb2..bd9f5b3efc 100644
--- a/engines/gob/map_v2.cpp
+++ b/engines/gob/map_v2.cpp
@@ -23,7 +23,6 @@
*
*/
-
#include "common/stream.h"
#include "gob/gob.h"
@@ -57,12 +56,12 @@ void Map_v2::loadMapObjects(const char *avjFile) {
uint32 passPos;
var = _vm->_parse->parseVarIndex();
- variables = _vm->_global->_inter_variables + var;
+ variables = _vm->_inter->_variables->getAddressOff8(var, 0);
id = _vm->_inter->load16();
if (id == -1) {
- _passMap = (int8 *)(_vm->_global->_inter_variables + var);
+ _passMap = (int8 *) _vm->_inter->_variables->getAddressOff8(var, 0);
return;
}
@@ -105,18 +104,17 @@ void Map_v2::loadMapObjects(const char *avjFile) {
// In the original asm, this writes byte-wise into the variables-array
tmpPos = mapData.pos();
mapData.seek(passPos);
- if (variables != _vm->_global->_inter_variables) {
- byte *sizes;
+ if ((variables != 0) &&
+ (variables != _vm->_inter->_variables->getAddressOff8(0, 0))) {
_passMap = (int8 *) variables;
mapHeight = _screenHeight / _tilesHeight;
mapWidth = _screenWidth / _tilesWidth;
- sizes = _vm->_global->_inter_variablesSizes +
- (((byte *) _passMap) - _vm->_global->_inter_variables);
+
for (int i = 0; i < mapHeight; i++) {
for (int j = 0; j < mapWidth; j++)
setPass(j, i, mapData.readSByte());
- memset(sizes + i * _passWidth, 0, mapWidth);
+ _vm->_inter->_variables->getAddressOff8(var + i * _passWidth, mapWidth);
}
}
mapData.seek(tmpPos);
diff --git a/engines/gob/map_v4.cpp b/engines/gob/map_v4.cpp
index 721f040341..3a74c4b6aa 100644
--- a/engines/gob/map_v4.cpp
+++ b/engines/gob/map_v4.cpp
@@ -54,7 +54,7 @@ void Map_v4::loadMapObjects(const char *avjFile) {
uint32 passPos;
var = _vm->_parse->parseVarIndex();
- variables = _vm->_global->_inter_variables + var;
+ variables = _vm->_inter->_variables->getAddressOff8(var, 0);
id = _vm->_inter->load16();
@@ -62,7 +62,7 @@ void Map_v4::loadMapObjects(const char *avjFile) {
warning("Woodruff Stub: loadMapObjects ID >= 65520");
return;
} else if (id == -1) {
- _passMap = (int8 *)(_vm->_global->_inter_variables + var);
+ _passMap = (int8 *) _vm->_inter->_variables->getAddressOff8(var, 0);
return;
}
@@ -113,25 +113,24 @@ void Map_v4::loadMapObjects(const char *avjFile) {
}
if (_widthByte == 4)
- _mapWidth = (int16) READ_VARO_UINT16(68);
+ _mapWidth = VAR(17);
_passWidth = _mapWidth;
// In the original asm, this writes byte-wise into the variables-array
tmpPos = mapData.pos();
mapData.seek(passPos);
- if (variables != _vm->_global->_inter_variables) {
- byte *sizes;
+ if ((variables != 0) &&
+ (variables != _vm->_inter->_variables->getAddressOff8(0, 0))) {
_passMap = (int8 *) variables;
mapHeight = _screenHeight / _tilesHeight;
mapWidth = _screenWidth / _tilesWidth;
- sizes = _vm->_global->_inter_variablesSizes +
- (((byte *) _passMap) - _vm->_global->_inter_variables);
+
for (int i = 0; i < mapHeight; i++) {
for (int j = 0; j < mapWidth; j++)
setPass(j, i, mapData.readSByte());
- memset(sizes + i * _passWidth, 0, mapWidth);
+ _vm->_inter->_variables->getAddressOff8(var + i * _passWidth, mapWidth);
}
}
mapData.seek(tmpPos);
diff --git a/engines/gob/module.mk b/engines/gob/module.mk
index aa2a235327..45048a0899 100644
--- a/engines/gob/module.mk
+++ b/engines/gob/module.mk
@@ -1,7 +1,6 @@
MODULE := engines/gob
MODULE_OBJS := \
- cdrom.o \
dataio.o \
detection.o \
draw.o \
@@ -38,7 +37,6 @@ MODULE_OBJS := \
mult.o \
mult_v1.o \
mult_v2.o \
- music.o \
palanim.o \
parse.o \
parse_v1.o \
@@ -46,14 +44,24 @@ MODULE_OBJS := \
saveload.o \
saveload_v2.o \
saveload_v3.o \
+ saveload_v4.o \
scenery.o \
scenery_v1.o \
scenery_v2.o \
- sound.o \
util.o \
+ variables.o \
video.o \
video_v1.o \
- video_v2.o
+ video_v2.o \
+ sound/sound.o \
+ sound/sounddesc.o \
+ sound/pcspeaker.o \
+ sound/adlib.o \
+ sound/infogrames.o \
+ sound/soundmixer.o \
+ sound/soundblaster.o \
+ sound/cdrom.o \
+ sound/bgatmosphere.o
# This module can be built as a plugin
ifeq ($(ENABLE_GOB), DYNAMIC_PLUGIN)
diff --git a/engines/gob/mult.cpp b/engines/gob/mult.cpp
index 70b6d33136..3d6a7942f9 100644
--- a/engines/gob/mult.cpp
+++ b/engines/gob/mult.cpp
@@ -23,7 +23,6 @@
*
*/
-
#include "common/endian.h"
#include "gob/gob.h"
@@ -34,9 +33,10 @@
#include "gob/game.h"
#include "gob/palanim.h"
#include "gob/scenery.h"
-#include "gob/sound.h"
#include "gob/video.h"
#include "gob/videoplayer.h"
+#include "gob/inter.h"
+#include "gob/sound/sound.h"
namespace Gob {
@@ -188,7 +188,7 @@ void Mult::playMult(int16 startFrame, int16 endFrame, char checkEscape,
if (_frame >= endFrame)
stopNoClear = true;
- if (_vm->_snd->_playingSound)
+ if (_vm->_sound->blasterPlayingSound())
stop = false;
_vm->_util->processInput();
@@ -225,8 +225,8 @@ void Mult::playMult(int16 startFrame, int16 endFrame, char checkEscape,
_animDataAllocated = false;
}
- if (_vm->_snd->_playingSound)
- _vm->_snd->stopSound(10);
+ if (_vm->_sound->blasterPlayingSound())
+ _vm->_sound->blasterStop(10);
WRITE_VAR(57, (uint32) -1);
} else
@@ -415,21 +415,24 @@ void Mult::doSoundAnim(bool &stop, int16 frame) {
if (sndKey->cmd != -1) {
if ((sndKey->cmd == 1) || (sndKey->cmd == 4)) {
- SoundDesc &sample = _vm->_game->_soundSamples[sndKey->soundIndex];
+ SoundDesc *sample = _vm->_sound->sampleGetBySlot(sndKey->soundIndex);
- _vm->_snd->stopSound(0);
- if (!sample.empty())
- _vm->_snd->playSample(sample, sndKey->repCount,
+ _vm->_sound->blasterStop(0);
+ if (sample && !sample->empty())
+ _vm->_sound->blasterPlay(sample, sndKey->repCount,
sndKey->freq, sndKey->fadeLength);
}
} else {
- if (_vm->_snd->_playingSound)
- _vm->_snd->stopSound(sndKey->fadeLength);
+ if (_vm->_sound->blasterPlayingSound())
+ _vm->_sound->blasterStop(sndKey->fadeLength);
}
}
}
void Mult::clearObjectVideos() {
+ if (!_objects)
+ return;
+
for (int i = 0; i < _objCount; i++)
if (_objects[i].videoSlot > 0)
_vm->_vidPlayer->slotClose(_objects[i].videoSlot - 1);
diff --git a/engines/gob/mult.h b/engines/gob/mult.h
index c283191ec8..aaf2e2826c 100644
--- a/engines/gob/mult.h
+++ b/engines/gob/mult.h
@@ -40,7 +40,7 @@ public:
uint8 layer;
uint8 frame;
int8 animType;
- uint8 order;
+ int8 order;
int8 isPaused;
int8 isStatic;
int8 maxTick;
@@ -229,7 +229,7 @@ public:
int16 *_renderData;
Mult_Object **_renderObjs;
- uint8 *_orderArray;
+ int8 *_orderArray;
SurfaceDesc::Ptr _animSurf;
int16 _animLeft;
diff --git a/engines/gob/mult_v1.cpp b/engines/gob/mult_v1.cpp
index 78071f1dd8..22683437e7 100644
--- a/engines/gob/mult_v1.cpp
+++ b/engines/gob/mult_v1.cpp
@@ -23,7 +23,6 @@
*
*/
-
#include "common/endian.h"
#include "common/stream.h"
diff --git a/engines/gob/mult_v2.cpp b/engines/gob/mult_v2.cpp
index 02211880ba..3a83ac1867 100644
--- a/engines/gob/mult_v2.cpp
+++ b/engines/gob/mult_v2.cpp
@@ -23,7 +23,6 @@
*
*/
-
#include "common/endian.h"
#include "common/stream.h"
@@ -526,14 +525,14 @@ void Mult_v2::playMultInit() {
delete[] _animArrayData;
_objects = new Mult_Object[_objCount];
- _orderArray = new uint8[_objCount];
+ _orderArray = new int8[_objCount];
_renderObjs = new Mult_Object*[_objCount];
_animArrayX = new int32[_objCount];
_animArrayY = new int32[_objCount];
_animArrayData = new Mult_AnimData[_objCount];
memset(_objects, 0, _objCount * sizeof(Mult_Object));
- memset(_orderArray, 0, _objCount * sizeof(uint8));
+ memset(_orderArray, 0, _objCount * sizeof(int8));
memset(_renderObjs, 0, _objCount * sizeof(Mult_Object *));
memset(_animArrayX, 0, _objCount * sizeof(int32));
memset(_animArrayY, 0, _objCount * sizeof(int32));
@@ -686,6 +685,11 @@ void Mult_v2::newCycleAnim(Mult_Object &animObj) {
return;
animLayer = _vm->_scenery->getAnimLayer(nAnim, nLayer);
+ } else {
+ if (animObj.videoSlot > 0) {
+ _vm->_video->retrace();
+ _vm->_vidPlayer->slotWaitEndFrame(animObj.videoSlot - 1, true);
+ }
}
if (animData.animType == 4) {
@@ -693,7 +697,7 @@ void Mult_v2::newCycleAnim(Mult_Object &animObj) {
animData.frame = 0;
animData.isPaused = 1;
if (animData.animation < 0)
- warning("TODO: AnimType 4, animation: %d", animData.animation);
+ warning("Woodruff Stub: AnimType 4, animation: %d", animData.animation);
return;
}
@@ -701,9 +705,8 @@ void Mult_v2::newCycleAnim(Mult_Object &animObj) {
animData.animType = 11;
if (animData.animType == 11) {
- if (animData.isBusy != 0) {
- warning("TODO: AnimType 11");
- }
+ if (animData.isBusy != 0)
+ warning("Woodruff Stub: AnimType 11");
return;
}
@@ -750,27 +753,39 @@ void Mult_v2::newCycleAnim(Mult_Object &animObj) {
case 5:
animData.isStatic = 1;
animData.frame = 0;
+ if ((animData.animation < 0) && (animObj.videoSlot > 0)) {
+ _vm->_vidPlayer->slotClose(animObj.videoSlot - 1);
+ animObj.videoSlot = 0;
+ }
+
break;
case 6:
case 7:
animData.frame--;
animData.isPaused = 1;
+/*
if ((animData.animation < 0) && (animObj.videoSlot > 0)) {
if (_vm->_vidPlayer->getFlags(animObj.videoSlot - 1) & 0x1000) {
_vm->_vidPlayer->slotClose(animObj.videoSlot - 1);
animObj.videoSlot = 0;
}
}
+*/
+ break;
+
+ case 10:
+ warning("Woodruff Stub: AnimType 10");
break;
}
+
animData.newCycle = 1;
}
void Mult_v2::animate() {
- uint8 minOrder = 100;
- uint8 maxOrder = 0;
- uint8 *orderArray;
+ int8 minOrder = 100;
+ int8 maxOrder = 0;
+ int8 *orderArray;
int orderArrayPos = 0;
int8 animIndices[150];
int numAnims = 0;
@@ -952,60 +967,58 @@ void Mult_v2::animate() {
Mult_Object &animObj1 = *_renderObjs[orderArray[i]];
Mult_AnimData &animData1 = *(animObj1.pAnimData);
- if (!animObj1.needRedraw && !animData1.isStatic) {
- for (int j = 0; j < orderArrayPos; j++) {
- Mult_Object &animObj2 = *_renderObjs[orderArray[j]];
+ if (!animObj1.needRedraw) {
- if (!animObj2.needRedraw)
- continue;
+ if (!animData1.isStatic) {
+ for (int j = 0; j < orderArrayPos; j++) {
+ Mult_Object &animObj2 = *_renderObjs[orderArray[j]];
+
+ if (!animObj2.needRedraw)
+ continue;
- if ((animObj1.newRight >= animObj2.newLeft) &&
- (animObj2.newRight >= animObj1.newLeft) &&
- (animObj1.newBottom >= animObj2.newTop) &&
- (animObj2.newBottom >= animObj1.newTop)) {
+ if ((animObj1.newRight >= animObj2.newLeft) &&
+ (animObj2.newRight >= animObj1.newLeft) &&
+ (animObj1.newBottom >= animObj2.newTop) &&
+ (animObj2.newBottom >= animObj1.newTop)) {
- _vm->_scenery->_toRedrawLeft = animObj2.newLeft;
- _vm->_scenery->_toRedrawRight = animObj2.newRight;
- _vm->_scenery->_toRedrawTop = animObj2.newTop;
- _vm->_scenery->_toRedrawBottom = animObj2.newBottom;
+ _vm->_scenery->_toRedrawLeft = animObj2.newLeft;
+ _vm->_scenery->_toRedrawRight = animObj2.newRight;
+ _vm->_scenery->_toRedrawTop = animObj2.newTop;
+ _vm->_scenery->_toRedrawBottom = animObj2.newBottom;
- _vm->_scenery->updateAnim(animData1.layer, animData1.frame,
- animData1.animation, 12, *animObj1.pPosX, *animObj1.pPosY, 1);
- _vm->_scenery->updateStatic(animData1.order + 1);
+ _vm->_scenery->updateAnim(animData1.layer, animData1.frame,
+ animData1.animation, 12, *animObj1.pPosX, *animObj1.pPosY, 1);
+ _vm->_scenery->updateStatic(animData1.order + 1);
+ }
}
}
- } else if (!animData1.isStatic) {
- _vm->_scenery->updateAnim(animData1.layer, animData1.frame,
- animData1.animation, 10, *animObj1.pPosX, *animObj1.pPosY, 1);
-
- if (_vm->_scenery->_toRedrawLeft != -12345) {
- if (_vm->_global->_pressedKeys[0x36]) {
- _vm->_video->drawLine(_vm->_draw->_frontSurface,
- _vm->_scenery->_toRedrawLeft, _vm->_scenery->_toRedrawTop,
- _vm->_scenery->_toRedrawRight, _vm->_scenery->_toRedrawTop, 15);
- _vm->_video->drawLine(_vm->_draw->_frontSurface,
- _vm->_scenery->_toRedrawLeft, _vm->_scenery->_toRedrawBottom,
- _vm->_scenery->_toRedrawRight, _vm->_scenery->_toRedrawBottom, 15);
- _vm->_video->drawLine(_vm->_draw->_frontSurface,
- _vm->_scenery->_toRedrawLeft, _vm->_scenery->_toRedrawTop,
- _vm->_scenery->_toRedrawLeft, _vm->_scenery->_toRedrawBottom, 15);
- _vm->_video->drawLine(_vm->_draw->_frontSurface,
- _vm->_scenery->_toRedrawRight, _vm->_scenery->_toRedrawTop,
- _vm->_scenery->_toRedrawRight, _vm->_scenery->_toRedrawBottom, 15);
- }
- animObj1.lastLeft = _vm->_scenery->_toRedrawLeft;
- animObj1.lastRight = _vm->_scenery->_toRedrawRight;
- animObj1.lastTop = _vm->_scenery->_toRedrawTop;
- animObj1.lastBottom = _vm->_scenery->_toRedrawBottom;
- } else
- animObj1.lastLeft = -1;
+
} else {
- _vm->_scenery->_toRedrawLeft = animObj1.newLeft;
- _vm->_scenery->_toRedrawRight = animObj1.newRight;
- _vm->_scenery->_toRedrawTop = animObj1.newTop;
- _vm->_scenery->_toRedrawBottom = animObj1.newBottom;
+
+ if (animData1.isStatic != 0) {
+ _vm->_scenery->_toRedrawLeft = animObj1.newLeft;
+ _vm->_scenery->_toRedrawRight = animObj1.newRight;
+ _vm->_scenery->_toRedrawTop = animObj1.newTop;
+ _vm->_scenery->_toRedrawBottom = animObj1.newBottom;
+ } else {
+ _vm->_scenery->updateAnim(animData1.layer, animData1.frame,
+ animData1.animation, 10, *animObj1.pPosX, *animObj1.pPosY, 1);
+
+ if (_vm->_scenery->_toRedrawLeft != -12345) {
+ animObj1.lastLeft = _vm->_scenery->_toRedrawLeft;
+ animObj1.lastRight = _vm->_scenery->_toRedrawRight;
+ animObj1.lastTop = _vm->_scenery->_toRedrawTop;
+ animObj1.lastBottom = _vm->_scenery->_toRedrawBottom;
+ } else {
+ animObj1.lastLeft = -1;
+ }
+
+ }
+
+ _vm->_scenery->updateStatic(animData1.order + 1);
+
}
- _vm->_scenery->updateStatic(animData1.order + 1);
+
}
// Advance animations
diff --git a/engines/gob/parse.cpp b/engines/gob/parse.cpp
index af12626c83..ad1f53bb6f 100644
--- a/engines/gob/parse.cpp
+++ b/engines/gob/parse.cpp
@@ -23,7 +23,6 @@
*
*/
-
#include "common/endian.h"
#include "gob/gob.h"
@@ -45,7 +44,7 @@ int32 Parse::encodePtr(byte *ptr, int type) {
offset = ptr - _vm->_game->_totFileData;
break;
case kInterVar:
- offset = ptr - _vm->_global->_inter_variables;
+ offset = ptr - ((byte *) _vm->_inter->_variables->getAddressOff8(0, 0));
break;
case kResStr:
offset = ptr - ((byte *) _vm->_global->_inter_resStr);
@@ -65,7 +64,7 @@ byte *Parse::decodePtr(int32 n) {
ptr = _vm->_game->_totFileData;
break;
case kInterVar:
- ptr = _vm->_global->_inter_variables;
+ ptr = (byte *) _vm->_inter->_variables->getAddressOff8(0, 0);
break;
case kResStr:
ptr = (byte *) _vm->_global->_inter_resStr;
diff --git a/engines/gob/parse_v1.cpp b/engines/gob/parse_v1.cpp
index 2b84ac5cee..3c5f90c068 100644
--- a/engines/gob/parse_v1.cpp
+++ b/engines/gob/parse_v1.cpp
@@ -23,7 +23,6 @@
*
*/
-
#include "common/endian.h"
#include "gob/gob.h"
@@ -376,7 +375,7 @@ int16 Parse_v1::parseExpr(byte stopToken, byte *arg_2) {
case 25:
*operPtr = 22;
temp = _vm->_inter->load16() * 4;
- *valPtr = encodePtr(_vm->_global->_inter_variables + temp,
+ *valPtr = encodePtr(_vm->_inter->_variables->getAddressOff8(temp, 0),
kInterVar);
if (*_vm->_global->_inter_execPtr == 13) {
_vm->_global->_inter_execPtr++;
@@ -404,8 +403,8 @@ int16 Parse_v1::parseExpr(byte stopToken, byte *arg_2) {
*valPtr = VAR(temp + offset);
break;
}
- *valPtr = encodePtr(_vm->_global->_inter_variables +
- temp * 4 + offset * _vm->_global->_inter_animDataSize * 4,
+ *valPtr = encodePtr(_vm->_inter->_variables->getAddressOff8(
+ temp * 4 + offset * _vm->_global->_inter_animDataSize * 4, 0),
kInterVar);
if (*_vm->_global->_inter_execPtr == 13) {
_vm->_global->_inter_execPtr++;
diff --git a/engines/gob/parse_v2.cpp b/engines/gob/parse_v2.cpp
index 65315c083a..a2e6b8fb37 100644
--- a/engines/gob/parse_v2.cpp
+++ b/engines/gob/parse_v2.cpp
@@ -23,7 +23,6 @@
*
*/
-
#include "common/endian.h"
#include "gob/gob.h"
@@ -409,8 +408,8 @@ int16 Parse_v2::parseExpr(byte stopToken, byte *arg_2) {
else if (operation == 27)
*valPtr = (int16) READ_VARO_UINT16(temp * 2 + offset * 2);
else if (operation == 28) {
- *valPtr = encodePtr(_vm->_global->_inter_variables +
- temp * 4 + offset * _vm->_global->_inter_animDataSize * 4,
+ *valPtr = encodePtr(_vm->_inter->_variables->getAddressOff8(
+ temp * 4 + offset * _vm->_global->_inter_animDataSize * 4, 0),
kInterVar);
if (*_vm->_global->_inter_execPtr == 13) {
_vm->_global->_inter_execPtr++;
@@ -468,7 +467,7 @@ int16 Parse_v2::parseExpr(byte stopToken, byte *arg_2) {
case 25:
*operPtr = 22;
temp = _vm->_inter->load16() * 4;
- *valPtr = encodePtr(_vm->_global->_inter_variables + temp, kInterVar);
+ *valPtr = encodePtr(_vm->_inter->_variables->getAddressOff8(temp, 0), kInterVar);
if (*_vm->_global->_inter_execPtr == 13) {
_vm->_global->_inter_execPtr++;
temp += parseValExpr(12);
diff --git a/engines/gob/saveload.cpp b/engines/gob/saveload.cpp
index 717bc143a6..2788716858 100644
--- a/engines/gob/saveload.cpp
+++ b/engines/gob/saveload.cpp
@@ -24,456 +24,714 @@
*/
#include "common/endian.h"
-#include "common/file.h"
+#include "common/savefile.h"
#include "gob/gob.h"
#include "gob/saveload.h"
-#include "gob/global.h"
#include "gob/draw.h"
-#include "gob/video.h"
namespace Gob {
-SaveLoad::SaveLoad(GobEngine *vm, const char *targetName) : _vm(vm) {
- _curSlot = -1;
+TempSprite::TempSprite() {
+ _sprite = 0;
+ _width = _height = 0;
+ _size = -1;
+ memset(_palette, 0, 768);
+}
- _stagesCount = 0;
- _buffer = 0;
+TempSprite::~TempSprite() {
+ delete[] _sprite;
+}
- _tempSprite = 0;
- memset(_tempPal, 0, 768);
- _tempSpriteSize = -1;
+int TempSprite::getSpriteIndex(int32 size) const {
+ if (size < -1000)
+ size += 1000;
- _saveFiles = new char*[5];
+ return -size - 1;
+}
- assert(_saveFiles);
+bool TempSprite::getSpritePalette(int32 size) const {
+ return size < -1000;
+}
- _saveFiles[0] = new char[strlen(targetName) + 5];
- _saveFiles[1] = 0;
- _saveFiles[2] = new char[strlen(targetName) + 5];
- _saveFiles[3] = _saveFiles[0];
- _saveFiles[4] = 0;
+bool TempSprite::getProperties(int16 dataVar, int32 size, int32 offset,
+ int &index, bool &palette) const {
- assert(_saveFiles[0] && _saveFiles[2]);
+ if (size >= 0) {
+ warning("Invalid index (%d)", size);
+ return false;
+ }
- sprintf(_saveFiles[0], "%s.s00", targetName);
- sprintf(_saveFiles[2], "%s.blo", targetName);
-}
+ index = getSpriteIndex(size);
+ palette = getSpritePalette(size);
-SaveLoad::~SaveLoad() {
- if (_buffer) {
- for (int i = 0; i < _stagesCount; i++)
- delete[] _buffer[i];
- delete[] _buffer;
+ if ((index < 0) || (index >= SPRITES_COUNT)) {
+ warning("Index out of range (%d)", index);
+ return false;
}
- delete _tempSprite;
+ return true;
+}
- delete[] _saveFiles[0];
- delete[] _saveFiles[2];
- delete[] _saveFiles;
+int32 TempSprite::getSize() const {
+ return _size;
}
-const char *SaveLoad::setCurSlot(int slot) {
- static char *slotBase = _saveFiles[0] + strlen(_saveFiles[0]) - 2;
+bool TempSprite::saveSprite(const SurfaceDesc &surfDesc) {
+ delete[] _sprite;
+
+ _width = surfDesc.getWidth();
+ _height = surfDesc.getHeight();
+ _size = _width * _height;
+ _sprite = new byte[_size];
- if (_curSlot != slot) {
- _curSlot = slot;
+ memcpy(_sprite, surfDesc.getVidMem(), _size);
- if (_curSlot >= 0)
- snprintf(slotBase, 3, "%02d", slot);
+ return true;
+}
+
+bool TempSprite::savePalette(const Video::Color *palette) {
+ memcpy((byte *) _palette, (byte *) palette, 768);
+ return true;
+}
+
+bool TempSprite::loadSprite(SurfaceDesc &surfDesc) {
+ if (!_sprite) {
+ warning("No sprite saved");
+ return false;
+ }
+
+ if (_size != (surfDesc.getWidth() * surfDesc.getHeight())) {
+ warning("Dimensions don't match (%dx%d - %dx%d",
+ _width, _height, surfDesc.getWidth(), surfDesc.getHeight());
+ return false;
}
- return _saveFiles[0];
+ memcpy(surfDesc.getVidMem(), _sprite, _size);
+
+ return true;
}
-uint32 SaveLoad::read(Common::ReadStream &in, byte *buf,
- byte *sizes, uint32 count) {
- uint32 nRead;
+bool TempSprite::loadPalette(Video::Color *palette) {
+ memcpy((byte *) palette, (byte *) _palette, 768);
+ return true;
+}
- nRead = in.read(buf, count);
- if (nRead != count) {
- warning("Can't read data: requested %d, got %d", count, nRead);
- return 0;
+bool TempSprite::toBuffer(byte *buffer, int32 size, bool palette) const {
+
+ int32 haveSize = _size + (palette ? 768 : 0);
+ if (size != haveSize) {
+ warning("Sizes don't match (%d != %d)", size, haveSize);
+ return false;
}
- nRead = in.read(sizes, count);
- if (nRead != count) {
- warning("Can't read data sizes: requested %d, got %d", count, nRead);
- return 0;
+ if (palette) {
+ memcpy(buffer, (byte *) _palette, 768);
+ buffer += 768;
}
- return count;
+ memcpy(buffer, _sprite, _size);
+
+ return true;
}
-uint32 SaveLoad::write(Common::WriteStream &out, byte *buf,
- byte *sizes, uint32 count) {
- uint32 written;
+bool TempSprite::fromBuffer(const byte *buffer, int32 size, bool palette) {
+ if (palette) {
+ memcpy((byte *) _palette, buffer, 768);
+ buffer += 768;
+ size -= 768;
+ }
- written = out.write(buf, count);
- if (written != count) {
- warning("Can't write data: requested %d, wrote %d", count, written);
- return 0;
+ _size = size;
+
+ delete[] _sprite;
+ _sprite = new byte[_size];
+
+ memcpy(_sprite, buffer, _size);
+
+ return true;
+}
+
+
+PlainSave::PlainSave() {
+}
+
+PlainSave::~PlainSave() {
+}
+
+bool PlainSave::save(int16 dataVar, int32 size, int32 offset, const char *name,
+ const Variables *variables) {
+
+ if ((size <= 0) || (offset != 0)) {
+ warning("Invalid size (%d) or offset (%d)", size, offset);
+ return false;
}
- written = out.write(sizes, count);
- if (written != count) {
- warning("Can't write data: requested %d, wrote %d", count, written);
- return 0;
+ byte *vars = new byte[size];
+ byte *varSizes = new byte[size];
+
+ if (!variables->copyTo(dataVar, vars, varSizes, size)) {
+ delete[] vars;
+ delete[] varSizes;
+ warning("dataVar (%d) or size (%d) out of range", dataVar, size);
+ return false;
}
- return count;
+ bool result = save(0, size, offset, name, vars, varSizes);
+
+ delete[] vars;
+ delete[] varSizes;
+
+ return result;
}
-bool SaveLoad::loadDataEndian(Common::ReadStream &in,
- int16 dataVar, uint32 size) {
+bool PlainSave::load(int16 dataVar, int32 size, int32 offset, const char *name,
+ Variables *variables) {
- bool retVal = false;
+ if ((size <= 0) || (offset != 0)) {
+ warning("Invalid size (%d) or offset (%d)", size, offset);
+ return false;
+ }
- byte *varBuf = new byte[size];
- byte *sizeBuf = new byte[size];
+ byte *vars = new byte[size];
+ byte *varSizes = new byte[size];
- assert(varBuf && sizeBuf);
+ bool result = load(0, size, offset, name, vars, varSizes);
- if (read(in, varBuf, sizeBuf, size) == size) {
- if (fromEndian(varBuf, sizeBuf, size)) {
- memcpy(_vm->_global->_inter_variables + dataVar, varBuf, size);
- memcpy(_vm->_global->_inter_variablesSizes + dataVar, sizeBuf, size);
- retVal = true;
+ if (result && variables) {
+ if (!variables->copyFrom(dataVar, vars, varSizes, size)) {
+ delete[] vars;
+ delete[] varSizes;
+ warning("dataVar (%d) or size (%d) out of range", dataVar, size);
+ return false;
}
}
- delete[] varBuf;
- delete[] sizeBuf;
+ delete[] vars;
+ delete[] varSizes;
- return retVal;
+ return result;
}
-bool SaveLoad::saveDataEndian(Common::WriteStream &out,
- int16 dataVar, uint32 size) {
+bool PlainSave::save(int16 dataVar, int32 size, int32 offset, const char *name,
+ const byte *variables, const byte *variableSizes) const {
- bool retVal = false;
+ if ((size <= 0) || (offset != 0)) {
+ warning("Invalid size (%d) or offset (%d)", size, offset);
+ return false;
+ }
- byte *varBuf = new byte[size];
- byte *sizeBuf = new byte[size];
+ Common::SaveFileManager *saveMan = g_system->getSavefileManager();
+ Common::OutSaveFile *out = saveMan->openForSaving(name);
- assert(varBuf && sizeBuf);
+ if (!out) {
+ warning("Can't open file \"%s\" for writing", name);
+ return false;
+ }
- memcpy(varBuf, _vm->_global->_inter_variables + dataVar, size);
- memcpy(sizeBuf, _vm->_global->_inter_variablesSizes + dataVar, size);
+ bool retVal;
+ retVal = SaveLoad::saveDataEndian(*out, dataVar, size, variables, variableSizes);
- if (toEndian(varBuf, sizeBuf, size))
- if (write(out, varBuf, sizeBuf, size) == size)
- retVal = true;
+ out->finalize();
+ if (out->ioFailed()) {
+ warning("Can't write to file \"%s\"", name);
+ retVal = false;
+ }
- delete[] varBuf;
- delete[] sizeBuf;
+ delete out;
+ return retVal;
+}
+
+bool PlainSave::load(int16 dataVar, int32 size, int32 offset, const char *name,
+ byte *variables, byte *variableSizes) const {
+
+ if ((size <= 0) || (offset != 0)) {
+ warning("Invalid size (%d) or offset (%d)", size, offset);
+ return false;
+ }
+
+ Common::SaveFileManager *saveMan = g_system->getSavefileManager();
+ Common::InSaveFile *in = saveMan->openForLoading(name);
+
+ if (!in) {
+ warning("Can't open file \"%s\" for reading", name);
+ return false;
+ }
+ bool retVal = SaveLoad::loadDataEndian(*in, dataVar, size, variables, variableSizes);
+ delete in;
return retVal;
}
-int32 SaveLoad::getSize(SaveType type) {
- switch (type) {
- case kSaveNone:
- return -1;
- break;
- case kSaveGame:
- return getSizeGame();
- break;
+StagedSave::StagedSave() {
+ _mode = kModeNone;
+ _name = 0;
+ _loaded = false;
+}
- case kSaveTempSprite:
- return getSizeTempSprite();
- break;
+StagedSave::~StagedSave() {
+ clear();
+}
- case kSaveNotes:
- return getSizeNotes();
- break;
+void StagedSave::addStage(int32 size, bool endianed) {
+ int32 offset = 0;
- case kSaveScreenshot:
- return getSizeScreenshot();
- break;
+ if (!_stages.empty())
+ offset = _stages[_stages.size() - 1].offset +
+ _stages[_stages.size() - 1].size;
- case kSaveIgnore:
- return -1;
- break;
- }
+ Stage stage(size, offset, endianed);
+ _stages.push_back(stage);
+}
+
+int StagedSave::findStage(int16 dataVar, int32 size, int32 offset) const {
+ for (uint i = 0; i < _stages.size(); i++)
+ if ((_stages[i].size == size) &&
+ (_stages[i].offset == offset))
+ return i;
return -1;
}
-bool SaveLoad::load(SaveType type, int16 dataVar, int32 size, int32 offset) {
- switch (type) {
- case kSaveNone:
- return false;
- break;
-
- case kSaveGame:
- return loadGame(dataVar, size, offset);
- break;
+bool StagedSave::allSaved() const {
+ for (uint i = 0; i < _stages.size(); i++)
+ if (!_stages[i].bufVar)
+ return false;
- case kSaveTempSprite:
- return loadTempSprite(dataVar, size, offset);
- break;
+ return true;
+}
- case kSaveNotes:
- return loadNotes(dataVar, size, offset);
- break;
+uint32 StagedSave::getSize() const {
+ uint32 size = 0;
- case kSaveScreenshot:
- return loadScreenshot(dataVar, size, offset);
- break;
+ for (uint i = 0; i < _stages.size(); i++) {
+ if (_stages[i].endianed)
+ size += 2 * _stages[i].size;
+ else
+ size += _stages[i].size;
+ }
+
+ return size;
+}
- case kSaveIgnore:
- return true;
- break;
+void StagedSave::clear() {
+ for (uint i = 0; i < _stages.size(); i++) {
+ delete[] _stages[i].bufVar;
+ delete[] _stages[i].bufVarSizes;
+ _stages[i].bufVar = 0;
+ _stages[i].bufVarSizes = 0;
}
- return false;
+ delete[] _name;
+ _name = 0;
+
+ _mode = kModeNone;
+ _loaded = false;
}
-bool SaveLoad::save(SaveType type, int16 dataVar, int32 size, int32 offset) {
- switch (type) {
- case kSaveNone:
- return false;
- break;
+void StagedSave::assertMode(Mode mode, const char *name) {
+ if ((_mode != mode) || ((name[0] != '\0') && strcmp(_name, name))) {
+ clear();
+ _mode = mode;
+ _name = new char[strlen(name) + 1];
+ strcpy(_name, name);
+ }
+}
- case kSaveGame:
- return saveGame(dataVar, size, offset);
- break;
+bool StagedSave::save(int16 dataVar, int32 size, int32 offset, const char *name,
+ const Variables *variables) {
- case kSaveTempSprite:
- return saveTempSprite(dataVar, size, offset);
- break;
+ if ((dataVar < 0) || (size <= 0) || (offset < 0)) {
+ warning("Invalid dataVar (%d), size (%d) or offset (%d)", dataVar, size, offset);
+ return false;
+ }
- case kSaveNotes:
- return saveNotes(dataVar, size, offset);
- break;
+ byte *vars = 0, *varSizes = 0;
- case kSaveScreenshot:
- return saveScreenshot(dataVar, size, offset);
- break;
+ if (variables) {
+ vars = new byte[size];
+ varSizes = new byte[size];
- case kSaveIgnore:
- return true;
- break;
+ if (!variables->copyTo(dataVar, vars, varSizes, size)) {
+ delete[] vars;
+ delete[] varSizes;
+ warning("dataVar (%d) or size (%d) out of range", dataVar, size);
+ return false;
+ }
}
- return false;
-}
+ bool result = save(0, size, offset, name, vars, varSizes);
+
+ delete[] vars;
+ delete[] varSizes;
-int32 SaveLoad::getSizeTempSprite() {
- return _tempSpriteSize;
+ return result;
}
-bool SaveLoad::loadTempSprite(int16 dataVar, int32 size, int32 offset) {
- int index;
- bool readPal;
+bool StagedSave::load(int16 dataVar, int32 size, int32 offset, const char *name,
+ Variables *variables) {
- if (size >= 0) {
- warning("Invalid attempt at loading from the temporary sprite");
+ if ((dataVar < 0) || (size <= 0) || (offset < 0)) {
+ warning("Invalid dataVar (%d), size (%d) or offset (%d)", dataVar, size, offset);
return false;
}
- index = getSpriteIndex(size);
- readPal = getSpritePalette(size);
+ byte *vars = new byte[size];
+ byte *varSizes = new byte[size];
- if ((index < 0) || (index >= SPRITES_COUNT)) {
- warning("Index out of range while loading from the temporary "
- "sprite (%d)", index);
- return false;
+ bool result = load(0, size, offset, name, vars, varSizes);
+
+ if (result && variables) {
+ if (!variables->copyFrom(dataVar, vars, varSizes, size)) {
+ delete[] vars;
+ delete[] varSizes;
+ warning("dataVar (%d) or size (%d) out of range", dataVar, size);
+ return false;
+ }
}
- return loadTempSprite(index, readPal);
+ delete[] vars;
+ delete[] varSizes;
+
+ return result;
}
-bool SaveLoad::saveTempSprite(int16 dataVar, int32 size, int32 offset) {
- int index;
- bool readPal;
+bool StagedSave::save(int16 dataVar, int32 size, int32 offset, const char *name,
+ const byte *variables, const byte *variableSizes) {
- if (size >= 0) {
- warning("Invalid attempt at saving to the temporary sprite");
+ if ((dataVar < 0) || (size <= 0) || (offset < 0)) {
+ warning("Invalid dataVar (%d), size (%d) or offset (%d)", dataVar, size, offset);
return false;
}
- index = getSpriteIndex(size);
- readPal = getSpritePalette(size);
+ int stage = findStage(dataVar, size, offset);
+ if (stage == -1) {
+ warning("Invalid saving procedure");
+ return false;
+ }
- if ((index < 0) || (index >= SPRITES_COUNT)) {
- warning("Index out of range while saving to the temporary sprite (%d)",
- index);
+ if (!variables || (_stages[stage].endianed && !variableSizes)) {
+ warning("Missing data");
return false;
}
- return saveTempSprite(index, readPal);
-}
+ assertMode(kModeSave, name);
-bool SaveLoad::loadTempSprite(uint32 index, bool palette) {
- SurfaceDesc *sprite;
+ _stages[stage].bufVar = new byte[size];
+ memcpy(_stages[stage].bufVar, variables + dataVar, size);
- if (palette) {
- memcpy((char *) _vm->_global->_pPaletteDesc->vgaPal,
- (char *) _tempPal, 768);
- _vm->_video->setFullPalette(_vm->_global->_pPaletteDesc);
+ if (_stages[stage].endianed) {
+ _stages[stage].bufVarSizes = new byte[size];
+ memcpy(_stages[stage].bufVarSizes, variableSizes + dataVar, size);
+ }
+
+ if (allSaved()) {
+ bool result = write();
+ clear();
+ return result;
}
- sprite = _vm->_draw->_spritesArray[index];
+ return true;
+}
+
+bool StagedSave::load(int16 dataVar, int32 size, int32 offset, const char *name,
+ byte *variables, byte *variableSizes) {
- if (!sprite) {
- warning("Couldn't load from the temporary sprite: "
- "No such sprite %d", index);
+ if ((dataVar < 0) || (size <= 0) || (offset < 0)) {
+ warning("Invalid dataVar (%d), size (%d) or offset (%d)", dataVar, size, offset);
return false;
}
- if ((sprite->getWidth() != _tempSprite->getWidth()) ||
- (sprite->getHeight() != _tempSprite->getHeight())) {
- warning("Resolution doesn't match while loading from the "
- "temporary sprite (%d: %dx%d vs. %dx%d)", index,
- sprite->getWidth(), sprite->getHeight(),
- _tempSprite->getWidth(), _tempSprite->getHeight());
+ int stage = findStage(dataVar, size, offset);
+ if (stage == -1) {
+ warning("Invalid loading procedure");
return false;
}
- _vm->_video->drawSprite(_tempSprite, sprite, 0, 0,
- sprite->getWidth() - 1, sprite->getHeight() - 1, 0, 0, 0);
+ assertMode(kModeLoad, name);
- if (index == 21) {
- _vm->_draw->forceBlit();
- _vm->_video->retrace();
+ if (!_loaded) {
+ if (!read()) {
+ clear();
+ return false;
+ }
}
+ if (variables)
+ memcpy(variables + dataVar, _stages[stage].bufVar, size);
+ if (_stages[stage].endianed && variableSizes)
+ memcpy(variableSizes + dataVar, _stages[stage].bufVarSizes, size);
+
return true;
}
-bool SaveLoad::saveTempSprite(uint32 index, bool palette) {
- SurfaceDesc *sprite = _vm->_draw->_spritesArray[index];
+bool StagedSave::write() const {
+ Common::SaveFileManager *saveMan = g_system->getSavefileManager();
+ Common::OutSaveFile *out = saveMan->openForSaving(_name);
- if (!sprite) {
- warning("Couldn't save to the temporary sprite: "
- "No such sprite %d", index);
+ if (!out) {
+ warning("Can't open file \"%s\" for writing", _name);
return false;
}
- delete _tempSprite;
- _tempSprite = _vm->_video->initSurfDesc(_vm->_global->_videoMode,
- sprite->getWidth(), sprite->getHeight(), 0);
+ bool result = true;
+ for (uint i = 0; (i < _stages.size()) && result; i++) {
+ if (!_stages[i].endianed) {
- _vm->_video->drawSprite(sprite, _tempSprite, 0, 0,
- sprite->getWidth() - 1, sprite->getHeight() - 1, 0, 0, 0);
+ uint32 written = out->write(_stages[i].bufVar, _stages[i].size);
- _tempSpriteSize = _vm->_draw->getSpriteRectSize(index);
+ result = (written == ((uint32) _stages[i].size));
+ if (!result)
+ warning("Can't write data: requested %d, wrote %d", _stages[i].size, written);
- if (palette) {
- memcpy((char *) _tempPal,
- (char *) _vm->_global->_pPaletteDesc->vgaPal, 768);
- _tempSpriteSize += 768;
+ } else
+ result = SaveLoad::saveDataEndian(*out, 0, _stages[i].size,
+ _stages[i].bufVar, _stages[i].bufVarSizes);
}
- return true;
+ if (result) {
+ out->finalize();
+ if (out->ioFailed()) {
+ warning("Can't write to file \"%s\"", _name);
+ result = false;
+ }
+ }
+
+ delete out;
+ return result;
}
-bool SaveLoad::loadSprite(Common::ReadStream &in, int32 size) {
- SurfaceDesc *sprite;
- byte *buf;
- int nRead;
- int index;
- bool readPal;
+bool StagedSave::read() {
+ Common::SaveFileManager *saveMan = g_system->getSavefileManager();
+ Common::InSaveFile *in = saveMan->openForLoading(_name);
- if (size >= 0) {
- warning("Invalid attempt at loading a sprite");
+ if (!in) {
+ warning("Can't open file \"%s\" for reading", _name);
return false;
}
- index = getSpriteIndex(size);
- readPal = getSpritePalette(size);
-
- if ((index < 0) || (index >= SPRITES_COUNT)) {
- warning("Index out of range while loading a sprite (%d)",
- index);
+ uint32 saveSize = getSize();
+ if (in->size() != saveSize) {
+ warning("Wrong size (%d != %d)", in->size(), saveSize);
return false;
}
- size = _vm->_draw->getSpriteRectSize(index);
- sprite = _vm->_draw->_spritesArray[index];
+ bool result = true;
+ for (uint i = 0; ((i < _stages.size()) && result); i++) {
+ _stages[i].bufVar = new byte[_stages[i].size];
- if (!sprite) {
- warning("Couldn't load sprite: No such sprite %d", index);
- return false;
- }
+ if (!_stages[i].endianed) {
- buf = new byte[MAX<int>(768, size)];
- assert(buf);
+ uint32 nRead = in->read(_stages[i].bufVar, _stages[i].size);
- if (readPal) {
- nRead = in.read(buf, 768);
- if (nRead != 768) {
- warning("Couldn't read a palette: requested 768, got %d", nRead);
- delete[] buf;
- return false;
- }
+ result = (nRead == ((uint32) _stages[i].size));
+ if (!result)
+ warning("Can't read data: requested %d, got %d", _stages[i].size, nRead);
- memcpy((char *) _vm->_global->_pPaletteDesc->vgaPal,
- (char *) buf, 768);
- _vm->_video->setFullPalette(_vm->_global->_pPaletteDesc);
- }
+ } else {
+ _stages[i].bufVarSizes = new byte[_stages[i].size];
- nRead = in.read(buf, size);
- if (nRead != size) {
- warning("Couldn't read sprite data: requested %d, got %d", size, nRead);
- delete[] buf;
- return false;
+ result = SaveLoad::loadDataEndian(*in, 0, _stages[i].size,
+ _stages[i].bufVar, _stages[i].bufVarSizes);
+ }
}
- memcpy((char *) sprite->getVidMem(), buf, size);
+ if (result)
+ _loaded = true;
+
+ delete in;
+ return result;
+}
+
+
+PagedBuffer::PagedBuffer(uint32 pageSize) {
+
+ _size = 0;
+ _pageSize = pageSize;
+}
+
+PagedBuffer::~PagedBuffer() {
+ clear();
+}
+
+bool PagedBuffer::empty() const {
+ return _pages.empty();
+}
+
+uint32 PagedBuffer::getSize() const {
+ return _size;
+}
+
+void PagedBuffer::clear() {
+ for (uint i = 0; i < _pages.size(); i++)
+ delete[] _pages[i];
+ _pages.clear();
+ _size = 0;
+}
+
+bool PagedBuffer::write(const byte *buffer, uint32 size, uint32 offset) {
+ grow(size, offset);
+
+ uint page = offset / _pageSize;
+ while (size > 0) {
+ if (!_pages[page])
+ _pages[page] = new byte[_pageSize];
+
+ uint32 pStart = offset % _pageSize;
+ uint32 n = MIN(size, _pageSize - pStart);
+
+ memcpy(_pages[page] + pStart, buffer, n);
+
+ buffer += n;
+ offset += n;
+ size -= n;
+ page++;
+ }
- delete[] buf;
return true;
}
-bool SaveLoad::saveSprite(Common::WriteStream &out, int32 size) {
- SurfaceDesc *sprite;
- int written;
- int index;
- bool readPal;
+bool PagedBuffer::read(byte *buffer, uint32 size, uint32 offset) const {
+ uint page = offset / _pageSize;
- if (size >= 0) {
- warning("Invalid attempt at saving a sprite");
- return false;
+ while (size > 0) {
+ if (offset >= _size) {
+ memset(buffer, 0, size);
+ break;
+ }
+
+ uint32 pStart = offset % _pageSize;
+ uint32 n = MIN(MIN(size, _pageSize - pStart), _size - offset);
+
+ if (_pages[page])
+ memcpy(buffer, _pages[page] + pStart, n);
+ else
+ memset(buffer, 0, n);
+
+ buffer += n;
+ offset += n;
+ size -= n;
+ page++;
}
- index = getSpriteIndex(size);
- readPal = getSpritePalette(size);
+ return true;
+}
- if ((index < 0) || (index >= SPRITES_COUNT)) {
- warning("Index out of range while saving a sprite (%d)",
- index);
- return false;
+uint32 PagedBuffer::writeToStream(Common::WriteStream &out) const {
+ for (uint i = 0; i < _pages.size(); i++) {
+ if (!_pages[i]) {
+ for (uint32 j = 0; j < _pageSize; j++)
+ out.writeByte(0);
+ } else
+ out.write(_pages[i], _pageSize);
}
- size = _vm->_draw->getSpriteRectSize(index);
- sprite = _vm->_draw->_spritesArray[index];
+ return _size;
+}
+
+uint32 PagedBuffer::readFromStream(Common::ReadStream &in) {
+ clear();
- if (!sprite) {
- warning("Couldn't save sprite: No such sprite %d", index);
- return false;
+ while (!in.eos()) {
+ byte *buffer = new byte[_pageSize];
+
+ _size += in.read(buffer, _pageSize);
+
+ _pages.push_back(buffer);
}
- if (readPal) {
- written = out.write((char *) _vm->_global->_pPaletteDesc->vgaPal, 768);
- if (written != 768) {
- warning("Couldn't write a palette: requested 768, wrote %d", written);
- return false;
- }
+ return _size;
+}
+
+void PagedBuffer::grow(uint32 size, uint32 offset) {
+ uint32 eSize = offset + size;
+
+ while (_size < eSize) {
+ _pages.push_back(0);
+ _size += MIN(_pageSize, eSize - _size);
}
+}
+
+
+SaveLoad::SaveLoad(GobEngine *vm, const char *targetName) : _vm(vm) {
+
+ _targetName = new char[strlen(targetName) + 1];
+ strcpy(_targetName, targetName);
+}
+
+SaveLoad::~SaveLoad() {
+ delete[] _targetName;
+}
- written = out.write((char *) sprite->getVidMem(), size);
- if (written != size) {
- warning("Couldn't write a sprite: requested %d, wrote %d",
- size, written);
+int32 SaveLoad::getSize(const char *fileName) {
+ int type;
+
+ type = getSaveType(stripPath(fileName));
+ if (type == -1)
+ return -1;
+
+ debugC(3, kDebugSaveLoad, "Requested size of save file \"%s\" (type %d)",
+ fileName, type);
+
+ return getSizeVersioned(type);
+}
+
+bool SaveLoad::load(const char *fileName, int16 dataVar, int32 size, int32 offset) {
+ int type;
+
+ type = getSaveType(stripPath(fileName));
+ if (type == -1)
return false;
- }
- return true;
+ debugC(3, kDebugSaveLoad, "Requested loading of save file \"%s\" (type %d) - %d, %d, %d",
+ fileName, type, dataVar, size, offset);
+
+ return loadVersioned(type, dataVar, size, offset);
+}
+
+bool SaveLoad::save(const char *fileName, int16 dataVar, int32 size, int32 offset) {
+ int type;
+
+ type = getSaveType(stripPath(fileName));
+ if (type == -1)
+ return false;
+
+ debugC(3, kDebugSaveLoad, "Requested saving of save file \"%s\" (type %d) - %d, %d, %d",
+ fileName, type, dataVar, size, offset);
+
+ return saveVersioned(type, dataVar, size, offset);
+}
+
+const char *SaveLoad::stripPath(const char *fileName) {
+ const char *backSlash;
+ if ((backSlash = strrchr(fileName, '\\')))
+ return backSlash + 1;
+
+ return fileName;
+}
+
+char *SaveLoad::setCurrentSlot(char *destName, int slot) {
+ char *slotBase = destName + strlen(destName) - 2;
+
+ snprintf(slotBase, 3, "%02d", slot);
+
+ return destName;
+}
+
+void SaveLoad::buildIndex(byte *buffer, char *name, int n, int32 size, int32 offset) {
+ Common::SaveFileManager *saveMan = g_system->getSavefileManager();
+ Common::InSaveFile *in;
+
+ for (int i = 0; i < n; i++, buffer += size) {
+ in = saveMan->openForLoading(setCurrentSlot(name, i));
+ if (in) {
+ in->seek(offset);
+ in->read(buffer, size);
+ delete in;
+ } else
+ memset(buffer, 0, size);
+ }
}
bool SaveLoad::fromEndian(byte *buf, const byte *sizes, uint32 count) {
@@ -514,4 +772,89 @@ bool SaveLoad::toEndian(byte *buf, const byte *sizes, uint32 count) {
return true;
}
+uint32 SaveLoad::read(Common::ReadStream &in,
+ byte *buf, byte *sizes, uint32 count) {
+ uint32 nRead;
+
+ nRead = in.read(buf, count);
+ if (nRead != count) {
+ warning("Can't read data: requested %d, got %d", count, nRead);
+ return 0;
+ }
+
+ nRead = in.read(sizes, count);
+ if (nRead != count) {
+ warning("Can't read data sizes: requested %d, got %d", count, nRead);
+ return 0;
+ }
+
+ return count;
+}
+
+uint32 SaveLoad::write(Common::WriteStream &out,
+ const byte *buf, const byte *sizes, uint32 count) {
+ uint32 written;
+
+ written = out.write(buf, count);
+ if (written != count) {
+ warning("Can't write data: requested %d, wrote %d", count, written);
+ return 0;
+ }
+
+ written = out.write(sizes, count);
+ if (written != count) {
+ warning("Can't write data: requested %d, wrote %d", count, written);
+ return 0;
+ }
+
+ return count;
+}
+
+bool SaveLoad::loadDataEndian(Common::ReadStream &in,
+ int16 dataVar, uint32 size, byte *variables, byte *variableSizes) {
+
+ bool retVal = false;
+
+ byte *varBuf = new byte[size];
+ byte *sizeBuf = new byte[size];
+
+ assert(varBuf && sizeBuf);
+
+ if (read(in, varBuf, sizeBuf, size) == size) {
+ if (fromEndian(varBuf, sizeBuf, size)) {
+ memcpy(variables + dataVar, varBuf, size);
+ memcpy(variableSizes + dataVar, sizeBuf, size);
+ retVal = true;
+ }
+ }
+
+ delete[] varBuf;
+ delete[] sizeBuf;
+
+ return retVal;
+}
+
+bool SaveLoad::saveDataEndian(Common::WriteStream &out,
+ int16 dataVar, uint32 size, const byte *variables, const byte *variableSizes) {
+
+ bool retVal = false;
+
+ byte *varBuf = new byte[size];
+ byte *sizeBuf = new byte[size];
+
+ assert(varBuf && sizeBuf);
+
+ memcpy(varBuf, variables + dataVar, size);
+ memcpy(sizeBuf, variableSizes + dataVar, size);
+
+ if (toEndian(varBuf, sizeBuf, size))
+ if (write(out, varBuf, sizeBuf, size) == size)
+ retVal = true;
+
+ delete[] varBuf;
+ delete[] sizeBuf;
+
+ return retVal;
+}
+
} // End of namespace Gob
diff --git a/engines/gob/saveload.h b/engines/gob/saveload.h
index bf1e4c01a8..29f7ee2594 100644
--- a/engines/gob/saveload.h
+++ b/engines/gob/saveload.h
@@ -26,143 +26,380 @@
#ifndef GOB_SAVELOAD_H
#define GOB_SAVELOAD_H
+#include "common/array.h"
#include "common/stream.h"
#include "gob/video.h"
+#include "gob/variables.h"
namespace Gob {
-enum SaveType {
- kSaveNone = -1,
- kSaveGame,
- kSaveTempSprite,
- kSaveNotes,
- kSaveScreenshot,
- kSaveIgnore
+class TempSprite {
+public:
+ TempSprite();
+ ~TempSprite();
+
+ bool getProperties(int16 dataVar, int32 size, int32 offset,
+ int &index, bool &palette) const;
+
+ int32 getSize() const;
+
+ bool saveSprite(const SurfaceDesc &surfDesc);
+ bool savePalette(const Video::Color *palette);
+ bool loadSprite(SurfaceDesc &surfDesc);
+ bool loadPalette(Video::Color *palette);
+
+ bool toBuffer(byte *buffer, int32 size, bool palette) const;
+ bool fromBuffer(const byte *buffer, int32 size, bool palette);
+
+private:
+ byte *_sprite;
+ int16 _width;
+ int16 _height;
+ int32 _size;
+ Video::Color _palette[256];
+
+ int getSpriteIndex(int32 size) const;
+ bool getSpritePalette(int32 size) const;
};
-class SaveLoad {
+class PlainSave {
+public:
+ PlainSave();
+ ~PlainSave();
+
+ bool save(int16 dataVar, int32 size, int32 offset, const char *name,
+ const Variables *variables);
+ bool load(int16 dataVar, int32 size, int32 offset, const char *name,
+ Variables *variables);
+
+ bool save(int16 dataVar, int32 size, int32 offset, const char *name,
+ const byte *variables, const byte *variableSizes) const;
+ bool load(int16 dataVar, int32 size, int32 offset, const char *name,
+ byte *variables, byte *variableSizes) const;
+};
+
+class StagedSave {
public:
- int32 getSize(SaveType type);
- bool load(SaveType type, int16 dataVar, int32 size, int32 offset);
- bool save(SaveType type, int16 dataVar, int32 size, int32 offset);
+ StagedSave();
+ ~StagedSave();
+
+ void addStage(int32 size, bool endianed = true);
- virtual SaveType getSaveType(const char *fileName) = 0;
+ bool save(int16 dataVar, int32 size, int32 offset, const char *name,
+ const Variables *variables);
+ bool load(int16 dataVar, int32 size, int32 offset, const char *name,
+ Variables *variables);
+
+ bool save(int16 dataVar, int32 size, int32 offset, const char *name,
+ const byte *variables, const byte *variableSizes);
+ bool load(int16 dataVar, int32 size, int32 offset, const char *name,
+ byte *variables, byte *variableSizes);
+
+private:
+ struct Stage {
+ byte *bufVar;
+ byte *bufVarSizes;
+ int32 size;
+ int32 offset;
+ bool endianed;
+
+ Stage(int32 s = 0, int32 off = 0, bool end = true) :
+ bufVar(0), bufVarSizes(0), size(s), offset(off), endianed(end) {}
+ };
+
+ enum Mode {
+ kModeNone,
+ kModeSave,
+ kModeLoad
+ };
+
+ Common::Array<Stage> _stages;
+ enum Mode _mode;
+ char *_name;
+
+ bool _loaded;
+
+ int findStage(int16 dataVar, int32 size, int32 offset) const;
+ bool allSaved() const;
+
+ uint32 getSize() const;
+
+ void clear();
+ void assertMode(Mode mode, const char *name);
+
+ bool write() const;
+ bool read();
+};
+
+class PagedBuffer {
+public:
+ PagedBuffer(uint32 pageSize = 1024);
+ ~PagedBuffer();
+
+ bool empty() const;
+ uint32 getSize() const;
+
+ void clear();
+
+ bool write(const byte *buffer, uint32 size, uint32 offset);
+ bool read(byte *buffer, uint32 size, uint32 offset) const;
+
+ uint32 writeToStream(Common::WriteStream &out) const;
+ uint32 readFromStream(Common::ReadStream &in);
+
+private:
+ uint32 _size;
+ uint32 _pageSize;
+ Common::Array<byte *> _pages;
+
+ void grow(uint32 size, uint32 offset);
+};
+
+class SaveLoad {
+public:
+ enum SaveMode {
+ kSaveModeNone,
+ kSaveModeIgnore,
+ kSaveModeSave
+ };
SaveLoad(GobEngine *vm, const char *targetName);
virtual ~SaveLoad();
-protected:
- int _curSlot;
- char **_saveFiles;
+ virtual SaveMode getSaveMode(const char *fileName) = 0;
- int _stagesCount;
- byte **_buffer;
+ int32 getSize(const char *fileName);
+ bool load(const char *fileName, int16 dataVar, int32 size, int32 offset);
+ bool save(const char *fileName, int16 dataVar, int32 size, int32 offset);
- // While using the notepad or changing the font, the original executable
- // temporarily dumps Draw::_backSurface to a file. Since that's not really
- // a nice thing to do, we work around it.
- SurfaceDesc *_tempSprite;
- Video::Color _tempPal[256];
- int32 _tempSpriteSize;
+ char *setCurrentSlot(char *destName, int slot);
+ void buildIndex(byte *buffer, char *name, int n, int32 size, int32 offset = 0);
+ static const char *stripPath(const char *fileName);
+
+ static bool fromEndian(byte *buf, const byte *sizes, uint32 count);
+ static bool toEndian(byte *buf, const byte *sizes, uint32 count);
+ static uint32 read(Common::ReadStream &in,
+ byte *buf, byte *sizes, uint32 count);
+ static uint32 write(Common::WriteStream &out,
+ const byte *buf, const byte *sizes, uint32 count);
+
+ static bool loadDataEndian(Common::ReadStream &in,
+ int16 dataVar, uint32 size, byte *variables, byte *variableSizes);
+ static bool saveDataEndian(Common::WriteStream &out,
+ int16 dataVar, uint32 size, const byte *variables, const byte *variableSizes);
+
+protected:
GobEngine *_vm;
- int getSpriteIndex(int32 size) {
- if (size < -1000)
- size += 1000;
-
- return -size - 1;
- }
- bool getSpritePalette(int32 size) {
- return size < -1000;
- }
-
- const char *setCurSlot(int slot);
- bool fromEndian(byte *buf, const byte *sizes, uint32 count);
- bool toEndian(byte *buf, const byte *sizes, uint32 count);
- uint32 read(Common::ReadStream &in, byte *buf,
- byte *sizes, uint32 count);
- uint32 write(Common::WriteStream &out, byte *buf,
- byte *sizes, uint32 count);
-
- bool loadDataEndian(Common::ReadStream &in, int16 dataVar, uint32 size);
- bool saveDataEndian(Common::WriteStream &out, int16 dataVar, uint32 size);
-
- bool loadTempSprite(uint32 index, bool palette);
- bool saveTempSprite(uint32 index, bool palette);
- bool loadSprite(Common::ReadStream &in, int32 size);
- bool saveSprite(Common::WriteStream &out, int32 size);
-
- int32 getSizeTempSprite();
- bool loadTempSprite(int16 dataVar, int32 size, int32 offset);
- bool saveTempSprite(int16 dataVar, int32 size, int32 offset);
-
- virtual uint32 getSaveGameSize() = 0;
-
- virtual int32 getSizeGame() = 0;
- virtual int32 getSizeNotes() = 0;
- virtual int32 getSizeScreenshot() = 0;
- virtual bool loadGame(int16 dataVar, int32 size, int32 offset) = 0;
- virtual bool loadNotes(int16 dataVar, int32 size, int32 offset) = 0;
- virtual bool loadScreenshot(int16 dataVar, int32 size, int32 offset) = 0;
- virtual bool saveGame(int16 dataVar, int32 size, int32 offset) = 0;
- virtual bool saveNotes(int16 dataVar, int32 size, int32 offset) = 0;
- virtual bool saveScreenshot(int16 dataVar, int32 size, int32 offset) = 0;
+ char *_targetName;
+
+ virtual int getSaveType(const char *fileName) = 0;
+
+ virtual int32 getSizeVersioned(int type) = 0;
+ virtual bool loadVersioned(int type, int16 dataVar, int32 size, int32 offset) = 0;
+ virtual bool saveVersioned(int type, int16 dataVar, int32 size, int32 offset) = 0;
};
class SaveLoad_v2 : public SaveLoad {
public:
- virtual SaveType getSaveType(const char *fileName);
+ enum SaveType {
+ kSaveGame,
+ kSaveTempSprite,
+ kSaveNotes
+ };
SaveLoad_v2(GobEngine *vm, const char *targetName);
- virtual ~SaveLoad_v2() {}
+ virtual ~SaveLoad_v2();
+
+ virtual SaveMode getSaveMode(const char *fileName);
protected:
- virtual uint32 getSaveGameSize();
-
- virtual int32 getSizeGame();
- virtual int32 getSizeNotes();
- virtual int32 getSizeScreenshot();
- virtual bool loadGame(int16 dataVar, int32 size, int32 offset);
- virtual bool loadNotes(int16 dataVar, int32 size, int32 offset);
- virtual bool loadScreenshot(int16 dataVar, int32 size, int32 offset);
- virtual bool saveGame(int16 dataVar, int32 size, int32 offset);
- virtual bool saveNotes(int16 dataVar, int32 size, int32 offset);
- virtual bool saveScreenshot(int16 dataVar, int32 size, int32 offset);
-
- void initBuffer();
+ struct SaveFile {
+ const char *sourceName;
+ char *destName;
+ SaveMode mode;
+ SaveType type;
+ };
+
+ static SaveFile _saveFiles[];
+
+ int32 _varSize;
+
+ TempSprite _tmpSprite;
+ PlainSave _notes;
+ StagedSave _save;
+
+ byte _indexBuffer[600];
+ bool _hasIndex;
+
+ virtual int getSaveType(const char *fileName);
+
+ virtual int32 getSizeVersioned(int type);
+ virtual bool loadVersioned(int type, int16 dataVar, int32 size, int32 offset);
+ virtual bool saveVersioned(int type, int16 dataVar, int32 size, int32 offset);
+
+ int getSlot(int32 offset) const;
+ int getSlotRemainder(int32 offset) const;
+
+ int32 getSizeGame(SaveFile &saveFile);
+ int32 getSizeTempSprite(SaveFile &saveFile);
+ int32 getSizeNotes(SaveFile &saveFile);
+
+ bool loadGame(SaveFile &saveFile, int16 dataVar, int32 size, int32 offset);
+ bool loadTempSprite(SaveFile &saveFile, int16 dataVar, int32 size, int32 offset);
+ bool loadNotes(SaveFile &saveFile, int16 dataVar, int32 size, int32 offset);
+
+ bool saveGame(SaveFile &saveFile, int16 dataVar, int32 size, int32 offset);
+ bool saveTempSprite(SaveFile &saveFile, int16 dataVar, int32 size, int32 offset);
+ bool saveNotes(SaveFile &saveFile, int16 dataVar, int32 size, int32 offset);
+
+ void assertInited();
};
-class SaveLoad_v3 : public SaveLoad_v2 {
-public:
- virtual SaveType getSaveType(const char *fileName);
+enum SaveType {
+ kSaveNone = -1,
+ kSaveGame,
+ kSaveTempSprite,
+ kSaveNotes,
+ kSaveScreenshot,
+ kSaveIgnore
+};
- SaveLoad_v3(GobEngine *vm, const char *targetName, uint32 screenshotSize = 19968,
+class SaveLoad_v3 : public SaveLoad {
+public:
+ enum SaveType {
+ kSaveNone,
+ kSaveGame,
+ kSaveTempSprite,
+ kSaveNotes,
+ kSaveScreenshot
+ };
+
+ SaveLoad_v3(GobEngine *vm, const char *targetName,
+ uint32 screenshotSize = 19968,
int32 indexOffset = 40, int32 screenshotOffset = 80);
- virtual ~SaveLoad_v3() {}
+ virtual ~SaveLoad_v3();
+
+ virtual SaveMode getSaveMode(const char *fileName);
protected:
+ struct SaveFile {
+ const char *sourceName;
+ char *destName;
+ SaveMode mode;
+ SaveType type;
+ int slot;
+ };
+
bool _useScreenshots;
bool _firstSizeGame;
- int8 _saveSlot;
uint32 _screenshotSize;
int32 _indexOffset;
int32 _screenshotOffset;
- virtual uint32 getSaveGameSize();
+ static SaveFile _saveFiles[];
+
+ int32 _varSize;
+
+ TempSprite _screenshot;
+ TempSprite _tmpSprite;
+ PlainSave _notes;
+ StagedSave _save;
+
+ byte _propBuffer[1000];
+ byte _indexBuffer[1200];
+ bool _hasIndex;
+
+ virtual int getSaveType(const char *fileName);
+
+ virtual int32 getSizeVersioned(int type);
+ virtual bool loadVersioned(int type, int16 dataVar, int32 size, int32 offset);
+ virtual bool saveVersioned(int type, int16 dataVar, int32 size, int32 offset);
+
+ int getSlot(int32 offset) const;
+ int getSlotRemainder(int32 offset) const;
+
+ int32 getSizeGame(SaveFile &saveFile);
+ int32 getSizeTempSprite(SaveFile &saveFile);
+ int32 getSizeNotes(SaveFile &saveFile);
+ int32 getSizeScreenshot(SaveFile &saveFile);
+
+ bool loadGame(SaveFile &saveFile, int16 dataVar, int32 size, int32 offset);
+ bool loadTempSprite(SaveFile &saveFile, int16 dataVar, int32 size, int32 offset);
+ bool loadNotes(SaveFile &saveFile, int16 dataVar, int32 size, int32 offset);
+ bool loadScreenshot(SaveFile &saveFile, int16 dataVar, int32 size, int32 offset);
+
+ bool saveGame(SaveFile &saveFile, int16 dataVar, int32 size, int32 offset);
+ bool saveTempSprite(SaveFile &saveFile, int16 dataVar, int32 size, int32 offset);
+ bool saveNotes(SaveFile &saveFile, int16 dataVar, int32 size, int32 offset);
+ bool saveScreenshot(SaveFile &saveFile, int16 dataVar, int32 size, int32 offset);
+
+ void assertInited();
+
+ void buildScreenshotIndex(byte *buffer, char *name, int n);
+};
+
+class SaveLoad_v4 : public SaveLoad {
+public:
+ enum SaveType {
+ kSaveNone,
+ kSaveScreenProps,
+ kSaveGame,
+ kSaveGameScreenProps
+ };
+
+ bool _firstSizeGame;
+
+ SaveLoad_v4(GobEngine *vm, const char *targetName);
+ virtual ~SaveLoad_v4();
+
+ virtual SaveMode getSaveMode(const char *fileName);
+
+protected:
+ struct SaveFile {
+ const char *sourceName;
+ char *destName;
+ SaveMode mode;
+ SaveType type;
+ };
+
+ static SaveFile _saveFiles[];
+
+ int32 _varSize;
+
+ StagedSave _save;
+
+ byte _propBuffer[1000];
+ byte _indexBuffer[1200];
+ bool _hasIndex;
+
+ byte *_screenProps;
+
+ virtual int getSaveType(const char *fileName);
+
+ virtual int32 getSizeVersioned(int type);
+ virtual bool loadVersioned(int type, int16 dataVar, int32 size, int32 offset);
+ virtual bool saveVersioned(int type, int16 dataVar, int32 size, int32 offset);
+
+ int getSlot(int32 offset) const;
+ int getSlotRemainder(int32 offset) const;
+
+ int32 getSizeScreenProps(SaveFile &saveFile);
+ int32 getSizeGame(SaveFile &saveFile);
+ int32 getSizeGameScreenProps(SaveFile &saveFile);
+
+ bool loadScreenProps(SaveFile &saveFile, int16 dataVar, int32 size, int32 offset);
+ bool loadGame(SaveFile &saveFile, int16 dataVar, int32 size, int32 offset);
+ bool loadGameScreenProps(SaveFile &saveFile, int16 dataVar, int32 size, int32 offset);
- virtual int32 getSizeGame();
- virtual int32 getSizeScreenshot();
- virtual bool loadGame(int16 dataVar, int32 size, int32 offset);
- virtual bool loadScreenshot(int16 dataVar, int32 size, int32 offset);
- virtual bool saveGame(int16 dataVar, int32 size, int32 offset);
- virtual bool saveNotes(int16 dataVar, int32 size, int32 offset);
- virtual bool saveScreenshot(int16 dataVar, int32 size, int32 offset);
+ bool saveScreenProps(SaveFile &saveFile, int16 dataVar, int32 size, int32 offset);
+ bool saveGame(SaveFile &saveFile, int16 dataVar, int32 size, int32 offset);
+ bool saveGameScreenProps(SaveFile &saveFile, int16 dataVar, int32 size, int32 offset);
- bool saveGame(int32 screenshotSize);
- void initBuffer();
+ void assertInited();
};
} // End of namespace Gob
diff --git a/engines/gob/saveload_v2.cpp b/engines/gob/saveload_v2.cpp
index ab7211b216..a92fe8cf01 100644
--- a/engines/gob/saveload_v2.cpp
+++ b/engines/gob/saveload_v2.cpp
@@ -24,273 +24,344 @@
*/
#include "common/endian.h"
-#include "common/file.h"
+#include "common/savefile.h"
#include "gob/gob.h"
#include "gob/saveload.h"
#include "gob/global.h"
#include "gob/game.h"
+#include "gob/draw.h"
+#include "gob/inter.h"
namespace Gob {
+SaveLoad_v2::SaveFile SaveLoad_v2::_saveFiles[] = {
+ { "cat.inf", 0, kSaveModeSave, kSaveGame},
+ { "cat.cat", 0, kSaveModeSave, kSaveGame},
+ { "save.inf", 0, kSaveModeSave, kSaveTempSprite},
+ { "bloc.inf", 0, kSaveModeSave, kSaveNotes}
+};
+
SaveLoad_v2::SaveLoad_v2(GobEngine *vm, const char *targetName) :
- SaveLoad(vm, targetName) {
+ SaveLoad(vm, targetName) {
+
+ _saveFiles[0].destName = new char[strlen(targetName) + 5];
+ _saveFiles[1].destName = _saveFiles[0].destName;
+ _saveFiles[2].destName = 0;
+ _saveFiles[3].destName = new char[strlen(targetName) + 5];
- _stagesCount = 1;
+ sprintf(_saveFiles[0].destName, "%s.s00", targetName);
+ sprintf(_saveFiles[3].destName, "%s.blo", targetName);
+
+ _varSize = 0;
+ _hasIndex = false;
}
-SaveType SaveLoad_v2::getSaveType(const char *fileName) {
- const char *backSlash;
- if ((backSlash = strrchr(fileName, '\\')))
- fileName = backSlash + 1;
-
- if (!scumm_stricmp(fileName, "cat.inf"))
- return kSaveGame;
- if (!scumm_stricmp(fileName, "cat.cat"))
- return kSaveGame;
- if (!scumm_stricmp(fileName, "save.inf"))
- return kSaveTempSprite;
- if (!scumm_stricmp(fileName, "bloc.inf"))
- return kSaveNotes;
-
- return kSaveNone;
+SaveLoad_v2::~SaveLoad_v2() {
+ delete[] _saveFiles[0].destName;
+ delete[] _saveFiles[3].destName;
}
-uint32 SaveLoad_v2::getSaveGameSize() {
- return 80 + (READ_LE_UINT32(_vm->_game->_totFileData + 0x2C) * 4) * 2;
+SaveLoad::SaveMode SaveLoad_v2::getSaveMode(const char *fileName) {
+ fileName = stripPath(fileName);
+
+ for (int i = 0; i < ARRAYSIZE(_saveFiles); i++)
+ if (!scumm_stricmp(fileName, _saveFiles[i].sourceName))
+ return _saveFiles[i].mode;
+
+ return kSaveModeNone;
}
-int32 SaveLoad_v2::getSizeNotes() {
- Common::SaveFileManager *saveMan = g_system->getSavefileManager();
- Common::InSaveFile *in;
- int32 size = -1;
+int SaveLoad_v2::getSaveType(const char *fileName) {
+ for (int i = 0; i < ARRAYSIZE(_saveFiles); i++)
+ if (!scumm_stricmp(fileName, _saveFiles[i].sourceName))
+ return i;
- in = saveMan->openForLoading(_saveFiles[(int) kSaveNotes]);
- if (in) {
- size = in->size();
- delete in;
+ return -1;
+}
+
+int32 SaveLoad_v2::getSizeVersioned(int type) {
+ assertInited();
+
+ switch (_saveFiles[type].type) {
+ case kSaveGame:
+ return getSizeGame(_saveFiles[type]);
+ case kSaveTempSprite:
+ return getSizeTempSprite(_saveFiles[type]);
+ case kSaveNotes:
+ return getSizeNotes(_saveFiles[type]);
}
- return size;
+ return -1;
}
-int32 SaveLoad_v2::getSizeGame() {
+bool SaveLoad_v2::loadVersioned(int type, int16 dataVar, int32 size, int32 offset) {
+ assertInited();
+
+ switch (_saveFiles[type].type) {
+ case kSaveGame:
+ if (loadGame(_saveFiles[type], dataVar, size, offset))
+ return true;
+
+ warning("While loading from slot %d", getSlot(offset));
+ break;
+
+ case kSaveTempSprite:
+ if(loadTempSprite(_saveFiles[type], dataVar, size, offset))
+ return true;
+
+ warning("While loading the temporary sprite");
+ break;
+
+ case kSaveNotes:
+ if (loadNotes(_saveFiles[type], dataVar, size, offset))
+ return true;
+
+ warning("While loading the notes");
+ break;
+ }
+
+ return false;
+}
+
+bool SaveLoad_v2::saveVersioned(int type, int16 dataVar, int32 size, int32 offset) {
+ assertInited();
+
+ switch (_saveFiles[type].type) {
+ case kSaveGame:
+ if (saveGame(_saveFiles[type], dataVar, size, offset))
+ return true;
+
+ warning("While saving to slot %d", getSlot(offset));
+ break;
+
+ case kSaveTempSprite:
+ if(saveTempSprite(_saveFiles[type], dataVar, size, offset))
+ return true;
+
+ warning("While saving the temporary sprite");
+ break;
+
+ case kSaveNotes:
+ if (saveNotes(_saveFiles[type], dataVar, size, offset))
+ return true;
+
+ warning("While saving the notes");
+ break;
+ }
+
+ return false;
+}
+
+int SaveLoad_v2::getSlot(int32 offset) const {
+ return ((offset - 600) / _varSize);
+}
+
+int SaveLoad_v2::getSlotRemainder(int32 offset) const {
+ return ((offset - 600) % _varSize);
+}
+
+int32 SaveLoad_v2::getSizeGame(SaveFile &saveFile) {
Common::SaveFileManager *saveMan = g_system->getSavefileManager();
Common::InSaveFile *in;
for (int i = 14; i >= 0; i--) {
- in = saveMan->openForLoading(setCurSlot(i));
+ in = saveMan->openForLoading(setCurrentSlot(saveFile.destName, i));
if (in) {
delete in;
- return (i + 1) * READ_LE_UINT32(_vm->_game->_totFileData + 0x2C) *
- 4 + 600;
+ return (i + 1) * _varSize + 600;
}
}
return -1;
}
-int32 SaveLoad_v2::getSizeScreenshot() {
- return -1;
+int32 SaveLoad_v2::getSizeTempSprite(SaveFile &saveFile) {
+ return _tmpSprite.getSize();
}
-bool SaveLoad_v2::loadGame(int16 dataVar, int32 size, int32 offset) {
+int32 SaveLoad_v2::getSizeNotes(SaveFile &saveFile) {
Common::SaveFileManager *saveMan = g_system->getSavefileManager();
Common::InSaveFile *in;
- int32 varSize = READ_LE_UINT32(_vm->_game->_totFileData + 0x2C) * 4;
+ int32 size = -1;
+
+ in = saveMan->openForLoading(saveFile.destName);
+ if (in) {
+ size = in->size();
+ delete in;
+ }
+
+ return size;
+}
+
+bool SaveLoad_v2::loadGame(SaveFile &saveFile,
+ int16 dataVar, int32 size, int32 offset) {
if (size == 0) {
dataVar = 0;
- size = varSize;
+ size = _varSize;
}
- int slot = (offset - 600) / varSize;
- int slotR = (offset - 600) % varSize;
+ if (offset == 0) {
+ debugC(3, kDebugSaveLoad, "Loading save index");
- if ((offset == 0) && (size == 600)) {
-
- byte *varBuf = _vm->_global->_inter_variables + dataVar;
- for (int i = 0; i < 15; i++, varBuf += 40) {
- in = saveMan->openForLoading(setCurSlot(i));
- if (in) {
- in->read(varBuf, 40);
- delete in;
- } else
- memset(varBuf, 0, 40);
+ if (size != 600) {
+ warning("Requested index has wrong size (%d)", size);
+ return false;
}
- memset(_vm->_global->_inter_variablesSizes + dataVar, 0, 600);
- return true;
- } else if ((offset > 0) && (slot < 15) &&
- (slotR == 0) && (size == varSize)) {
+ SaveLoad::buildIndex(_vm->_inter->_variables->getAddressOff8(dataVar, 600),
+ saveFile.destName, 15, 40);
+
+ } else {
+ int slot = getSlot(offset);
+ int slotRem = getSlotRemainder(offset);
+
+ debugC(2, kDebugSaveLoad, "Loading from slot %d", slot);
- in = saveMan->openForLoading(setCurSlot(slot));
- if (!in) {
- warning("Can't open file for slot %d", slot);
+ SaveLoad::setCurrentSlot(saveFile.destName, slot);
+
+ if ((slot >= 15) || (slotRem != 0)) {
+ warning("Invalid loading procedure (%d, %d, %d, %d, %d)",
+ dataVar, size, offset, slot, slotRem);
return false;
}
- uint32 sGameSize = getSaveGameSize();
- uint32 fSize = in->size();
- if (fSize != sGameSize) {
- warning("Can't load from slot %d: Wrong size (%d, %d)", slot,
- fSize, sGameSize);
- delete in;
+ if (!_save.load(dataVar, size, 40, saveFile.destName, _vm->_inter->_variables))
return false;
- }
+ }
- in->seek(80);
- if (loadDataEndian(*in, dataVar, size)) {
- delete in;
- debugC(1, kDebugFileIO, "Loading from slot %d", slot);
- return true;
- }
- delete in;
+ return true;
+}
- } else
- warning("Invalid loading procedure (%d, %d, %d, %d)",
- offset, size, slot, slotR);
+bool SaveLoad_v2::loadTempSprite(SaveFile &saveFile,
+ int16 dataVar, int32 size, int32 offset) {
- return false;
-}
+ debugC(3, kDebugSaveLoad, "Loading from the temporary sprite");
-bool SaveLoad_v2::loadNotes(int16 dataVar, int32 size, int32 offset) {
- bool retVal;
+ int index;
+ bool palette;
- if ((size <= 0) || (offset != 0)) {
- warning("Invalid attempt at loading the notes (%d, %d)", size, offset);
+ if (!_tmpSprite.getProperties(dataVar, size, offset, index, palette))
return false;
- }
-
- Common::SaveFileManager *saveMan = g_system->getSavefileManager();
- char *sName = _saveFiles[(int) kSaveNotes];
- Common::InSaveFile *in = saveMan->openForLoading(sName);
- if (!in) {
- warning("Can't open file \"%s\" for reading", sName);
+ if (!_tmpSprite.loadSprite(*_vm->_draw->_spritesArray[index]))
return false;
+
+ if (palette) {
+ if (!_tmpSprite.loadPalette(_vm->_global->_pPaletteDesc->vgaPal))
+ return false;
+
+ _vm->_video->setFullPalette(_vm->_global->_pPaletteDesc);
}
- retVal = loadDataEndian(*in, dataVar, size);
- delete in;
- return retVal;
-}
+ if (index == 21) {
+ _vm->_draw->forceBlit();
+ _vm->_video->retrace();
+ }
-bool SaveLoad_v2::loadScreenshot(int16 dataVar, int32 size, int32 offset) {
- return false;
+ return true;
}
-bool SaveLoad_v2::saveGame(int16 dataVar, int32 size, int32 offset) {
- int32 varSize = READ_LE_UINT32(_vm->_game->_totFileData + 0x2C) * 4;
+bool SaveLoad_v2::loadNotes(SaveFile &saveFile,
+ int16 dataVar, int32 size, int32 offset) {
+
+ debugC(2, kDebugSaveLoad, "Loading the notes");
+
+ return _notes.load(dataVar, size, offset, saveFile.destName, _vm->_inter->_variables);
+}
- initBuffer();
+bool SaveLoad_v2::saveGame(SaveFile &saveFile,
+ int16 dataVar, int32 size, int32 offset) {
if (size == 0) {
dataVar = 0;
- size = varSize;
+ size = _varSize;
}
- int slot = (offset - 600) / varSize;
- int slotR = (offset - 600) % varSize;
+ if (offset == 0) {
+ debugC(3, kDebugSaveLoad, "Saving save index");
- if ((offset == 0) && (size == 600)) {
+ if (size != 600) {
+ warning("Requested index has wrong size (%d)", size);
+ return false;
+ }
- delete[] _buffer[0];
- _buffer[0] = new byte[1200];
- assert(_buffer[0]);
+ _vm->_inter->_variables->copyTo(dataVar, _indexBuffer, 0, 600);
+ _hasIndex = true;
- memcpy(_buffer[0], _vm->_global->_inter_variables + dataVar, 600);
- memset(_buffer[0] + 600, 0, 600);
+ } else {
+ int slot = getSlot(offset);
+ int slotRem = getSlotRemainder(offset);
- return true;
+ debugC(2, kDebugSaveLoad, "Saving to slot %d", slot);
- } else if ((offset > 0) && (slot < 15) &&
- (slotR == 0) && (size == varSize)) {
+ SaveLoad::setCurrentSlot(saveFile.destName, slot);
- if (!_buffer[0]) {
- warning("Tried to save without writing the index first");
+ if ((slot >= 15) || (slotRem != 0)) {
+ warning("Invalid saving procedure (%d, %d, %d, %d, %d)",
+ dataVar, size, offset, slot, slotRem);
return false;
}
- Common::SaveFileManager *saveMan = g_system->getSavefileManager();
- Common::OutSaveFile *out;
-
- out = saveMan->openForSaving(setCurSlot(slot));
- if (!out) {
- warning("Can't open file for slot %d for writing", slot);
- delete[] _buffer[0];
- _buffer[0] = 0;
+ if (!_hasIndex) {
+ warning("No index written yet");
return false;
}
- bool retVal = false;
+ _hasIndex = false;
- if (out->write(_buffer[0] + slot * 40, 40) == 40)
- if (out->write(_buffer[0] + 600 + slot * 40, 40) == 40)
- if (saveDataEndian(*out, dataVar, size)) {
- out->finalize();
- if (!out->ioFailed())
- retVal = true;
- }
-
- if (!retVal)
- warning("Can't save to slot %d", slot);
- else
- debugC(1, kDebugFileIO, "Saved to slot %d", slot);
-
- delete[] _buffer[0];
- _buffer[0] = 0;
- delete out;
+ byte sizes[40];
+ memset(sizes, 0, 40);
+ if(!_save.save(0, 40, 0, saveFile.destName, _indexBuffer + (slot * 40), sizes))
+ return false;
- return retVal;
+ if (!_save.save(dataVar, size, 40, saveFile.destName, _vm->_inter->_variables))
+ return false;
- } else
- warning("Invalid saving procedure (%d, %d, %d, %d)",
- offset, size, slot, slotR);
+ }
- return false;
+ return true;
}
-bool SaveLoad_v2::saveNotes(int16 dataVar, int32 size, int32 offset) {
- bool retVal;
+bool SaveLoad_v2::saveTempSprite(SaveFile &saveFile,
+ int16 dataVar, int32 size, int32 offset) {
- if ((size <= 0) || (offset != 0)) {
- warning("Invalid attempt at saving the notes (%d, %d)", size, offset);
- return false;
- }
+ debugC(3, kDebugSaveLoad, "Saving to the temporary sprite");
- Common::SaveFileManager *saveMan = g_system->getSavefileManager();
- char *sName = _saveFiles[(int) kSaveNotes];
+ int index;
+ bool palette;
- Common::OutSaveFile *out = saveMan->openForSaving(sName);
- if (!out) {
- warning("Can't open file \"%s\" for writing", sName);
+ if (!_tmpSprite.getProperties(dataVar, size, offset, index, palette))
return false;
- }
- retVal = saveDataEndian(*out, dataVar, size);
+ if (!_tmpSprite.saveSprite(*_vm->_draw->_spritesArray[index]))
+ return false;
- out->finalize();
- if (out->ioFailed()) {
- warning("Can't save notes");
- retVal = false;
- }
+ if (palette)
+ if (!_tmpSprite.savePalette(_vm->_global->_pPaletteDesc->vgaPal))
+ return false;
- delete out;
- return retVal;
+ return true;
}
-bool SaveLoad_v2::saveScreenshot(int16 dataVar, int32 size, int32 offset) {
+bool SaveLoad_v2::saveNotes(SaveFile &saveFile,
+ int16 dataVar, int32 size, int32 offset) {
+
+ debugC(2, kDebugSaveLoad, "Saving the notes");
+
+ return _notes.save(dataVar, size, offset, saveFile.destName, _vm->_inter->_variables);
return false;
}
-void SaveLoad_v2::initBuffer() {
- if (_buffer)
+void SaveLoad_v2::assertInited() {
+ if (_varSize > 0)
return;
- _buffer = new byte*[_stagesCount];
- assert(_buffer);
- _buffer[0] = 0;
+ _varSize = READ_LE_UINT32(_vm->_game->_totFileData + 0x2C) * 4;
+
+ _save.addStage(40);
+ _save.addStage(_varSize);
}
} // End of namespace Gob
diff --git a/engines/gob/saveload_v3.cpp b/engines/gob/saveload_v3.cpp
index 4a4036fded..67879db3d1 100644
--- a/engines/gob/saveload_v3.cpp
+++ b/engines/gob/saveload_v3.cpp
@@ -24,62 +24,181 @@
*/
#include "common/endian.h"
-#include "common/file.h"
+#include "common/savefile.h"
#include "gob/gob.h"
#include "gob/saveload.h"
#include "gob/global.h"
#include "gob/game.h"
+#include "gob/draw.h"
+#include "gob/inter.h"
namespace Gob {
+SaveLoad_v3::SaveFile SaveLoad_v3::_saveFiles[] = {
+ { "cat.inf", 0, kSaveModeSave, kSaveGame, -1},
+ { "ima.inf", 0, kSaveModeSave, kSaveScreenshot, -1},
+ { "intro.$$$", 0, kSaveModeSave, kSaveTempSprite, -1},
+ { "bloc.inf", 0, kSaveModeSave, kSaveNotes, -1},
+ { "prot", 0, kSaveModeIgnore, kSaveNone, -1},
+ { "config", 0, kSaveModeIgnore, kSaveNone, -1},
+};
+
SaveLoad_v3::SaveLoad_v3(GobEngine *vm, const char *targetName,
uint32 screenshotSize, int32 indexOffset, int32 screenshotOffset) :
- SaveLoad_v2(vm, targetName) {
+ SaveLoad(vm, targetName) {
_screenshotSize = screenshotSize;
_indexOffset = indexOffset;
_screenshotOffset = screenshotOffset;
- _saveSlot = -1;
- _stagesCount = 3;
-
_useScreenshots = false;
_firstSizeGame = true;
+
+ _saveFiles[0].destName = new char[strlen(targetName) + 5];
+ _saveFiles[1].destName = _saveFiles[0].destName;
+ _saveFiles[2].destName = 0;
+ _saveFiles[3].destName = new char[strlen(targetName) + 5];
+ _saveFiles[4].destName = 0;
+ _saveFiles[5].destName = 0;
+
+ sprintf(_saveFiles[0].destName, "%s.s00", targetName);
+ sprintf(_saveFiles[3].destName, "%s.blo", targetName);
+
+ _varSize = 0;
+ _hasIndex = false;
+ memset(_propBuffer, 0, 1000);
}
-SaveType SaveLoad_v3::getSaveType(const char *fileName) {
- const char *backSlash;
- if ((backSlash = strrchr(fileName, '\\')))
- fileName = backSlash + 1;
-
- if (!scumm_stricmp(fileName, "cat.inf"))
- return kSaveGame;
- if (!scumm_stricmp(fileName, "ima.inf"))
- return kSaveScreenshot;
- if (!scumm_stricmp(fileName, "intro.$$$"))
- return kSaveTempSprite;
- if (!scumm_stricmp(fileName, "bloc.inf"))
- return kSaveNotes;
- if (!scumm_stricmp(fileName, "prot"))
- return kSaveIgnore;
- if (!scumm_stricmp(fileName, "config"))
- return kSaveIgnore;
-
- return kSaveNone;
+SaveLoad_v3::~SaveLoad_v3() {
+ delete[] _saveFiles[0].destName;
+ delete[] _saveFiles[3].destName;
}
-uint32 SaveLoad_v3::getSaveGameSize() {
- uint32 size;
+SaveLoad::SaveMode SaveLoad_v3::getSaveMode(const char *fileName) {
+ fileName = stripPath(fileName);
- size = 1040 + (READ_LE_UINT32(_vm->_game->_totFileData + 0x2C) * 4) * 2;
- if (_useScreenshots)
- size += _screenshotSize;
+ for (int i = 0; i < ARRAYSIZE(_saveFiles); i++)
+ if (!scumm_stricmp(fileName, _saveFiles[i].sourceName))
+ return _saveFiles[i].mode;
- return size;
+ return kSaveModeNone;
+}
+
+int SaveLoad_v3::getSaveType(const char *fileName) {
+ for (int i = 0; i < ARRAYSIZE(_saveFiles); i++)
+ if (!scumm_stricmp(fileName, _saveFiles[i].sourceName))
+ return i;
+
+ return -1;
+}
+
+int32 SaveLoad_v3::getSizeVersioned(int type) {
+ assertInited();
+
+ switch (_saveFiles[type].type) {
+ case kSaveGame:
+ return getSizeGame(_saveFiles[type]);
+ case kSaveTempSprite:
+ return getSizeTempSprite(_saveFiles[type]);
+ case kSaveNotes:
+ return getSizeNotes(_saveFiles[type]);
+ case kSaveScreenshot:
+ return getSizeScreenshot(_saveFiles[type]);
+ default:
+ break;
+ }
+
+ return -1;
+}
+
+bool SaveLoad_v3::loadVersioned(int type, int16 dataVar, int32 size, int32 offset) {
+ assertInited();
+
+ switch (_saveFiles[type].type) {
+ case kSaveGame:
+ if (loadGame(_saveFiles[type], dataVar, size, offset))
+ return true;
+
+ warning("While loading from slot %d", getSlot(offset));
+ break;
+
+ case kSaveTempSprite:
+ if(loadTempSprite(_saveFiles[type], dataVar, size, offset))
+ return true;
+
+ warning("While loading the temporary sprite");
+ break;
+
+ case kSaveNotes:
+ if (loadNotes(_saveFiles[type], dataVar, size, offset))
+ return true;
+
+ warning("While loading the notes");
+ break;
+
+ case kSaveScreenshot:
+ if (loadScreenshot(_saveFiles[type], dataVar, size, offset))
+ return true;
+
+ warning("While loading a screenshot");
+ break;
+
+ default:
+ break;
+ }
+
+ return false;
}
-int32 SaveLoad_v3::getSizeGame() {
+bool SaveLoad_v3::saveVersioned(int type, int16 dataVar, int32 size, int32 offset) {
+ assertInited();
+
+ switch (_saveFiles[type].type) {
+ case kSaveGame:
+ if (saveGame(_saveFiles[type], dataVar, size, offset))
+ return true;
+
+ warning("While saving to slot %d", getSlot(offset));
+ break;
+
+ case kSaveTempSprite:
+ if(saveTempSprite(_saveFiles[type], dataVar, size, offset))
+ return true;
+
+ warning("While saving the temporary sprite");
+ break;
+
+ case kSaveNotes:
+ if (saveNotes(_saveFiles[type], dataVar, size, offset))
+ return true;
+
+ warning("While saving the notes");
+ break;
+
+ case kSaveScreenshot:
+ if (saveScreenshot(_saveFiles[type], dataVar, size, offset))
+ return true;
+
+ warning("While saving a screenshot");
+ break;
+
+ default:
+ break;
+ }
+
+ return false;
+}
+
+int SaveLoad_v3::getSlot(int32 offset) const {
+ return ((offset - 1700) / _varSize);
+}
+
+int SaveLoad_v3::getSlotRemainder(int32 offset) const {
+ return ((offset - 1700) % _varSize);
+}
+
+int32 SaveLoad_v3::getSizeGame(SaveFile &saveFile) {
if (_firstSizeGame) {
_firstSizeGame = false;
return -1;
@@ -89,358 +208,403 @@ int32 SaveLoad_v3::getSizeGame() {
Common::InSaveFile *in;
int32 size = -1;
- int slot = _curSlot;
+ int slot = saveFile.slot;
for (int i = 29; i >= 0; i--) {
- in = saveMan->openForLoading(setCurSlot(i));
+ in = saveMan->openForLoading(setCurrentSlot(saveFile.destName, i));
if (in) {
delete in;
- size = (i + 1) * READ_LE_UINT32(_vm->_game->_totFileData + 0x2C) *
- 4 + 1700;
+ size = (i + 1) * _varSize + 1700;
break;
}
}
- setCurSlot(slot);
+ setCurrentSlot(saveFile.destName, slot);
return size;
}
-int32 SaveLoad_v3::getSizeScreenshot() {
+int32 SaveLoad_v3::getSizeTempSprite(SaveFile &saveFile) {
+ return _tmpSprite.getSize();
+}
+
+int32 SaveLoad_v3::getSizeNotes(SaveFile &saveFile) {
Common::SaveFileManager *saveMan = g_system->getSavefileManager();
Common::InSaveFile *in;
int32 size = -1;
- _useScreenshots = true;
- int slot = _curSlot;
+ in = saveMan->openForLoading(saveFile.destName);
+ if (in) {
+ size = in->size();
+ delete in;
+ }
+
+ return size;
+}
+
+int32 SaveLoad_v3::getSizeScreenshot(SaveFile &saveFile) {
+ if (!_useScreenshots) {
+ _useScreenshots = true;
+ _save.addStage(_screenshotSize, false);
+ }
+
+ Common::SaveFileManager *saveMan = g_system->getSavefileManager();
+ Common::InSaveFile *in;
+ int32 size = -1;
+
+ int slot = saveFile.slot;
for (int i = 29; i >= 0; i--) {
- in = saveMan->openForLoading(setCurSlot(i));
+ in = saveMan->openForLoading(setCurrentSlot(saveFile.destName, i));
if (in) {
delete in;
size = (i + 1) * _screenshotSize + _screenshotOffset;
break;
}
}
- setCurSlot(slot);
+ setCurrentSlot(saveFile.destName, slot);
return size;
}
-bool SaveLoad_v3::loadGame(int16 dataVar, int32 size, int32 offset) {
- int32 varSize = READ_LE_UINT32(_vm->_game->_totFileData + 0x2C) * 4;
- Common::SaveFileManager *saveMan = g_system->getSavefileManager();
- Common::InSaveFile *in;
+bool SaveLoad_v3::loadGame(SaveFile &saveFile,
+ int16 dataVar, int32 size, int32 offset) {
- int slot = (offset - 1700) / varSize;
- int slotR = (offset - 1700) % varSize;
-
- initBuffer();
+ if (size == 0) {
+ dataVar = 0;
+ size = _varSize;
+ }
- if ((size > 0) && (offset < 500) && ((size + offset) <= 500)) {
+ if (offset < 500) {
+ debugC(3, kDebugSaveLoad, "Loading global properties");
- memcpy(_vm->_global->_inter_variables + dataVar,
- _buffer[0] + offset, size);
- memcpy(_vm->_global->_inter_variablesSizes + dataVar,
- _buffer[0] + offset + 500, size);
- return true;
+ if ((size + offset) > 500) {
+ warning("Wrong global properties list size (%d, %d)", size, offset);
+ return false;
+ }
- } else if ((size == 1200) && (offset == 500)) {
+ _vm->_inter->_variables->copyFrom(dataVar,
+ _propBuffer + offset, _propBuffer + offset + 500, size);
- memset(_buffer[1], 0, 1200);
+ } else if (offset == 500) {
+ debugC(3, kDebugSaveLoad, "Loading save index");
- slot = _curSlot;
- for (int i = 0; i < 30; i++) {
- in = saveMan->openForLoading(setCurSlot(i));
- if (in) {
- in->seek(1000);
- in->read(_buffer[1] + i * 40, 40);
- delete in;
- }
+ if (size != 1200) {
+ warning("Requested index has wrong size (%d)", size);
+ return false;
}
- setCurSlot(slot);
- memcpy(_vm->_global->_inter_variables + dataVar, _buffer[1], 1200);
- memset(_vm->_global->_inter_variablesSizes + dataVar, 0, 1200);
- return true;
+ int slot = saveFile.slot;
+
+ SaveLoad::buildIndex(_vm->_inter->_variables->getAddressOff8(dataVar, 1200),
+ saveFile.destName, 30, 40, 1000);
- } else if ((offset > 0) && (slot < 30) &&
- (slotR == 0) && (size == 0)) {
+ setCurrentSlot(saveFile.destName, slot);
- in = saveMan->openForLoading(setCurSlot(slot));
- if (!in) {
- warning("Can't open file for slot %d", slot);
+ } else {
+ saveFile.slot = getSlot(offset);
+ int slotRem = getSlotRemainder(offset);
+
+ debugC(2, kDebugSaveLoad, "Loading from slot %d", saveFile.slot);
+
+ SaveLoad::setCurrentSlot(saveFile.destName, saveFile.slot);
+
+ if ((saveFile.slot < 0) || (saveFile.slot >= 30) || (slotRem != 0)) {
+ warning("Invalid loading procedure (%d, %d, %d, %d, %d)",
+ dataVar, size, offset, saveFile.slot, slotRem);
return false;
}
- uint32 sGameSize = getSaveGameSize();
- uint32 fSize = in->size();
- if (fSize != sGameSize) {
- warning("Can't load from slot %d: Wrong size (%d, %d)", slot,
- fSize, sGameSize);
- delete in;
+ if (!_save.load(dataVar, size, 540, saveFile.destName, _vm->_inter->_variables))
return false;
- }
+ }
- byte varBuf[500], sizeBuf[500];
- if (read(*in, varBuf, sizeBuf, 500) == 500) {
- if (fromEndian(varBuf, sizeBuf, 500)) {
- memcpy(_buffer[0], varBuf, 500);
- memcpy(_buffer[0] + 500, sizeBuf, 500);
- in->seek(1040);
- if (loadDataEndian(*in, 0, varSize)) {
- delete in;
- debugC(1, kDebugFileIO, "Loading from slot %d", slot);
- return true;
- }
- }
- }
- delete in;
+ return true;
+}
- } else
- warning("Invalid loading procedure (%d, %d, %d, %d)",
- offset, size, slot, slotR);
+bool SaveLoad_v3::loadTempSprite(SaveFile &saveFile,
+ int16 dataVar, int32 size, int32 offset) {
- return false;
+ debugC(3, kDebugSaveLoad, "Loading from the temporary sprite");
+
+ int index;
+ bool palette;
+
+ if (!_tmpSprite.getProperties(dataVar, size, offset, index, palette))
+ return false;
+
+ if (!_tmpSprite.loadSprite(*_vm->_draw->_spritesArray[index]))
+ return false;
+
+ if (palette) {
+ if (!_tmpSprite.loadPalette(_vm->_global->_pPaletteDesc->vgaPal))
+ return false;
+
+ _vm->_video->setFullPalette(_vm->_global->_pPaletteDesc);
+ }
+
+ if (index == 21) {
+ _vm->_draw->forceBlit();
+ _vm->_video->retrace();
+ }
+
+ return true;
}
-bool SaveLoad_v3::loadScreenshot(int16 dataVar, int32 size, int32 offset) {
- Common::SaveFileManager *saveMan = g_system->getSavefileManager();
- Common::InSaveFile *in;
+bool SaveLoad_v3::loadNotes(SaveFile &saveFile,
+ int16 dataVar, int32 size, int32 offset) {
- int slot = (offset - _screenshotOffset) / _screenshotSize;
- int slotR = (offset - _screenshotOffset) % _screenshotSize;
+ debugC(2, kDebugSaveLoad, "Loading the notes");
- _useScreenshots = true;
- if ((size == 40) && (offset == _indexOffset)) {
- char buf[40];
+ return _notes.load(dataVar, size, offset, saveFile.destName, _vm->_inter->_variables);
+}
- memset(buf, 0, 40);
+bool SaveLoad_v3::loadScreenshot(SaveFile &saveFile,
+ int16 dataVar, int32 size, int32 offset) {
- slot = _curSlot;
- for (int i = 0; i < 30; i++) {
- in = saveMan->openForLoading(setCurSlot(i));
- if (in) {
- delete in;
- buf[i] = 1;
- }
+ debugC(3, kDebugSaveLoad, "Loading a screenshot");
+
+ if (!_useScreenshots) {
+ _useScreenshots = true;
+ _save.addStage(_screenshotSize, false);
+ }
+
+ if (offset == _indexOffset) {
+ if (size != 40) {
+ warning("Requested index has wrong size (%d)", size);
+ return false;
}
- setCurSlot(slot);
- memcpy(_vm->_global->_inter_variables + dataVar, buf, 40);
- memset(_vm->_global->_inter_variablesSizes + dataVar, 0, 40);
- return true;
+ byte buffer[40];
+ memset(buffer, 0, 40);
+
+ int slot = saveFile.slot;
+ buildScreenshotIndex(buffer, saveFile.destName, 30);
+ setCurrentSlot(saveFile.destName, slot);
- } else if ((offset > 0) && (slot < 30) &&
- (slotR == 0) && (size < 0)) {
+ memcpy(_vm->_inter->_variables->getAddressOff8(dataVar, 40), buffer, 40);
- int32 varSize = READ_LE_UINT32(_vm->_game->_totFileData + 0x2C) * 4;
+ } else {
+ saveFile.slot = (offset - _screenshotOffset) / _screenshotSize;
+ int slotRem = (offset - _screenshotOffset) % _screenshotSize;
- in = saveMan->openForLoading(setCurSlot(slot));
- if (!in) {
- warning("Can't open file for slot %d", slot);
+ SaveLoad::setCurrentSlot(saveFile.destName, saveFile.slot);
+
+ if ((saveFile.slot < 0) || (saveFile.slot >= 30) || (slotRem != 0)) {
+ warning("Invalid loading procedure (%d, %d, %d, %d, %d)",
+ dataVar, size, offset, saveFile.slot, slotRem);
return false;
}
- uint32 sGameSize = getSaveGameSize();
- uint32 fSize = in->size();
- if (fSize != sGameSize) {
- warning("Can't load screenshot from slot %d: Wrong size (%d, %d)",
- slot, fSize, sGameSize);
- delete in;
+ byte *buffer = new byte[_screenshotSize];
+
+ if (!_save.load(0, _screenshotSize, _varSize + 540, saveFile.destName, buffer, 0)) {
+ delete[] buffer;
return false;
}
- in->seek(1040 + varSize * 2);
+ int index;
+ bool palette;
- bool success = loadSprite(*in, size);
- delete in;
- return success;
+ if (!_screenshot.getProperties(dataVar, size, offset, index, palette)) {
+ delete[] buffer;
+ return false;
+ }
- } else
- warning("Invalid attempt at loading a screenshot (%d, %d, %d, %d)",
- offset, size, slot, slotR);
+ if (!_screenshot.fromBuffer(buffer, _screenshotSize, palette)) {
+ delete[] buffer;
+ return false;
+ }
- return false;
-}
+ if (!_screenshot.loadSprite(*_vm->_draw->_spritesArray[index])) {
+ delete[] buffer;
+ return false;
+ }
-bool SaveLoad_v3::saveGame(int16 dataVar, int32 size, int32 offset) {
- int32 varSize = READ_LE_UINT32(_vm->_game->_totFileData + 0x2C) * 4;
+ if (palette) {
+ if (!_screenshot.loadPalette(_vm->_global->_pPaletteDesc->vgaPal)) {
+ delete[] buffer;
+ return false;
+ }
+ _vm->_video->setFullPalette(_vm->_global->_pPaletteDesc);
+ }
+
+ delete[] buffer;
+ }
- int slot = (offset - 1700) / varSize;
- int slotR = (offset - 1700) % varSize;
+ return true;
+}
- initBuffer();
+bool SaveLoad_v3::saveGame(SaveFile &saveFile,
+ int16 dataVar, int32 size, int32 offset) {
- if ((size > 0) && (offset < 500) && ((size + offset) <= 500)) {
+ if (size == 0) {
+ dataVar = 0;
+ size = _varSize;
+ }
- memcpy(_buffer[0] + offset,
- _vm->_global->_inter_variables + dataVar, size);
- memcpy(_buffer[0] + offset + 500,
- _vm->_global->_inter_variablesSizes + dataVar, size);
+ if (offset < 500) {
+ debugC(3, kDebugSaveLoad, "Loading global properties");
- return true;
+ if ((size + offset) > 500) {
+ warning("Wrong global properties list size (%d, %d)", size, offset);
+ return false;
+ }
- } else if ((size > 0) && (offset >= 500) && (offset < 1700) &&
- ((size + offset) <= 1700)) {
+ _vm->_inter->_variables->copyTo(dataVar,
+ _propBuffer + offset, _propBuffer + offset + 500, size);
- memcpy(_buffer[1] + offset - 500,
- _vm->_global->_inter_variables + dataVar, size);
+ } else if (offset == 500) {
+ debugC(3, kDebugSaveLoad, "Saving save index");
- return true;
+ if (size != 1200) {
+ warning("Requested index has wrong size (%d)", size);
+ return false;
+ }
- } else if ((offset > 0) && (slot < 30) &&
- (slotR == 0) && (size == 0)) {
+ _vm->_inter->_variables->copyTo(dataVar, _indexBuffer, 0, size);
+ _hasIndex = true;
- _saveSlot = -1;
+ } else {
+ saveFile.slot = getSlot(offset);
+ int slotRem = getSlotRemainder(offset);
- delete _buffer[2];
- _buffer[2] = new byte[varSize * 2];
- assert(_buffer[2]);
+ debugC(2, kDebugSaveLoad, "Saving to slot %d", saveFile.slot);
- memcpy(_buffer[2], _vm->_global->_inter_variables, varSize);
- memcpy(_buffer[2] + varSize,
- _vm->_global->_inter_variablesSizes, varSize);
+ SaveLoad::setCurrentSlot(saveFile.destName, saveFile.slot);
- if (!toEndian(_buffer[2], _buffer[2] + varSize, varSize)) {
- delete _buffer[2];
- _buffer[2] = 0;
+ if ((saveFile.slot < 0) || (saveFile.slot >= 30) || (slotRem != 0)) {
+ warning("Invalid saving procedure (%d, %d, %d, %d, %d)",
+ dataVar, size, offset, saveFile.slot, slotRem);
return false;
}
- _saveSlot = slot;
+ if (!_hasIndex) {
+ warning("No index written yet");
+ return false;
+ }
- if (!_useScreenshots)
- return saveGame(0);
+ _hasIndex = false;
- return true;
+ if(!_save.save(0, 500, 0, saveFile.destName, _propBuffer, _propBuffer + 500))
+ return false;
- } else
- warning("Invalid saving procedure (%d, %d, %d, %d)",
- offset, size, slot, slotR);
+ if(!_save.save(0, 40, 500, saveFile.destName, _indexBuffer + (saveFile.slot * 40), 0))
+ return false;
- return false;
-}
+ if (!_save.save(dataVar, size, 540, saveFile.destName, _vm->_inter->_variables))
+ return false;
+
+ }
-bool SaveLoad_v3::saveNotes(int16 dataVar, int32 size, int32 offset) {
- return SaveLoad_v2::saveNotes(dataVar, size - 160, offset);
+ return true;
}
-bool SaveLoad_v3::saveScreenshot(int16 dataVar, int32 size, int32 offset) {
- int slot = (offset - _screenshotOffset) / _screenshotSize;
- int slotR = (offset - _screenshotOffset) % _screenshotSize;
+bool SaveLoad_v3::saveTempSprite(SaveFile &saveFile,
+ int16 dataVar, int32 size, int32 offset) {
- _useScreenshots = true;
+ debugC(3, kDebugSaveLoad, "Saving to the temporary sprite");
- if ((offset < _screenshotOffset) && (size > 0)) {
+ int index;
+ bool palette;
- return true;
+ if (!_tmpSprite.getProperties(dataVar, size, offset, index, palette))
+ return false;
- } else if ((offset > 0) && (slot < 30) &&
- (slotR == 0) && (size < 0)) {
+ if (!_tmpSprite.saveSprite(*_vm->_draw->_spritesArray[index]))
+ return false;
+
+ if (palette)
+ if (!_tmpSprite.savePalette(_vm->_global->_pPaletteDesc->vgaPal))
+ return false;
+
+ return true;
+}
- return saveGame(size);
+bool SaveLoad_v3::saveNotes(SaveFile &saveFile,
+ int16 dataVar, int32 size, int32 offset) {
- } else
- warning("Invalid attempt at saving a screenshot (%d, %d, %d, %d)",
- offset, size, slot, slotR);
+ debugC(2, kDebugSaveLoad, "Saving the notes");
+ return _notes.save(dataVar, size - 160, offset, saveFile.destName, _vm->_inter->_variables);
return false;
}
-bool SaveLoad_v3::saveGame(int32 screenshotSize) {
- int8 slot = _saveSlot;
-
- _saveSlot = -1;
+bool SaveLoad_v3::saveScreenshot(SaveFile &saveFile,
+ int16 dataVar, int32 size, int32 offset) {
- initBuffer();
+ debugC(3, kDebugSaveLoad, "Saving a screenshot");
- if ((slot < 0) || (slot > 29)) {
- warning("Can't save to slot %d: Out of range", slot);
- delete[] _buffer[2];
- _buffer[2] = 0;
- return false;
+ if (!_useScreenshots) {
+ _useScreenshots = true;
+ _save.addStage(_screenshotSize, false);
}
- if (!_buffer[2]) {
- warning("Can't save to slot %d: No data", slot);
- return false;
- }
+ if (offset >= _screenshotOffset) {
- Common::SaveFileManager *saveMan = g_system->getSavefileManager();
- Common::OutSaveFile *out;
+ saveFile.slot = (offset - _screenshotOffset) / _screenshotSize;
+ int slotRem = (offset - _screenshotOffset) % _screenshotSize;
- out = saveMan->openForSaving(setCurSlot(slot));
- if (!out) {
- warning("Can't open file for slot %d for writing", slot);
- delete[] _buffer[2];
- _buffer[2] = 0;
- return false;
- }
+ setCurrentSlot(saveFile.destName, saveFile.slot);
+
+ if ((saveFile.slot < 0) || (saveFile.slot >= 30) || (slotRem != 0)) {
+ warning("Invalid saving procedure (%d, %d, %d, %d, %d)",
+ dataVar, size, offset, saveFile.slot, slotRem);
+ return false;
+ }
- int32 varSize = READ_LE_UINT32(_vm->_game->_totFileData + 0x2C) * 4;
- byte varBuf[500], sizeBuf[500];
+ int index;
+ bool palette;
- memcpy(varBuf, _buffer[0], 500);
- memcpy(sizeBuf, _buffer[0] + 500, 500);
+ if (!_screenshot.getProperties(dataVar, size, offset, index, palette))
+ return false;
- bool retVal = false;
- if (toEndian(varBuf, sizeBuf, 500))
- if (write(*out, varBuf, sizeBuf, 500) == 500)
- if (out->write(_buffer[1] + slot * 40, 40) == 40)
- if (out->write(_buffer[2], varSize * 2) == ((uint32) (varSize * 2))) {
- out->flush();
- if (!out->ioFailed())
- retVal = true;
- }
+ if (!_screenshot.saveSprite(*_vm->_draw->_spritesArray[index]))
+ return false;
- delete[] _buffer[2];
- _buffer[2] = 0;
+ if (palette)
+ if (!_screenshot.savePalette(_vm->_global->_pPaletteDesc->vgaPal))
+ return false;
- if (!retVal) {
- warning("Can't save to slot %d", slot);
- delete out;
- return false;
- }
+
+ byte *buffer = new byte[_screenshotSize];
- if (_useScreenshots) {
- if (screenshotSize >= 0) {
- warning("Can't save to slot %d: Screenshot expected", slot);
- delete out;
+ if (!_screenshot.toBuffer(buffer, _screenshotSize, palette)) {
+ delete[] buffer;
return false;
}
- if (!saveSprite(*out, screenshotSize)) {
- delete out;
+ if (!_save.save(0, _screenshotSize, _varSize + 540, saveFile.destName, buffer, 0)) {
+ delete[] buffer;
return false;
}
- }
- out->finalize();
- if (out->ioFailed()) {
- warning("Can't save to slot %d", slot);
- delete out;
- return false;
+ delete[] buffer;
}
- debugC(1, kDebugFileIO, "Saved to slot %d", slot);
- delete out;
return true;
}
-void SaveLoad_v3::initBuffer() {
- if (_buffer)
+void SaveLoad_v3::assertInited() {
+ if (_varSize > 0)
return;
- _buffer = new byte*[_stagesCount];
-
- assert(_buffer);
+ _varSize = READ_LE_UINT32(_vm->_game->_totFileData + 0x2C) * 4;
- _buffer[0] = new byte[1000];
- _buffer[1] = new byte[1200];
- _buffer[2] = 0;
+ _save.addStage(500);
+ _save.addStage(40, false);
+ _save.addStage(_varSize);
+}
- assert(_buffer[0] && _buffer[1]);
+void SaveLoad_v3::buildScreenshotIndex(byte *buffer, char *name, int n) {
+ Common::SaveFileManager *saveMan = g_system->getSavefileManager();
+ Common::InSaveFile *in;
- memset(_buffer[0], 0, 1000);
- memset(_buffer[1], 0, 1200);
+ memset(buffer, 0, n);
+ for (int i = 0; i < n; i++) {
+ in = saveMan->openForLoading(setCurrentSlot(name, i));
+ if (in) {
+ delete in;
+ buffer[i] = 1;
+ }
+ }
}
} // End of namespace Gob
diff --git a/engines/gob/saveload_v4.cpp b/engines/gob/saveload_v4.cpp
new file mode 100644
index 0000000000..a6548dd82d
--- /dev/null
+++ b/engines/gob/saveload_v4.cpp
@@ -0,0 +1,439 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/endian.h"
+
+#include "gob/gob.h"
+#include "gob/saveload.h"
+#include "gob/game.h"
+#include "gob/inter.h"
+
+namespace Gob {
+
+SaveLoad_v4::SaveFile SaveLoad_v4::_saveFiles[] = {
+ { "save.tmp", 0, kSaveModeSave, kSaveScreenProps },
+ { "cat.inf", 0, kSaveModeSave, kSaveGame },
+ { "save0.tmp", 0, kSaveModeSave, kSaveGameScreenProps },
+ { "save1.tmp", 0, kSaveModeSave, kSaveGameScreenProps },
+ { "save2.tmp", 0, kSaveModeSave, kSaveGameScreenProps },
+ { "save3.tmp", 0, kSaveModeSave, kSaveGameScreenProps },
+ { "save4.tmp", 0, kSaveModeSave, kSaveGameScreenProps },
+ { "save5.tmp", 0, kSaveModeSave, kSaveGameScreenProps },
+ { "save6.tmp", 0, kSaveModeSave, kSaveGameScreenProps },
+ { "save7.tmp", 0, kSaveModeSave, kSaveGameScreenProps },
+ { "save8.tmp", 0, kSaveModeSave, kSaveGameScreenProps },
+ { "save9.tmp", 0, kSaveModeSave, kSaveGameScreenProps }
+};
+
+SaveLoad_v4::SaveLoad_v4(GobEngine *vm, const char *targetName) :
+ SaveLoad(vm, targetName) {
+
+ _firstSizeGame = true;
+
+ _saveFiles[0].destName = 0;
+ _saveFiles[1].destName = new char[strlen(targetName) + 5];
+ _saveFiles[2].destName = _saveFiles[1].destName;
+ _saveFiles[3].destName = _saveFiles[1].destName;
+ _saveFiles[4].destName = _saveFiles[1].destName;
+ _saveFiles[5].destName = _saveFiles[1].destName;
+ _saveFiles[6].destName = _saveFiles[1].destName;
+ _saveFiles[7].destName = _saveFiles[1].destName;
+ _saveFiles[8].destName = _saveFiles[1].destName;
+ _saveFiles[9].destName = _saveFiles[1].destName;
+ _saveFiles[10].destName = _saveFiles[1].destName;
+ _saveFiles[11].destName = _saveFiles[1].destName;
+
+ sprintf(_saveFiles[1].destName, "%s.s00", targetName);
+
+ _varSize = 0;
+ _hasIndex = false;
+ memset(_propBuffer, 0, 1000);
+
+ _screenProps = new byte[512000];
+ memset(_screenProps, 0, 512000);
+}
+
+SaveLoad_v4::~SaveLoad_v4() {
+ delete[] _screenProps;
+ delete[] _saveFiles[1].destName;
+}
+
+SaveLoad::SaveMode SaveLoad_v4::getSaveMode(const char *fileName) {
+ fileName = stripPath(fileName);
+
+ for (int i = 0; i < ARRAYSIZE(_saveFiles); i++)
+ if (!scumm_stricmp(fileName, _saveFiles[i].sourceName))
+ return _saveFiles[i].mode;
+
+ return kSaveModeNone;
+}
+
+int SaveLoad_v4::getSaveType(const char *fileName) {
+ for (int i = 0; i < ARRAYSIZE(_saveFiles); i++)
+ if (!scumm_stricmp(fileName, _saveFiles[i].sourceName))
+ return i;
+
+ return -1;
+}
+
+int32 SaveLoad_v4::getSizeVersioned(int type) {
+ assertInited();
+
+ switch (_saveFiles[type].type) {
+ case kSaveScreenProps:
+ return getSizeScreenProps(_saveFiles[type]);
+ case kSaveGame:
+ return getSizeGame(_saveFiles[type]);
+ case kSaveGameScreenProps:
+ return getSizeGameScreenProps(_saveFiles[type]);
+ default:
+ break;
+ }
+
+ return -1;
+}
+
+bool SaveLoad_v4::loadVersioned(int type, int16 dataVar, int32 size, int32 offset) {
+ assertInited();
+
+ switch (_saveFiles[type].type) {
+ case kSaveScreenProps:
+ if (loadScreenProps(_saveFiles[type], dataVar, size, offset))
+ return true;
+
+ warning("While loading screen properties");
+ break;
+
+ case kSaveGame:
+ if (loadGame(_saveFiles[type], dataVar, size, offset))
+ return true;
+
+ warning("While loading from slot %d", getSlot(offset));
+ break;
+
+ case kSaveGameScreenProps:
+ if (loadGameScreenProps(_saveFiles[type], dataVar, size, offset))
+ return true;
+
+ warning("While loading screen properties from slot %d", getSlot(offset));
+ break;
+
+ default:
+ break;
+ }
+
+ return false;
+}
+
+bool SaveLoad_v4::saveVersioned(int type, int16 dataVar, int32 size, int32 offset) {
+ assertInited();
+
+ switch (_saveFiles[type].type) {
+ case kSaveScreenProps:
+ if (saveScreenProps(_saveFiles[type], dataVar, size, offset))
+ return true;
+
+ warning("While saving screen properties");
+ break;
+
+ case kSaveGame:
+ if (saveGame(_saveFiles[type], dataVar, size, offset))
+ return true;
+
+ warning("While saving to slot %d", getSlot(offset));
+ break;
+
+ case kSaveGameScreenProps:
+ if (saveGameScreenProps(_saveFiles[type], dataVar, size, offset))
+ return true;
+
+ warning("While saving screen properties to slot %d", getSlot(offset));
+ break;
+
+ default:
+ break;
+ }
+
+ return false;
+}
+
+int SaveLoad_v4::getSlot(int32 offset) const {
+ return ((offset - 1700) / _varSize);
+}
+
+int SaveLoad_v4::getSlotRemainder(int32 offset) const {
+ return ((offset - 1700) % _varSize);
+}
+
+int32 SaveLoad_v4::getSizeScreenProps(SaveFile &saveFile) {
+ return 256000;
+}
+
+int32 SaveLoad_v4::getSizeGame(SaveFile &saveFile) {
+ if (_firstSizeGame) {
+ _firstSizeGame = false;
+ return -1;
+ }
+
+ Common::SaveFileManager *saveMan = g_system->getSavefileManager();
+ Common::InSaveFile *in;
+ int32 size = -1;
+
+ for (int i = 29; i >= 0; i--) {
+ in = saveMan->openForLoading(setCurrentSlot(saveFile.destName, i));
+ if (in) {
+ delete in;
+ size = (i + 1) * _varSize + 1700;
+ break;
+ }
+ }
+
+ return size;
+}
+
+int32 SaveLoad_v4::getSizeGameScreenProps(SaveFile &saveFile) {
+ return -1;
+
+ Common::SaveFileManager *saveMan = g_system->getSavefileManager();
+ Common::InSaveFile *in;
+
+ setCurrentSlot(saveFile.destName, saveFile.sourceName[4] - '0');
+ in = saveMan->openForLoading(saveFile.destName);
+
+ if (!in)
+ return -1;
+
+ int32 size = in->size();
+
+ delete in;
+
+ return size;
+}
+
+bool SaveLoad_v4::loadScreenProps(SaveFile &saveFile,
+ int16 dataVar, int32 size, int32 offset) {
+
+ // Using a sprite as a buffer
+ if (size <= 0)
+ return true;
+
+ if ((offset < 0) || (size + offset) > 256000) {
+ warning("Invalid size (%d) or offset (%d)", size, offset);
+ return false;
+ }
+
+ debugC(3, kDebugSaveLoad, "Loading screen properties (%d, %d, %d)",
+ dataVar, size, offset);
+
+ _vm->_inter->_variables->copyFrom(dataVar,
+ _screenProps + offset, _screenProps + 256000 + offset, size);
+
+ return true;
+}
+
+bool SaveLoad_v4::loadGame(SaveFile &saveFile,
+ int16 dataVar, int32 size, int32 offset) {
+
+ if (size == 0) {
+ dataVar = 0;
+ size = _varSize;
+ }
+
+ if (offset < 500) {
+ debugC(3, kDebugSaveLoad, "Loading global properties");
+
+ if ((size + offset) > 500) {
+ warning("Wrong global properties list size (%d, %d)", size, offset);
+ return false;
+ }
+
+ _vm->_inter->_variables->copyFrom(dataVar,
+ _propBuffer + offset, _propBuffer + offset + 500, size);
+
+ } else if (offset == 500) {
+ debugC(3, kDebugSaveLoad, "Loading save index");
+
+ if (size != 1200) {
+ warning("Requested index has wrong size (%d)", size);
+ return false;
+ }
+
+ SaveLoad::buildIndex(_vm->_inter->_variables->getAddressOff8(dataVar, 1200),
+ saveFile.destName, 30, 40, 1000);
+
+ } else {
+ int slot = getSlot(offset);
+ int slotRem = getSlotRemainder(offset);
+
+ debugC(2, kDebugSaveLoad, "Loading from slot %d", slot);
+
+ SaveLoad::setCurrentSlot(saveFile.destName, slot);
+
+ if ((slot < 0) || (slot >= 30) || (slotRem != 0)) {
+ warning("Invalid loading procedure (%d, %d, %d, %d, %d)",
+ dataVar, size, offset, slot, slotRem);
+ return false;
+ }
+
+ if (!_save.load(dataVar, size, 540, saveFile.destName, _vm->_inter->_variables))
+ return false;
+ }
+
+ return true;
+}
+
+bool SaveLoad_v4::loadGameScreenProps(SaveFile &saveFile,
+ int16 dataVar, int32 size, int32 offset) {
+
+ if (size != -5) {
+ warning("Invalid loading procedure (%d, %d, %d)", dataVar, size, offset);
+ return false;
+ }
+
+ setCurrentSlot(saveFile.destName, saveFile.sourceName[4] - '0');
+
+ if (!_save.load(0, 256000, _varSize + 540, saveFile.destName,
+ _screenProps, _screenProps + 256000))
+ return false;
+
+ return true;
+}
+
+bool SaveLoad_v4::saveScreenProps(SaveFile &saveFile,
+ int16 dataVar, int32 size, int32 offset) {
+
+ // Using a sprite as a buffer
+ if (size <= 0)
+ return true;
+
+ if ((offset < 0) || (size + offset) > 256000) {
+ warning("Invalid size (%d) or offset (%d)", size, offset);
+ return false;
+ }
+
+ debugC(3, kDebugSaveLoad, "Saving screen properties (%d, %d, %d)",
+ dataVar, size, offset);
+
+ _vm->_inter->_variables->copyTo(dataVar,
+ _screenProps + offset, _screenProps + 256000 + offset, size);
+
+ return true;
+}
+
+bool SaveLoad_v4::saveGame(SaveFile &saveFile,
+ int16 dataVar, int32 size, int32 offset) {
+
+ if (size == 0) {
+ dataVar = 0;
+ size = _varSize;
+ }
+
+ if (offset < 500) {
+ debugC(3, kDebugSaveLoad, "Loading global properties");
+
+ if ((size + offset) > 500) {
+ warning("Wrong global properties list size (%d, %d)", size, offset);
+ return false;
+ }
+
+ _vm->_inter->_variables->copyTo(dataVar,
+ _propBuffer + offset, _propBuffer + offset + 500, size);
+
+ } else if (offset == 500) {
+ debugC(3, kDebugSaveLoad, "Saving save index");
+
+ if (size != 1200) {
+ warning("Requested index has wrong size (%d)", size);
+ return false;
+ }
+
+ _vm->_inter->_variables->copyTo(dataVar, _indexBuffer, 0, size);
+ _hasIndex = true;
+
+ } else {
+ int slot = getSlot(offset);
+ int slotRem = getSlotRemainder(offset);
+
+ debugC(2, kDebugSaveLoad, "Saving to slot %d", slot);
+
+ SaveLoad::setCurrentSlot(saveFile.destName, slot);
+
+ if ((slot < 0) || (slot >= 30) || (slotRem != 0)) {
+ warning("Invalid saving procedure (%d, %d, %d, %d, %d)",
+ dataVar, size, offset, slot, slotRem);
+ return false;
+ }
+
+ if (!_hasIndex) {
+ warning("No index written yet");
+ return false;
+ }
+
+ _hasIndex = false;
+
+ if(!_save.save(0, 500, 0, saveFile.destName, _propBuffer, _propBuffer + 500))
+ return false;
+
+ if(!_save.save(0, 40, 500, saveFile.destName, _indexBuffer + (slot * 40), 0))
+ return false;
+
+ if (!_save.save(dataVar, size, 540, saveFile.destName, _vm->_inter->_variables))
+ return false;
+
+ }
+
+ return true;
+}
+
+bool SaveLoad_v4::saveGameScreenProps(SaveFile &saveFile,
+ int16 dataVar, int32 size, int32 offset) {
+
+ if (size != -5) {
+ warning("Invalid saving procedure (%d, %d, %d)", dataVar, size, offset);
+ return false;
+ }
+
+ setCurrentSlot(saveFile.destName, saveFile.sourceName[4] - '0');
+
+ if (!_save.save(0, 256000, _varSize + 540, saveFile.destName,
+ _screenProps, _screenProps + 256000))
+ return false;
+
+ return true;
+}
+
+void SaveLoad_v4::assertInited() {
+ if (_varSize > 0)
+ return;
+
+ _varSize = READ_LE_UINT32(_vm->_game->_totFileData + 0x2C) * 4;
+
+ _save.addStage(500);
+ _save.addStage(40, false);
+ _save.addStage(_varSize);
+ _save.addStage(256000);
+}
+
+} // End of namespace Gob
diff --git a/engines/gob/scenery.cpp b/engines/gob/scenery.cpp
index 3f9ec9e6f2..6b52cdbbd6 100644
--- a/engines/gob/scenery.cpp
+++ b/engines/gob/scenery.cpp
@@ -23,7 +23,6 @@
*
*/
-
#include "common/endian.h"
#include "common/stream.h"
@@ -101,7 +100,6 @@ int16 Scenery::loadStatic(char search) {
byte *extData = 0;
byte *dataPtr;
Static *ptr;
- int16 pictDescId;
int16 width;
int16 height;
int16 sprResId;
@@ -144,8 +142,6 @@ int16 Scenery::loadStatic(char search) {
dataPtr += 2;
ptr->layers = new StaticLayer[ptr->layersCount];
- ptr->pieces = new PieceDesc*[picsCount];
- ptr->piecesFromExt = new bool[picsCount];
for (int i = 0; i < ptr->layersCount; i++) {
int16 offset = READ_LE_UINT16(dataPtr + i * 2);
@@ -155,9 +151,9 @@ int16 Scenery::loadStatic(char search) {
ptr->layers[i].planes = new StaticPlane[ptr->layers[i].planeCount];
for (int j = 0; j < ptr->layers[i].planeCount; ++j) {
- ptr->layers[i].planes[j].pictIndex = layerData.readSByte();
- ptr->layers[i].planes[j].pieceIndex = layerData.readSByte();
- ptr->layers[i].planes[j].drawOrder = layerData.readSByte();
+ ptr->layers[i].planes[j].pictIndex = layerData.readByte();
+ ptr->layers[i].planes[j].pieceIndex = layerData.readByte();
+ ptr->layers[i].planes[j].drawOrder = layerData.readByte();
ptr->layers[i].planes[j].destX = layerData.readSint16LE();
ptr->layers[i].planes[j].destY = layerData.readSint16LE();
ptr->layers[i].planes[j].transp = layerData.readSByte();
@@ -167,18 +163,13 @@ int16 Scenery::loadStatic(char search) {
backsPtr++;
}
+ ptr->pieces = new PieceDesc*[picsCount];
+ ptr->piecesCount = new uint32[picsCount];
+
for (int i = 0; i < picsCount; i++) {
- pictDescId = _vm->_inter->load16();
+ int16 pictDescId = _vm->_inter->load16();
- if (pictDescId >= 30000) {
- ptr->pieces[i] =
- (PieceDesc *) _vm->_game->loadExtData(pictDescId, 0, 0);
- ptr->piecesFromExt[i] = true;
- } else {
- ptr->pieces[i] =
- (PieceDesc *) _vm->_game->loadTotResource(pictDescId);
- ptr->piecesFromExt[i] = false;
- }
+ loadPieces(pictDescId, ptr->pieces[i], ptr->piecesCount[i]);
width = _vm->_inter->load16();
height = _vm->_inter->load16();
@@ -225,8 +216,7 @@ void Scenery::freeStatic(int16 index) {
return;
for (int i = 0; i < _staticPictCount[index]; i++) {
- if (_statics[index].piecesFromExt[i])
- delete[] _statics[index].pieces[i];
+ delete[] _statics[index].pieces[i];
spr = _staticPictToSprite[index * 7 + i];
_spriteRefs[spr]--;
@@ -240,7 +230,7 @@ void Scenery::freeStatic(int16 index) {
delete[] _statics[index].layers[i].planes;
delete[] _statics[index].layers;
delete[] _statics[index].pieces;
- delete[] _statics[index].piecesFromExt;
+ delete[] _statics[index].piecesCount;
_statics[index].layersCount = 0;
_staticPictCount[index] = -1;
@@ -254,8 +244,8 @@ void Scenery::renderStatic(int16 scenery, int16 layer) {
int16 order;
int16 plane;
- int16 pieceIndex;
- int16 pictIndex;
+ uint16 pieceIndex;
+ uint16 pictIndex;
int16 left;
int16 right;
@@ -278,7 +268,7 @@ void Scenery::renderStatic(int16 scenery, int16 layer) {
}
planeCount = layerPtr->planeCount;
- for (order = 0; order < 40; order++) {
+ for (order = 0; order < 100; order++) {
for (plane = 0, planePtr = layerPtr->planes;
plane < planeCount; plane++, planePtr++) {
if (planePtr->drawOrder != order)
@@ -287,12 +277,21 @@ void Scenery::renderStatic(int16 scenery, int16 layer) {
pieceIndex = planePtr->pieceIndex;
pictIndex = planePtr->pictIndex - 1;
+ if (pictIndex >= _staticPictCount[scenery])
+ continue;
+
+ if (!ptr->pieces || !ptr->pieces[pictIndex])
+ continue;
+
+ if (pieceIndex >= ptr->piecesCount[pictIndex])
+ continue;
+
_vm->_draw->_destSpriteX = planePtr->destX;
_vm->_draw->_destSpriteY = planePtr->destY;
- left = FROM_LE_16(ptr->pieces[pictIndex][pieceIndex].left);
- right = FROM_LE_16(ptr->pieces[pictIndex][pieceIndex].right);
- top = FROM_LE_16(ptr->pieces[pictIndex][pieceIndex].top);
- bottom = FROM_LE_16(ptr->pieces[pictIndex][pieceIndex].bottom);
+ left = ptr->pieces[pictIndex][pieceIndex].left;
+ right = ptr->pieces[pictIndex][pieceIndex].right;
+ top = ptr->pieces[pictIndex][pieceIndex].top;
+ bottom = ptr->pieces[pictIndex][pieceIndex].bottom;
_vm->_draw->_sourceSurface =
_staticPictToSprite[scenery * 7 + pictIndex];
@@ -314,8 +313,8 @@ void Scenery::updateStatic(int16 orderFrom, byte index, byte layer) {
int16 planeCount;
int16 order;
int16 plane;
- int16 pieceIndex;
- int16 pictIndex;
+ uint16 pieceIndex;
+ uint16 pictIndex;
int16 left;
int16 right;
@@ -330,7 +329,7 @@ void Scenery::updateStatic(int16 orderFrom, byte index, byte layer) {
planeCount = layerPtr->planeCount;
- for (order = orderFrom; order < 40; order++) {
+ for (order = orderFrom; order < 100; order++) {
for (planePtr = layerPtr->planes, plane = 0;
plane < planeCount; plane++, planePtr++) {
if (planePtr->drawOrder != order)
@@ -338,13 +337,23 @@ void Scenery::updateStatic(int16 orderFrom, byte index, byte layer) {
pieceIndex = planePtr->pieceIndex;
pictIndex = planePtr->pictIndex - 1;
+
+ if (pictIndex >= _staticPictCount[index])
+ continue;
+
+ if (!pictPtr || !pictPtr[pictIndex])
+ continue;
+
+ if (pieceIndex >= _statics[index].piecesCount[pictIndex])
+ continue;
+
_vm->_draw->_destSpriteX = planePtr->destX;
_vm->_draw->_destSpriteY = planePtr->destY;
- left = FROM_LE_16(pictPtr[pictIndex][pieceIndex].left);
- right = FROM_LE_16(pictPtr[pictIndex][pieceIndex].right);
- top = FROM_LE_16(pictPtr[pictIndex][pieceIndex].top);
- bottom = FROM_LE_16(pictPtr[pictIndex][pieceIndex].bottom);
+ left = pictPtr[pictIndex][pieceIndex].left;
+ right = pictPtr[pictIndex][pieceIndex].right;
+ top = pictPtr[pictIndex][pieceIndex].top;
+ bottom = pictPtr[pictIndex][pieceIndex].bottom;
if (_vm->_draw->_destSpriteX > _toRedrawRight)
continue;
@@ -415,7 +424,6 @@ int16 Scenery::loadAnim(char search) {
byte *extData;
byte *dataPtr;
Animation *ptr;
- int16 pictDescId;
int16 width;
int16 height;
int16 sprResId;
@@ -454,9 +462,6 @@ int16 Scenery::loadAnim(char search) {
dataPtr += 2;
ptr->layers = new AnimLayer[ptr->layersCount];
- ptr->pieces = new PieceDesc*[picsCount];
- ptr->piecesFromExt = new bool[picsCount];
- ptr->sizes = new uint16[picsCount];
for (i = 0; i < ptr->layersCount; i++) {
int16 offset = READ_LE_UINT16(dataPtr + i * 2);
@@ -492,23 +497,13 @@ int16 Scenery::loadAnim(char search) {
}
}
+ ptr->pieces = new PieceDesc*[picsCount];
+ ptr->piecesCount = new uint32[picsCount];
+
for (i = 0; i < picsCount; i++) {
- pictDescId = _vm->_inter->load16();
- if (pictDescId >= 30000) {
- uint32 size;
-
- ptr->pieces[i] =
- (PieceDesc *) _vm->_game->loadExtData(pictDescId, 0, 0, &size);
- ptr->piecesFromExt[i] = true;
- ptr->sizes[i] = size / 8;
- } else {
- int16 size;
+ int16 pictDescId = _vm->_inter->load16();
- ptr->pieces[i] =
- (PieceDesc *) _vm->_game->loadTotResource(pictDescId, &size);
- ptr->piecesFromExt[i] = false;
- ptr->sizes[i] = size / 8;
- }
+ loadPieces(pictDescId, ptr->pieces[i], ptr->piecesCount[i]);
width = _vm->_inter->load16();
height = _vm->_inter->load16();
@@ -554,8 +549,7 @@ void Scenery::freeAnim(int16 index) {
return;
for (int i = 0; i < _animPictCount[index]; i++) {
- if (_animations[index].piecesFromExt[i])
- delete[] _animations[index].pieces[i];
+ delete[] _animations[index].pieces[i];
spr = _animPictToSprite[index * 7 + i];
_spriteRefs[spr]--;
@@ -569,8 +563,7 @@ void Scenery::freeAnim(int16 index) {
delete[] _animations[index].layers[i].frames;
delete[] _animations[index].layers;
delete[] _animations[index].pieces;
- delete[] _animations[index].piecesFromExt;
- delete[] _animations[index].sizes;
+ delete[] _animations[index].piecesCount;
_animPictCount[index] = 0;
}
@@ -620,8 +613,8 @@ void Scenery::updateAnim(int16 layer, int16 frame, int16 animation, int16 flags,
Mult::Mult_Object &obj = _vm->_mult->_objects[-animation - 1];
- if (!_vm->_vidPlayer->slotIsOpen(obj.videoSlot - 1)) {
- _toRedrawLeft = -1234;
+ if ((obj.videoSlot == 0) || !_vm->_vidPlayer->slotIsOpen(obj.videoSlot - 1)) {
+ _toRedrawLeft = -12345;
return;
}
@@ -629,8 +622,17 @@ void Scenery::updateAnim(int16 layer, int16 frame, int16 animation, int16 flags,
frame = _vm->_vidPlayer->getFramesCount(obj.videoSlot - 1) - 1;
// Seek to frame
- while (_vm->_vidPlayer->getCurrentFrame(obj.videoSlot - 1) <= frame)
- _vm->_vidPlayer->slotPlay(obj.videoSlot - 1);
+ if (_vm->_vidPlayer->getCurrentFrame(obj.videoSlot - 1) < 256) {
+ while (_vm->_vidPlayer->getCurrentFrame(obj.videoSlot - 1) <= frame)
+ _vm->_vidPlayer->slotPlay(obj.videoSlot - 1);
+ } else {
+ int16 curFrame = _vm->_vidPlayer->getCurrentFrame(obj.videoSlot - 1);
+ uint8 frameWrap = curFrame / 256;
+ frame = (frame + 1) % 256;
+
+ while (_vm->_vidPlayer->getCurrentFrame(obj.videoSlot - 1) < (frameWrap * 256 + frame))
+ _vm->_vidPlayer->slotPlay(obj.videoSlot - 1);
+ }
destX = 0;
destY = 0;
@@ -724,7 +726,7 @@ void Scenery::updateAnim(int16 layer, int16 frame, int16 animation, int16 flags,
}
- if (flags & 4) {
+ if (!(flags & 4)) {
_animLeft = _toRedrawLeft = left;
_animTop = _toRedrawTop = top;
_animRight = _toRedrawRight = right;
@@ -812,20 +814,19 @@ void Scenery::updateAnim(int16 layer, int16 frame, int16 animation, int16 flags,
pictIndex = (pictIndex & 15) - 1;
- if ((pictIndex == 0xFFFF) || (_animPictCount[animation] <= pictIndex)) {
- warning("Scenery::updateAnim: pictIndex out of range");
- return;
- }
+ if (pictIndex >= _animPictCount[animation])
+ continue;
- if (_animations[animation].sizes[pictIndex] <= pieceIndex) {
- warning("Scenery::updateAnim: pieceIndex out of range");
+ if (!pictPtr[pictIndex])
continue;
- }
- left = READ_LE_UINT16(&pictPtr[pictIndex][pieceIndex].left);
- right = READ_LE_UINT16(&pictPtr[pictIndex][pieceIndex].right);
- top = READ_LE_UINT16(&pictPtr[pictIndex][pieceIndex].top);
- bottom = READ_LE_UINT16(&pictPtr[pictIndex][pieceIndex].bottom);
+ if (pieceIndex >= _animations[animation].piecesCount[pictIndex])
+ continue;
+
+ left = pictPtr[pictIndex][pieceIndex].left;
+ right = pictPtr[pictIndex][pieceIndex].right;
+ top = pictPtr[pictIndex][pieceIndex].top;
+ bottom = pictPtr[pictIndex][pieceIndex].bottom;
if (flags & 2) {
if (destX < _vm->_mult->_animLeft) {
@@ -946,4 +947,42 @@ Scenery::AnimLayer *Scenery::getAnimLayer(uint16 index, uint16 layer) {
return &_animations[index].layers[layer];
}
+void Scenery::loadPieces(int16 pictDescId, PieceDesc *&pieceDesc, uint32 &piecesCount) {
+ byte *data;
+ uint32 size;
+ bool fromExt = false;
+
+ if (pictDescId >= 30000) {
+ fromExt = true;
+
+ uint32 eSize;
+
+ data = _vm->_game->loadExtData(pictDescId, 0, 0, &eSize);
+ size = eSize;
+ } else {
+ int16 tSize;
+
+ data = _vm->_game->loadTotResource(pictDescId, &tSize);
+ size = tSize;
+ }
+
+ if (!data)
+ error("Scenery::loadPieces(): Can't load pictDescId %d", pictDescId);
+
+ piecesCount = size / 8;
+ pieceDesc = new PieceDesc[piecesCount];
+
+ Common::MemoryReadStream pieceData(data, size);
+
+ for (uint32 i = 0; i < piecesCount; i++) {
+ pieceDesc[i].left = (int16) pieceData.readUint16LE();
+ pieceDesc[i].right = (int16) pieceData.readUint16LE();
+ pieceDesc[i].top = (int16) pieceData.readUint16LE();
+ pieceDesc[i].bottom = (int16) pieceData.readUint16LE();
+ }
+
+ if (fromExt)
+ delete[] data;
+}
+
} // End of namespace Gob
diff --git a/engines/gob/scenery.h b/engines/gob/scenery.h
index a1a1304d4d..21bf29deda 100644
--- a/engines/gob/scenery.h
+++ b/engines/gob/scenery.h
@@ -34,16 +34,16 @@ public:
#include "common/pack-start.h" // START STRUCT PACKING
struct PieceDesc {
- int16 left; //NOTE:
- int16 right; //These are stored in Little Endian format
- int16 top; //And should be converted by client code when accessed
- int16 bottom; //i.e. use FROM_LE_16()
+ int16 left;
+ int16 right;
+ int16 top;
+ int16 bottom;
} PACKED_STRUCT;
struct StaticPlane {
- int8 pictIndex;
- int8 pieceIndex;
- int8 drawOrder;
+ uint8 pictIndex;
+ uint8 pieceIndex;
+ uint8 drawOrder;
int16 destX;
int16 destY;
int8 transp;
@@ -82,19 +82,16 @@ public:
int16 layersCount;
StaticLayer *layers;
PieceDesc **pieces;
- bool *piecesFromExt;
- Static() : layersCount(0), layers(0), pieces(0),
- piecesFromExt(0) {}
+ uint32 *piecesCount;
+ Static() : layersCount(0), layers(0), pieces(0), piecesCount(0) {}
};
struct Animation {
int16 layersCount;
AnimLayer *layers;
PieceDesc **pieces;
- bool *piecesFromExt;
- uint16 *sizes;
- Animation() : layersCount(0), layers(0), pieces(0),
- piecesFromExt(0) {}
+ uint32 *piecesCount;
+ Animation() : layersCount(0), layers(0), pieces(0), piecesCount(0) {}
};
int16 _curStatic;
@@ -151,6 +148,8 @@ protected:
GobEngine *_vm;
+ void loadPieces(int16 pictDescId, PieceDesc *&pieceDesc, uint32 &piecesCount);
+
void updateStatic(int16 orderFrom, byte index, byte layer);
};
diff --git a/engines/gob/scenery_v1.cpp b/engines/gob/scenery_v1.cpp
index 5d3eb15a95..605b098693 100644
--- a/engines/gob/scenery_v1.cpp
+++ b/engines/gob/scenery_v1.cpp
@@ -23,13 +23,12 @@
*
*/
-
#include "common/endian.h"
#include "gob/gob.h"
#include "gob/scenery.h"
#include "gob/util.h"
-#include "gob/cdrom.h"
+#include "gob/sound/sound.h"
namespace Gob {
@@ -37,11 +36,11 @@ Scenery_v1::Scenery_v1(GobEngine *vm) : Scenery(vm) {
}
int16 Scenery_v1::loadAnim(char search) {
- if (_vm->_cdrom->_cdPlaying) {
- while (_vm->_cdrom->getTrackPos() != -1)
+ if (_vm->_sound->cdIsPlaying()) {
+ while (_vm->_sound->cdGetTrackPos() != -1)
_vm->_util->longDelay(50);
- _vm->_cdrom->_cdPlaying = false;
+ _vm->_sound->cdStop();
}
return Scenery::loadAnim(search);
diff --git a/engines/gob/scenery_v2.cpp b/engines/gob/scenery_v2.cpp
index 6ed377af64..1a0de6f291 100644
--- a/engines/gob/scenery_v2.cpp
+++ b/engines/gob/scenery_v2.cpp
@@ -23,7 +23,6 @@
*
*/
-
#include "common/endian.h"
#include "gob/gob.h"
diff --git a/engines/gob/sound.cpp b/engines/gob/sound.cpp
deleted file mode 100644
index 6b227cfb0e..0000000000
--- a/engines/gob/sound.cpp
+++ /dev/null
@@ -1,374 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
-
-
-#include "common/endian.h"
-
-#include "gob/gob.h"
-#include "gob/sound.h"
-#include "gob/global.h"
-#include "gob/util.h"
-#include "gob/dataio.h"
-#include "gob/game.h"
-
-namespace Gob {
-
-void SoundDesc::set(SoundType type, SoundSource src,
- byte *data, uint32 dSize) {
-
- free();
-
- _type = type;
- _source = src;
- _data = _dataPtr = data;
- _size = dSize;
-}
-
-void SoundDesc::load(SoundType type, SoundSource src,
- byte *data, uint32 dSize) {
-
- free();
-
- _source = src;
- switch (type) {
- case SOUND_ADL:
- loadADL(data, dSize);
- break;
- case SOUND_SND:
- loadSND(data, dSize);
- break;
- }
-}
-
-void SoundDesc::free() {
- if (_source != SOUND_TOT)
- delete[] _data;
- _data = _dataPtr = 0;
- _id = 0;
-}
-
-void SoundDesc::convToSigned() {
- if ((_type == SOUND_SND) && _data && _dataPtr)
- for (uint32 i = 0; i < _size; i++)
- _dataPtr[i] ^= 0x80;
-}
-
-void SoundDesc::loadSND(byte *data, uint32 dSize) {
- assert(dSize > 6);
-
- _type = SOUND_SND;
- _data = data;
- _dataPtr = data + 6;
- _frequency = MAX((int16) READ_BE_UINT16(data + 4), (int16) 4700);
- _flag = data[0] ? (data[0] & 0x7F) : 8;
- data[0] = 0;
- _size = MIN(READ_BE_UINT32(data), dSize - 6);
-}
-
-void SoundDesc::loadADL(byte *data, uint32 dSize) {
- _type = SOUND_ADL;
- _data = _dataPtr = data;
- _size = dSize;
-}
-
-Snd::Snd(GobEngine *vm) : _vm(vm) {
- _playingSound = 0;
- _curSoundDesc = 0;
-
- _rate = _vm->_mixer->getOutputRate();
- _end = true;
- _data = 0;
- _length = 0;
- _freq = 0;
- _repCount = 0;
-
- _offset = 0;
- _offsetFrac = 0;
- _offsetInc = 0;
-
- _cur = 0;
- _last = 0;
-
- _fade = false;
- _fadeVol = 65536;
- _fadeVolStep = 0;
- _fadeSamples = 0;
- _curFadeSamples = 0;
-
- _compositionSamples = 0;
- _compositionSampleCount = 0;
- _compositionPos = -1;
-
- _speakerStream = new Audio::PCSpeaker(_vm->_mixer->getOutputRate());
-
- _vm->_mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_handle,
- this, -1, 255, 0, false, true);
- _vm->_mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_speakerHandle,
- _speakerStream, -1, 50, 0, false, true);
-}
-
-Snd::~Snd() {
- // stop permanent streams manually:
-
- // First the speaker stream
- _vm->_mixer->stopHandle(_speakerHandle);
- delete _speakerStream;
-
- // Next, this stream (class Snd is an AudioStream, too)
- _vm->_mixer->stopHandle(_handle);
-}
-
-void Snd::speakerOn(int16 frequency, int32 length) {
- _speakerStream->play(Audio::PCSpeaker::kWaveFormSquare, frequency, length);
-}
-
-void Snd::speakerOff() {
- _speakerStream->stop();
-}
-
-void Snd::speakerOnUpdate(uint32 milis) {
- if (_speakerStream->isPlaying())
- _speakerStream->stop(milis);
-}
-
-void Snd::stopSound(int16 fadeLength, SoundDesc *sndDesc) {
- Common::StackLock slock(_mutex);
-
- if (sndDesc && (sndDesc != _curSoundDesc))
- return;
-
- if (fadeLength <= 0) {
- _data = 0;
- _end = true;
- _playingSound = 0;
- _curSoundDesc = 0;
- return;
- }
-
- _fade = true;
- _fadeVol = 65536;
- _fadeSamples = (int) (fadeLength * (((double) _rate) / 10.0));
- _fadeVolStep = MAX((int32) 1, (int32) (65536 / _fadeSamples));
- _curFadeSamples = 0;
-}
-
-void Snd::setRepeating(int32 repCount) {
- Common::StackLock slock(_mutex);
-
- _repCount = repCount;
-}
-
-void Snd::waitEndPlay(bool interruptible, bool stopComp) {
- if (stopComp)
- _compositionPos = -1;
- while (!_end && !_vm->_quitRequested) {
- if (interruptible && (_vm->_util->checkKey() == 0x11B)) {
- WRITE_VAR(57, -1);
- return;
- }
- _vm->_util->longDelay(200);
- }
- stopSound(0);
-}
-
-void Snd::stopComposition() {
- if (_compositionPos != -1) {
- stopSound(0);
- _compositionPos = -1;
- }
-}
-
-void Snd::nextCompositionPos() {
- int8 slot;
-
- while ((++_compositionPos < 50) &&
- ((slot = _composition[_compositionPos]) != -1)) {
- if ((slot >= 0) && (slot < _compositionSampleCount)) {
- SoundDesc &sample = _compositionSamples[slot];
- if (!sample.empty() && (sample.getType() == SOUND_SND)) {
- setSample(sample, 1, 0, 0);
- return;
- }
- }
- if (_compositionPos == 49)
- _compositionPos = -1;
- }
- _compositionPos = -1;
-}
-
-void Snd::playComposition(int16 *composition, int16 freqVal,
- SoundDesc *sndDescs, int8 sndCount) {
- int i;
-
- waitEndPlay();
- stopComposition();
-
- _compositionSamples = sndDescs ? sndDescs : _vm->_game->_soundSamples;
- _compositionSampleCount = sndCount;
-
- i = -1;
- do {
- i++;
- _composition[i] = composition[i];
- } while ((i < 50) && (composition[i] != -1));
-
- _compositionPos = -1;
- nextCompositionPos();
-}
-
-void Snd::setSample(SoundDesc &sndDesc, int16 repCount, int16 frequency,
- int16 fadeLength) {
-
- if (frequency <= 0)
- frequency = sndDesc._frequency;
-
- _curSoundDesc = &sndDesc;
- sndDesc._repCount = repCount - 1;
- sndDesc._frequency = frequency;
-
- _data = (int8 *) sndDesc.getData();
- _length = sndDesc.size();
- _freq = frequency;
-
- _repCount = repCount;
- _end = false;
- _playingSound = 1;
-
- _offset = 0;
- _offsetFrac = 0;
- _offsetInc = (_freq << FRAC_BITS) / _rate;
-
- _last = _cur;
- _cur = _data[0];
-
- _curFadeSamples = 0;
- if (fadeLength == 0) {
- _fade = false;
- _fadeVol = 65536;
- _fadeSamples = 0;
- _fadeVolStep = 0;
- } else {
- _fade = true;
- _fadeVol = 0;
- _fadeSamples = (int) (fadeLength * (((double) _rate) / 10.0));
- _fadeVolStep = - MAX((int32) 1, (int32) (65536 / _fadeSamples));
- }
-}
-
-bool Snd::loadSample(SoundDesc &sndDesc, const char *fileName) {
- byte *data;
- uint32 size;
-
- data = (byte *) _vm->_dataIO->getData(fileName);
- if (!data)
- return false;
-
- size = _vm->_dataIO->getDataSize(fileName);
- sndDesc.load(SOUND_SND, SOUND_FILE, data, size);
-
- return true;
-}
-
-void Snd::freeSample(SoundDesc &sndDesc) {
- stopSound(0, &sndDesc);
- sndDesc.free();
-}
-
-void Snd::playSample(SoundDesc &sndDesc, int16 repCount, int16 frequency,
- int16 fadeLength) {
- Common::StackLock slock(_mutex);
-
- if (!_end)
- return;
-
- setSample(sndDesc, repCount, frequency, fadeLength);
-}
-
-void Snd::checkEndSample() {
- if (_compositionPos != -1)
- nextCompositionPos();
- else if ((_repCount == -1) || (--_repCount > 0)) {
- _offset = 0;
- _offsetFrac = 0;
- _end = false;
- _playingSound = 1;
- } else {
- _end = true;
- _playingSound = 0;
- }
-}
-
-int Snd::readBuffer(int16 *buffer, const int numSamples) {
- Common::StackLock slock(_mutex);
-
- for (int i = 0; i < numSamples; i++) {
- if (!_data)
- return i;
- if (_end || (_offset >= _length))
- checkEndSample();
- if (_end)
- return i;
-
- // Linear interpolation. See sound/rate.cpp
-
- int16 val = (_last + (((_cur - _last) * _offsetFrac +
- FRAC_HALF) >> FRAC_BITS)) << 8;
- *buffer++ = (val * _fadeVol) >> 16;
-
- _offsetFrac += _offsetInc;
-
- // Was there an integral change?
- if (fracToInt(_offsetFrac) > 0) {
- _last = _cur;
- _cur = _data[_offset];
- _offset += fracToInt(_offsetFrac);
- _offsetFrac &= FRAC_LO_MASK;
- }
-
- if (_fade) {
-
- if (++_curFadeSamples >= _fadeSamples) {
- if (_fadeVolStep > 0) {
- _data = 0;
- _end = true;
- _playingSound = 0;
- _compositionPos = -1;
- _curSoundDesc = 0;
- } else {
- _fadeVol = 65536;
- _fade = false;
- }
- } else
- _fadeVol -= _fadeVolStep;
-
- if (_fadeVol < 0)
- _fadeVol = 0;
-
- }
- }
- return numSamples;
-}
-
-} // End of namespace Gob
diff --git a/engines/gob/sound.h b/engines/gob/sound.h
deleted file mode 100644
index 6780c201b5..0000000000
--- a/engines/gob/sound.h
+++ /dev/null
@@ -1,172 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * $URL$
- * $Id$
- *
- */
-
-#ifndef GOB_SOUND_H
-#define GOB_SOUND_H
-
-#include "common/mutex.h"
-#include "common/frac.h"
-#include "sound/audiostream.h"
-#include "sound/mixer.h"
-#include "sound/softsynth/pcspk.h"
-
-namespace Gob {
-
-enum SoundType {
- SOUND_SND,
- SOUND_ADL
-};
-
-enum SoundSource {
- SOUND_FILE,
- SOUND_TOT,
- SOUND_EXT
-};
-
-class SoundDesc {
-public:
- int16 _repCount;
- int16 _frequency;
- int16 _flag;
- int16 _id;
-
- byte *getData() { return _dataPtr; }
- uint32 size() { return _size; }
- bool empty() { return !_dataPtr; }
- bool isId(int16 id) { return _dataPtr && _id == id; }
- SoundType getType() { return _type; }
-
- void set(SoundType type, SoundSource src, byte *data, uint32 dSize);
- void load(SoundType type, SoundSource src, byte *data, uint32 dSize);
- void free();
- void convToSigned();
-
- // Which fade out length to use when the fade starts half-way through?
- int16 calcFadeOutLength(int16 frequency) {
- return (10 * (_size / 2)) / frequency;
- }
- uint32 calcLength(int16 repCount, int16 frequency, bool fade) {
- uint32 fadeSize = fade ? _size / 2 : 0;
- return ((_size * repCount - fadeSize) * 1000) / frequency;
- }
-
- SoundDesc() : _data(0), _dataPtr(0), _size(0), _type(SOUND_SND),
- _source(SOUND_FILE), _repCount(0), _frequency(0),
- _flag(0), _id(0) {}
- ~SoundDesc() { free(); }
-
-private:
- byte *_data;
- byte *_dataPtr;
- uint32 _size;
-
- SoundType _type;
- SoundSource _source;
-
- void loadSND(byte *data, uint32 dSize);
- void loadADL(byte *data, uint32 dSize);
-};
-
-class Snd : public Audio::AudioStream {
-public:
- char _playingSound;
-
- Snd(GobEngine *vm);
- ~Snd();
-
- void speakerOn(int16 frequency, int32 length);
- void speakerOff();
- void speakerOnUpdate(uint32 milis);
- void stopSound(int16 fadeLength, SoundDesc *sndDesc = 0);
-
- bool loadSample(SoundDesc &sndDesc, const char *fileName);
- void freeSample(SoundDesc &sndDesc);
- void playSample(SoundDesc &sndDesc, int16 repCount,
- int16 frequency, int16 fadeLength = 0);
-
- void playComposition(int16 *composition, int16 freqVal,
- SoundDesc *sndDescs = 0, int8 sndCount = 60);
- void stopComposition();
- void setRepeating(int32 repCount);
- void waitEndPlay(bool interruptible = false, bool stopComp = true);
-
- static void convToSigned(byte *buffer, int length) {
- while (length-- > 0)
- *buffer++ ^= 0x80;
- }
-
- int readBuffer(int16 *buffer, const int numSamples);
- bool isStereo() const { return false; }
- bool endOfData() const { return _end; }
- bool endOfStream() const { return false; }
- int getRate() const { return _rate; }
-
-protected:
- Audio::PCSpeaker *_speakerStream;
- Audio::SoundHandle _speakerHandle;
-
- Audio::SoundHandle *_activeHandle;
- Audio::SoundHandle _compositionHandle;
-
- SoundDesc *_compositionSamples;
- int8 _compositionSampleCount;
- int16 _composition[50];
- int8 _compositionPos;
-
- Audio::SoundHandle _handle;
- Common::Mutex _mutex;
- SoundDesc *_curSoundDesc;
- bool _end;
- int8 *_data;
- uint32 _length;
- uint32 _rate;
- int32 _freq;
- int32 _repCount;
-
- uint32 _offset;
- frac_t _offsetFrac;
- frac_t _offsetInc;
-
- int16 _cur;
- int16 _last;
-
- bool _fade;
- int32 _fadeVol;
- int32 _fadeVolStep;
- uint8 _fadeLength;
- uint32 _fadeSamples;
- uint32 _curFadeSamples;
-
- GobEngine *_vm;
-
- void setSample(SoundDesc &sndDesc, int16 repCount,
- int16 frequency, int16 fadeLength);
- void checkEndSample();
- void nextCompositionPos();
-};
-
-} // End of namespace Gob
-
-#endif // GOB_SOUND_H
diff --git a/engines/gob/music.cpp b/engines/gob/sound/adlib.cpp
index 7be046c02a..b3d392ad1e 100644
--- a/engines/gob/music.cpp
+++ b/engines/gob/sound/adlib.cpp
@@ -24,91 +24,55 @@
*/
#include "common/file.h"
-
#include "common/endian.h"
#include "gob/gob.h"
-#include "gob/music.h"
-#include "gob/game.h"
-#include "gob/util.h"
+#include "gob/sound/adlib.h"
namespace Gob {
-const char *Adlib::_tracks[][2] = {
- {"avt00.tot", "mine"},
- {"avt001.tot", "nuit"},
- {"avt002.tot", "campagne"},
- {"avt003.tot", "extsor1"},
- {"avt004.tot", "interieure"},
- {"avt005.tot", "zombie"},
- {"avt006.tot", "zombie"},
- {"avt007.tot", "campagne"},
- {"avt008.tot", "campagne"},
- {"avt009.tot", "extsor1"},
- {"avt010.tot", "extsor1"},
- {"avt011.tot", "interieure"},
- {"avt012.tot", "zombie"},
- {"avt014.tot", "nuit"},
- {"avt015.tot", "interieure"},
- {"avt016.tot", "statue"},
- {"avt017.tot", "zombie"},
- {"avt018.tot", "statue"},
- {"avt019.tot", "mine"},
- {"avt020.tot", "statue"},
- {"avt021.tot", "mine"},
- {"avt022.tot", "zombie"}
-};
-
-const char *Adlib::_trackFiles[] = {
-// "musmac1.adl", // TODO: This track isn't played correctly at all yet
- "musmac2.adl",
- "musmac3.adl",
- "musmac4.adl",
- "musmac5.adl",
- "musmac6.adl"
-};
-
-const unsigned char Adlib::_operators[] = {0, 1, 2, 8, 9, 10, 16, 17, 18};
-const unsigned char Adlib::_volRegNums[] = {
+const unsigned char AdLib::_operators[] = {0, 1, 2, 8, 9, 10, 16, 17, 18};
+const unsigned char AdLib::_volRegNums[] = {
3, 4, 5,
11, 12, 13,
19, 20, 21
};
-Adlib::Adlib(GobEngine *vm) : _vm(vm) {
- int i;
-
+AdLib::AdLib(Audio::Mixer &mixer) : _mixer(&mixer) {
_index = -1;
_data = 0;
_playPos = 0;
_dataSize = 0;
- _rate = _vm->_mixer->getOutputRate();
+
+ _rate = _mixer->getOutputRate();
_opl = makeAdlibOPL(_rate);
+
_first = true;
_ended = false;
_playing = false;
_needFree = false;
+
_repCount = -1;
_samplesTillPoll = 0;
- for (i = 0; i < 16; i ++)
+ for (int i = 0; i < 16; i ++)
_pollNotes[i] = 0;
setFreqs();
- _vm->_mixer->playInputStream(Audio::Mixer::kMusicSoundType, &_handle,
+ _mixer->playInputStream(Audio::Mixer::kMusicSoundType, &_handle,
this, -1, 255, 0, false, true);
}
-Adlib::~Adlib() {
+AdLib::~AdLib() {
Common::StackLock slock(_mutex);
- _vm->_mixer->stopHandle(_handle);
+ _mixer->stopHandle(_handle);
OPLDestroy(_opl);
if (_data && _needFree)
delete[] _data;
}
-int Adlib::readBuffer(int16 *buffer, const int numSamples) {
+int AdLib::readBuffer(int16 *buffer, const int numSamples) {
Common::StackLock slock(_mutex);
int samples;
int render;
@@ -160,12 +124,12 @@ int Adlib::readBuffer(int16 *buffer, const int numSamples) {
return numSamples;
}
-void Adlib::writeOPL(byte reg, byte val) {
- debugC(6, kDebugMusic, "writeOPL(%02X, %02X)", reg, val);
+void AdLib::writeOPL(byte reg, byte val) {
+ debugC(6, kDebugSound, "writeOPL(%02X, %02X)", reg, val);
OPLWriteReg(_opl, reg, val);
}
-void Adlib::setFreqs() {
+void AdLib::setFreqs() {
byte lin;
byte col;
long val = 0;
@@ -191,7 +155,7 @@ void Adlib::setFreqs() {
}
}
-void Adlib::reset() {
+void AdLib::reset() {
_first = true;
OPLResetChip(_opl);
_samplesTillPoll = 0;
@@ -209,13 +173,13 @@ void Adlib::reset() {
writeOPL(0x01, 0x20);
}
-void Adlib::setVoices() {
+void AdLib::setVoices() {
// Definitions of the 9 instruments
for (int i = 0; i < 9; i++)
setVoice(i, i, true);
}
-void Adlib::setVoice(byte voice, byte instr, bool set) {
+void AdLib::setVoice(byte voice, byte instr, bool set) {
int i;
int j;
uint16 strct[27];
@@ -251,7 +215,7 @@ void Adlib::setVoice(byte voice, byte instr, bool set) {
}
}
-void Adlib::setKey(byte voice, byte note, bool on, bool spec) {
+void AdLib::setKey(byte voice, byte note, bool on, bool spec) {
short freq = 0;
short octa = 0;
@@ -317,12 +281,12 @@ void Adlib::setKey(byte voice, byte note, bool on, bool spec) {
warning("Voice %d, note %02X unknown\n", voice, note);
}
-void Adlib::setVolume(byte voice, byte volume) {
+void AdLib::setVolume(byte voice, byte volume) {
volume = 0x3F - (volume * 0x7E + 0x7F) / 0xFE;
writeOPL(0x40 + _volRegNums[voice], volume);
}
-void Adlib::pollMusic() {
+void AdLib::pollMusic() {
unsigned char instr;
byte channel;
byte note;
@@ -419,24 +383,7 @@ void Adlib::pollMusic() {
_samplesTillPoll = tempo * (_rate / 1000);
}
-void Adlib::playBgMusic() {
- for (int i = 0; i < ARRAYSIZE(_tracks); i++)
- if (!scumm_stricmp(_vm->_game->_curTotFile, _tracks[i][0])) {
- playTrack(_tracks[i][1]);
- break;
- }
-}
-
-void Adlib::playTrack(const char *trackname) {
- if (_playing) return;
-
- debugC(1, kDebugMusic, "Adlib::playTrack(%s)", trackname);
- unload();
- load(_trackFiles[_vm->_util->getRandom(ARRAYSIZE(_trackFiles))]);
- startPlay();
-}
-
-bool Adlib::load(const char *fileName) {
+bool AdLib::load(const char *fileName) {
Common::File song;
unload();
@@ -457,7 +404,7 @@ bool Adlib::load(const char *fileName) {
return true;
}
-void Adlib::load(byte *data, uint32 size, int index) {
+bool AdLib::load(byte *data, uint32 size, int index) {
unload();
_repCount = 0;
@@ -468,9 +415,11 @@ void Adlib::load(byte *data, uint32 size, int index) {
reset();
setVoices();
_playPos = _data + 3 + (_data[1] + 1) * 0x38;
+
+ return true;
}
-void Adlib::unload() {
+void AdLib::unload() {
_playing = false;
_index = -1;
@@ -480,4 +429,29 @@ void Adlib::unload() {
_needFree = false;
}
+bool AdLib::isPlaying() const {
+ return _playing;
+}
+
+bool AdLib::getRepeating() const {
+ return _repCount != 0;
+}
+
+void AdLib::setRepeating(int32 repCount) {
+ _repCount = repCount;
+}
+
+int AdLib::getIndex() const {
+ return _index;
+}
+
+void AdLib::startPlay() {
+ if (_data) _playing = true;
+}
+
+void AdLib::stopPlay() {
+ Common::StackLock slock(_mutex);
+ _playing = false;
+}
+
} // End of namespace Gob
diff --git a/engines/gob/music.h b/engines/gob/sound/adlib.h
index 199ea515b0..4cd83d5883 100644
--- a/engines/gob/music.h
+++ b/engines/gob/sound/adlib.h
@@ -23,8 +23,8 @@
*
*/
-#ifndef GOB_MUSIC_H
-#define GOB_MUSIC_H
+#ifndef GOB_SOUND_ADLIB_H
+#define GOB_SOUND_ADLIB_H
#include "common/mutex.h"
#include "sound/audiostream.h"
@@ -35,61 +35,63 @@ namespace Gob {
class GobEngine;
-class Adlib : public Audio::AudioStream {
+class AdLib : public Audio::AudioStream {
public:
- Adlib(GobEngine *vm);
- ~Adlib();
-
- void lock() { _mutex.lock(); }
- void unlock() { _mutex.unlock(); }
- bool playing() const { return _playing; }
- bool getRepeating() const { return _repCount != 0; }
- void setRepeating (int32 repCount) { _repCount = repCount; }
- int getIndex() const { return _index; }
- void startPlay() { if (_data) _playing = true; }
- void stopPlay() {
- Common::StackLock slock(_mutex);
- _playing = false;
- }
- void playTrack(const char *trackname);
- void playBgMusic();
+ AdLib(Audio::Mixer &mixer);
+ ~AdLib();
+
+ bool isPlaying() const;
+ int getIndex() const;
+ bool getRepeating() const;
+
+ void setRepeating(int32 repCount);
+
+ void startPlay();
+ void stopPlay();
+
bool load(const char *fileName);
- void load(byte *data, uint32 size, int index = -1);
+ bool load(byte *data, uint32 size, int index = -1);
void unload();
// AudioStream API
- int readBuffer(int16 *buffer, const int numSamples);
- bool isStereo() const { return false; }
- bool endOfData() const { return !_playing; }
- bool endOfStream() const { return false; }
- int getRate() const { return _rate; }
+ int readBuffer(int16 *buffer, const int numSamples);
+ bool isStereo() const { return false; }
+ bool endOfData() const { return !_playing; }
+ bool endOfStream() const { return false; }
+ int getRate() const { return _rate; }
protected:
- static const char *_tracks[][2];
- static const char *_trackFiles[];
static const unsigned char _operators[];
static const unsigned char _volRegNums [];
+
+ Audio::Mixer *_mixer;
Audio::SoundHandle _handle;
FM_OPL *_opl;
- int _index;
+
+ Common::Mutex _mutex;
+
+ uint32 _rate;
+
byte *_data;
byte *_playPos;
uint32 _dataSize;
- uint32 _rate;
+
short _freqs[25][12];
byte _notes[11];
byte _notCol[11];
byte _notLin[11];
bool _notOn[11];
byte _pollNotes[16];
+
int _samplesTillPoll;
int32 _repCount;
+
bool _playing;
bool _first;
bool _ended;
bool _needFree;
- Common::Mutex _mutex;
- GobEngine *_vm;
+
+ int _index;
void writeOPL(byte reg, byte val);
void setFreqs();
@@ -103,4 +105,4 @@ protected:
} // End of namespace Gob
-#endif // GOB_MUSIC_H
+#endif // GOB_SOUND_ADLIB_H
diff --git a/engines/gob/sound/bgatmosphere.cpp b/engines/gob/sound/bgatmosphere.cpp
new file mode 100644
index 0000000000..f5a7fe0fdb
--- /dev/null
+++ b/engines/gob/sound/bgatmosphere.cpp
@@ -0,0 +1,128 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/system.h"
+#include "common/events.h"
+
+#include "gob/sound/bgatmosphere.h"
+
+namespace Gob {
+
+BackgroundAtmosphere::BackgroundAtmosphere(Audio::Mixer &mixer) :
+ SoundMixer(mixer, Audio::Mixer::kMusicSoundType) {
+
+ _playMode = kPlayModeLinear;
+ _queuePos = -1;
+ _shaded = false;
+
+ g_system->getEventManager()->registerRandomSource(_rnd, "gobBA");
+}
+
+BackgroundAtmosphere::~BackgroundAtmosphere() {
+ queueClear();
+}
+
+void BackgroundAtmosphere::play() {
+ Common::StackLock slock(_mutex);
+
+ _queuePos = -1;
+ getNextQueuePos();
+
+ if (_queuePos == -1)
+ return;
+
+ SoundMixer::play(*_queue[_queuePos], 1, 0);
+}
+
+void BackgroundAtmosphere::stop() {
+ SoundMixer::stop(0);
+}
+
+void BackgroundAtmosphere::setPlayMode(PlayMode mode) {
+ _playMode = mode;
+}
+
+void BackgroundAtmosphere::queueSample(SoundDesc &sndDesc) {
+ Common::StackLock slock(_mutex);
+
+ _queue.push_back(&sndDesc);
+}
+
+void BackgroundAtmosphere::queueClear() {
+ Common::StackLock slock(_mutex);
+
+ SoundMixer::stop(0);
+ for (uint i = 0; i < _queue.size(); i++)
+ delete _queue[i];
+
+ _queue.clear();
+ _queuePos = -1;
+}
+
+void BackgroundAtmosphere::checkEndSample() {
+ Common::StackLock slock(_mutex);
+
+ getNextQueuePos();
+
+ if (_queuePos == -1) {
+ _end = true;
+ _playingSound = 0;
+ } else {
+ SoundMixer::setSample(*_queue[_queuePos], 1, 0, 0);
+ if (_shaded)
+ _fadeVol = 20000;
+ }
+}
+
+void BackgroundAtmosphere::getNextQueuePos() {
+ if (_queue.size() == 0) {
+ _queuePos = -1;
+ return;
+ }
+
+ switch (_playMode) {
+
+ case kPlayModeLinear:
+ _queuePos = (_queuePos + 1) % _queue.size();
+ break;
+
+ case kPlayModeRandom:
+ _queuePos = _rnd.getRandomNumber(_queue.size() - 1);
+ break;
+
+ }
+}
+
+void BackgroundAtmosphere::shade() {
+ _shaded = true;
+ _fadeVol = 32768;
+}
+
+void BackgroundAtmosphere::unshade() {
+ _shaded = false;
+ _fadeVol = 65536;
+}
+
+} // End of namespace Gob
diff --git a/engines/gob/sound/bgatmosphere.h b/engines/gob/sound/bgatmosphere.h
new file mode 100644
index 0000000000..72b5614282
--- /dev/null
+++ b/engines/gob/sound/bgatmosphere.h
@@ -0,0 +1,75 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef GOB_SOUND_BGATMOSPHERE_H
+#define GOB_SOUND_BGATMOSPHERE_H
+
+#include "sound/mixer.h"
+#include "common/mutex.h"
+
+#include "gob/sound/sounddesc.h"
+#include "gob/sound/soundmixer.h"
+
+namespace Gob {
+
+class BackgroundAtmosphere : private SoundMixer {
+public:
+ enum PlayMode {
+ kPlayModeLinear,
+ kPlayModeRandom
+ };
+
+ BackgroundAtmosphere(Audio::Mixer &mixer);
+ ~BackgroundAtmosphere();
+
+ void play();
+ void stop();
+
+ void setPlayMode(PlayMode mode);
+
+ void queueSample(SoundDesc &sndDesc);
+ void queueClear();
+
+ void shade();
+ void unshade();
+
+private:
+ PlayMode _playMode;
+
+ Common::Array<SoundDesc *> _queue;
+ int _queuePos;
+ bool _shaded;
+
+ Common::Mutex _mutex;
+
+ Common::RandomSource _rnd;
+
+ void checkEndSample();
+ void getNextQueuePos();
+};
+
+} // End of namespace Gob
+
+#endif // GOB_SOUND_BGATMOSPHERE_H
diff --git a/engines/gob/cdrom.cpp b/engines/gob/sound/cdrom.cpp
index c037d24bbe..eef8025cc2 100644
--- a/engines/gob/cdrom.cpp
+++ b/engines/gob/sound/cdrom.cpp
@@ -23,20 +23,16 @@
*
*/
-
#include "common/endian.h"
+#include "common/util.h"
#include "sound/audiocd.h"
#include "gob/gob.h"
-#include "gob/cdrom.h"
-#include "gob/global.h"
-#include "gob/util.h"
-#include "gob/dataio.h"
-#include "gob/game.h"
+#include "gob/sound/cdrom.h"
namespace Gob {
-CDROM::CDROM(GobEngine *vm) : _vm(vm) {
+CDROM::CDROM() {
_cdPlaying = false;
_LICbuffer = 0;
@@ -47,116 +43,46 @@ CDROM::CDROM(GobEngine *vm) : _vm(vm) {
_startTime = 0;
}
-void CDROM::readLIC(const char *fname) {
- char tmp[80];
- int handle;
- uint16 version, startChunk, pos;
+CDROM::~CDROM() {
+}
- freeLICbuffer();
+void CDROM::readLIC(DataStream &stream) {
+ uint16 version, startChunk, pos;
+ freeLICBuffer();
*_curTrack = 0;
- strncpy0(tmp, fname, 79);
-
- handle = _vm->_dataIO->openData(tmp);
-
- if (handle == -1)
- return;
-
- _vm->_dataIO->closeData(handle);
-
- _vm->_dataIO->getUnpackedData(tmp);
-
- handle = _vm->_dataIO->openData(tmp);
- DataStream *stream = _vm->_dataIO->openAsStream(handle, true);
-
- version = stream->readUint16LE();
- startChunk = stream->readUint16LE();
- _numTracks = stream->readUint16LE();
+ version = stream.readUint16LE();
+ startChunk = stream.readUint16LE();
+ _numTracks = stream.readUint16LE();
if (version != 3)
- error("%s: Unknown version %d", fname, version);
+ error("Unknown version %d while reading LIC", version);
- stream->seek(50);
+ stream.seek(50);
for (int i = 0; i < startChunk; i++) {
- pos = stream->readUint16LE();
+ pos = stream.readUint16LE();
if (!pos)
break;
- stream->skip(pos);
+ stream.skip(pos);
}
_LICbuffer = new byte[_numTracks * 22];
- stream->read(_LICbuffer, _numTracks * 22);
-
- delete stream;
+ stream.read(_LICbuffer, _numTracks * 22);
}
-void CDROM::freeLICbuffer() {
+void CDROM::freeLICBuffer() {
delete[] _LICbuffer;
_LICbuffer = 0;
}
-void CDROM::playBgMusic() {
- static const char *tracks[][2] = {
- {"avt00.tot", "mine"},
- {"avt001.tot", "nuit"},
- {"avt002.tot", "campagne"},
- {"avt003.tot", "extsor1"},
- {"avt004.tot", "interieure"},
- {"avt005.tot", "zombie"},
- {"avt006.tot", "zombie"},
- {"avt007.tot", "campagne"},
- {"avt008.tot", "campagne"},
- {"avt009.tot", "extsor1"},
- {"avt010.tot", "extsor1"},
- {"avt011.tot", "interieure"},
- {"avt012.tot", "zombie"},
- {"avt014.tot", "nuit"},
- {"avt015.tot", "interieure"},
- {"avt016.tot", "statue"},
- {"avt017.tot", "zombie"},
- {"avt018.tot", "statue"},
- {"avt019.tot", "mine"},
- {"avt020.tot", "statue"},
- {"avt021.tot", "mine"},
- {"avt022.tot", "zombie"}
- };
-
- for (int i = 0; i < ARRAYSIZE(tracks); i++)
- if (!scumm_stricmp(_vm->_game->_curTotFile, tracks[i][0])) {
- startTrack(tracks[i][1]);
- break;
- }
-}
-
-void CDROM::playMultMusic() {
- static const char *tracks[][6] = {
- {"avt005.tot", "fra1", "all1", "ang1", "esp1", "ita1"},
- {"avt006.tot", "fra2", "all2", "ang2", "esp2", "ita2"},
- {"avt012.tot", "fra3", "all3", "ang3", "esp3", "ita3"},
- {"avt016.tot", "fra4", "all4", "ang4", "esp4", "ita4"},
- {"avt019.tot", "fra5", "all5", "ang5", "esp5", "ita5"},
- {"avt022.tot", "fra6", "all6", "ang6", "esp6", "ita6"}
- };
-
- // Default to "ang?" for other languages (including EN_USA)
- int language = _vm->_global->_language <= 4 ? _vm->_global->_language : 2;
- for (int i = 0; i < ARRAYSIZE(tracks); i++)
- if (!scumm_stricmp(_vm->_game->_curTotFile, tracks[i][0])) {
- startTrack(tracks[i][language + 1]);
- break;
- }
-}
-
void CDROM::startTrack(const char *trackName) {
if (!_LICbuffer)
return;
- debugC(1, kDebugMusic, "CDROM::startTrack(%s)", trackName);
-
byte *matchPtr = getTrackBuffer(trackName);
if (!matchPtr) {
warning("Track \"%s\" not found", trackName);
@@ -175,7 +101,7 @@ void CDROM::startTrack(const char *trackName) {
play(start, end);
- _startTime = _vm->_util->getTimeKey();
+ _startTime = g_system->getMillis();
_trackStop = _startTime + (end - start + 1 + 150) * 40 / 3;
}
@@ -186,17 +112,19 @@ void CDROM::play(uint32 from, uint32 to) {
// HSG encodes frame information into a double word:
// minute multiplied by 4500, plus second multiplied by 75,
// plus frame, minus 150
- debugC(1, kDebugMusic, "CDROM::play(%d, %d)", from, to);
-
AudioCD.play(1, 1, from, to - from + 1);
_cdPlaying = true;
}
-int32 CDROM::getTrackPos(const char *keyTrack) {
+bool CDROM::isPlaying() const {
+ return _cdPlaying;
+}
+
+int32 CDROM::getTrackPos(const char *keyTrack) const {
byte *keyBuffer = getTrackBuffer(keyTrack);
- uint32 curPos = (_vm->_util->getTimeKey() - _startTime) * 3 / 40;
+ uint32 curPos = (g_system->getMillis() - _startTime) * 3 / 40;
- if (_cdPlaying && (_vm->_util->getTimeKey() < _trackStop)) {
+ if (_cdPlaying && (g_system->getMillis() < _trackStop)) {
if (keyBuffer && _curTrackBuffer && (keyBuffer != _curTrackBuffer)) {
uint32 kStart = READ_LE_UINT32(keyBuffer + 12);
uint32 kEnd = READ_LE_UINT32(keyBuffer + 16);
@@ -216,7 +144,7 @@ int32 CDROM::getTrackPos(const char *keyTrack) {
return -1;
}
-const char *CDROM::getCurTrack() {
+const char *CDROM::getCurTrack() const {
return _curTrack;
}
@@ -227,8 +155,6 @@ void CDROM::stopPlaying() {
}
void CDROM::stop() {
- debugC(1, kDebugMusic, "CDROM::stop()");
-
_curTrackBuffer = 0;
AudioCD.stop();
_cdPlaying = false;
@@ -248,7 +174,7 @@ void CDROM::testCD(int trySubst, const char *label) {
// CD secor reading
}
-byte *CDROM::getTrackBuffer(const char *trackName) {
+byte *CDROM::getTrackBuffer(const char *trackName) const {
if (!_LICbuffer || !trackName)
return 0;
diff --git a/engines/gob/cdrom.h b/engines/gob/sound/cdrom.h
index 25490de5dc..201f7adb75 100644
--- a/engines/gob/cdrom.h
+++ b/engines/gob/sound/cdrom.h
@@ -23,29 +23,30 @@
*
*/
-#ifndef GOB_CDROM_H
-#define GOB_CDROM_H
+#ifndef GOB_SOUND_CDROM_H
+#define GOB_SOUND_CDROM_H
+
+#include "gob/dataio.h"
namespace Gob {
class CDROM {
public:
- bool _cdPlaying;
+ CDROM();
+ ~CDROM();
- void readLIC(const char *fname);
- void freeLICbuffer();
+ void readLIC(DataStream &stream);
+ void freeLICBuffer();
void startTrack(const char *trackName);
- void playBgMusic();
- void playMultMusic();
- void play(uint32 from, uint32 to);
- int32 getTrackPos(const char *keyTrack = 0);
- const char *getCurTrack();
void stopPlaying();
- void stop();
- void testCD(int trySubst, const char *label);
- CDROM(GobEngine *vm);
+ bool isPlaying() const;
+
+ int32 getTrackPos(const char *keyTrack = 0) const;
+ const char *getCurTrack() const;
+
+ void testCD(int trySubst, const char *label);
protected:
byte *_LICbuffer;
@@ -54,11 +55,14 @@ protected:
uint16 _numTracks;
uint32 _trackStop;
uint32 _startTime;
- GobEngine *_vm;
+ bool _cdPlaying;
+
+ void play(uint32 from, uint32 to);
+ void stop();
- byte *getTrackBuffer(const char *trackName);
+ byte *getTrackBuffer(const char *trackName) const;
};
} // End of namespace Gob
-#endif // GOB_CDROM_H
+#endif // GOB_SOUND_CDROM_H
diff --git a/engines/gob/sound/infogrames.cpp b/engines/gob/sound/infogrames.cpp
new file mode 100644
index 0000000000..0b46f3485c
--- /dev/null
+++ b/engines/gob/sound/infogrames.cpp
@@ -0,0 +1,103 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "gob/sound/infogrames.h"
+
+namespace Gob {
+
+Infogrames::Infogrames(Audio::Mixer &mixer) : _mixer(&mixer) {
+ _instruments = 0;
+ _song = 0;
+}
+
+Infogrames::~Infogrames() {
+ clearSong();
+ clearInstruments();
+}
+
+bool Infogrames::loadInstruments(const char *fileName) {
+ clearSong();
+ clearInstruments();
+
+ return loadInst(fileName);
+}
+
+bool Infogrames::loadSong(const char *fileName) {
+ clearSong();
+
+ if (!_instruments)
+ if (!loadInst("i1.ins"))
+ return false;
+
+ _song = new Audio::Infogrames(*_instruments, true,
+ _mixer->getOutputRate(), _mixer->getOutputRate() / 75);
+
+ if (!_song->load(fileName)) {
+ warning("Couldn't load infogrames music");
+ clearSong();
+ return false;
+ }
+
+ return true;
+}
+
+void Infogrames::play() {
+ if (_song && !_mixer->isSoundHandleActive(_handle)) {
+ _song->restart();
+ _mixer->playInputStream(Audio::Mixer::kMusicSoundType,
+ &_handle, _song, -1, 255, 0, false);
+ }
+}
+
+void Infogrames::stop() {
+ _mixer->stopHandle(_handle);
+}
+
+void Infogrames::clearInstruments() {
+ delete _instruments;
+ _instruments = 0;
+}
+
+void Infogrames::clearSong() {
+ if (_song) {
+ _mixer->stopHandle(_handle);
+
+ delete _song;
+ _song = 0;
+ }
+}
+
+bool Infogrames::loadInst(const char *fileName) {
+ _instruments = new Audio::Infogrames::Instruments;
+ if (!_instruments->load(fileName)) {
+ warning("Couldn't load instruments file");
+ clearInstruments();
+ return false;
+ }
+
+ return true;
+}
+
+} // End of namespace Gob
diff --git a/engines/gob/sound/infogrames.h b/engines/gob/sound/infogrames.h
new file mode 100644
index 0000000000..4a20dceb22
--- /dev/null
+++ b/engines/gob/sound/infogrames.h
@@ -0,0 +1,60 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef GOB_SOUND_INFOGRAMES_H
+#define GOB_SOUND_INFOGRAMES_H
+
+#include "sound/mixer.h"
+#include "sound/mods/infogrames.h"
+
+namespace Gob {
+
+class Infogrames {
+public:
+ Infogrames(Audio::Mixer &mixer);
+ ~Infogrames();
+
+ bool loadInstruments(const char *fileName);
+ bool loadSong(const char *fileName);
+
+ void play();
+ void stop();
+
+private:
+ Audio::Mixer *_mixer;
+
+ Audio::Infogrames::Instruments *_instruments;
+ Audio::Infogrames *_song;
+ Audio::SoundHandle _handle;
+
+ void clearInstruments();
+ void clearSong();
+
+ bool loadInst(const char *fileName);
+};
+
+} // End of namespace Gob
+
+#endif // GOB_SOUND_INFOGRAMES_H
diff --git a/engines/gob/sound/pcspeaker.cpp b/engines/gob/sound/pcspeaker.cpp
new file mode 100644
index 0000000000..0d1fc0a6db
--- /dev/null
+++ b/engines/gob/sound/pcspeaker.cpp
@@ -0,0 +1,55 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "gob/sound/pcspeaker.h"
+
+namespace Gob {
+
+PCSpeaker::PCSpeaker(Audio::Mixer &mixer) : _mixer(&mixer) {
+
+ _stream = new Audio::PCSpeaker(_mixer->getOutputRate());
+ _mixer->playInputStream(Audio::Mixer::kSFXSoundType,
+ &_handle, _stream, -1, 50, 0, false, true);
+}
+
+PCSpeaker::~PCSpeaker() {
+ _mixer->stopHandle(_handle);
+ delete _stream;
+}
+
+void PCSpeaker::speakerOn(int16 frequency, int32 length) {
+ _stream->play(Audio::PCSpeaker::kWaveFormSquare, frequency, length);
+}
+
+void PCSpeaker::speakerOff() {
+ _stream->stop();
+}
+
+void PCSpeaker::onUpdate(uint32 millis) {
+ if (_stream->isPlaying())
+ _stream->stop(millis);
+}
+
+} // End of namespace Gob
diff --git a/engines/gob/sound/pcspeaker.h b/engines/gob/sound/pcspeaker.h
new file mode 100644
index 0000000000..8c4fb08021
--- /dev/null
+++ b/engines/gob/sound/pcspeaker.h
@@ -0,0 +1,52 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef GOB_SOUND_PCSPEAKER_H
+#define GOB_SOUND_PCSPEAKER_H
+
+#include "sound/mixer.h"
+#include "sound/softsynth/pcspk.h"
+
+namespace Gob {
+
+class PCSpeaker {
+public:
+ PCSpeaker(Audio::Mixer &mixer);
+ ~PCSpeaker();
+
+ void speakerOn(int16 frequency, int32 length = -1);
+ void speakerOff();
+ void onUpdate(uint32 millis);
+
+private:
+ Audio::Mixer *_mixer;
+
+ Audio::PCSpeaker *_stream;
+ Audio::SoundHandle _handle;
+};
+
+} // End of namespace Gob
+
+#endif // GOB_SOUND_PCSPEAKER_H
diff --git a/engines/gob/sound/sound.cpp b/engines/gob/sound/sound.cpp
new file mode 100644
index 0000000000..2d2bf8e043
--- /dev/null
+++ b/engines/gob/sound/sound.cpp
@@ -0,0 +1,582 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "gob/gob.h"
+#include "gob/sound/sound.h"
+#include "gob/global.h"
+#include "gob/util.h"
+#include "gob/dataio.h"
+#include "gob/game.h"
+#include "gob/inter.h"
+
+namespace Gob {
+
+Sound::Sound(GobEngine *vm) : _vm(vm) {
+ _pcspeaker = new PCSpeaker(*_vm->_mixer);
+ _blaster = new SoundBlaster(*_vm->_mixer);
+
+ _adlib = 0;
+ _infogrames = 0;
+ _cdrom = 0;
+ _bgatmos = 0;
+
+ if (!_vm->_noMusic && _vm->hasAdlib())
+ _adlib = new AdLib(*_vm->_mixer);
+ if (!_vm->_noMusic && (_vm->getPlatform() == Common::kPlatformAmiga))
+ _infogrames = new Infogrames(*_vm->_mixer);
+ if (_vm->isCD())
+ _cdrom = new CDROM;
+ if (_vm->getGameType() == kGameTypeWoodruff)
+ _bgatmos = new BackgroundAtmosphere(*_vm->_mixer);
+}
+
+Sound::~Sound() {
+ delete _pcspeaker;
+ delete _blaster;
+ delete _adlib;
+ delete _infogrames;
+ delete _cdrom;
+ delete _bgatmos;
+
+ for (int i = 0; i < kSoundsCount; i++)
+ _sounds[i].free();
+}
+
+void Sound::convToSigned(byte *buffer, int length) {
+ while (length-- > 0)
+ *buffer++ ^= 0x80;
+}
+
+SoundDesc *Sound::sampleGetBySlot(int slot) {
+ if ((slot < 0) || (slot >= kSoundsCount))
+ return 0;
+
+ return &_sounds[slot];
+}
+
+const SoundDesc *Sound::sampleGetBySlot(int slot) const {
+ if ((slot < 0) || (slot >= kSoundsCount))
+ return 0;
+
+ return &_sounds[slot];
+}
+
+int Sound::sampleGetNextFreeSlot() const {
+ for (int i = 0; i < kSoundsCount; i++)
+ if (_sounds[i].empty())
+ return i;
+
+ return -1;
+}
+
+bool Sound::sampleLoad(SoundDesc *sndDesc, const char *fileName, bool tryExist) {
+ if (!sndDesc)
+ return false;
+
+ debugC(2, kDebugSound, "Loading sample \"%s\"", fileName);
+
+ int16 handle = _vm->_dataIO->openData(fileName);
+ if (handle < 0) {
+ warning("Can't open sample file \"%s\"", fileName);
+ return false;
+ }
+
+ _vm->_dataIO->closeData(handle);
+
+ byte *data;
+ uint32 size;
+
+ data = (byte *) _vm->_dataIO->getData(fileName);
+ if (!data)
+ return false;
+
+ size = _vm->_dataIO->getDataSize(fileName);
+ sndDesc->load(SOUND_SND, SOUND_FILE, data, size);
+
+ return true;
+}
+
+void Sound::sampleFree(SoundDesc *sndDesc, bool noteAdlib, int index) {
+ if (!sndDesc || sndDesc->empty())
+ return;
+
+ if (sndDesc->getType() == SOUND_ADL) {
+
+ if (_adlib && noteAdlib)
+ if ((index == -1) || (_adlib->getIndex() == index))
+ _adlib->stopPlay();
+
+ } else {
+
+ if (_blaster)
+ _blaster->stopSound(0, sndDesc);
+
+ }
+
+ sndDesc->free();
+}
+
+void Sound::speakerOn(int16 frequency, int32 length) {
+ if (!_pcspeaker)
+ return;
+
+ debugC(1, kDebugSound, "PCSpeaker: Playing tone (%d, %d)", frequency, length);
+
+ _pcspeaker->speakerOn(frequency, length);
+}
+
+void Sound::speakerOff() {
+ if (!_pcspeaker)
+ return;
+
+ debugC(1, kDebugSound, "PCSpeaker: Stopping tone");
+
+ _pcspeaker->speakerOff();
+}
+
+void Sound::speakerOnUpdate(uint32 millis) {
+ if (!_pcspeaker)
+ return;
+
+ _pcspeaker->onUpdate(millis);
+}
+
+bool Sound::infogramesLoadInstruments(const char *fileName) {
+ if (!_infogrames)
+ return false;
+
+ debugC(1, kDebugSound, "Infogrames: Loading instruments \"%s\"", fileName);
+
+ return _infogrames->loadInstruments(fileName);
+}
+
+bool Sound::infogramesLoadSong(const char *fileName) {
+ if (!_infogrames)
+ return false;
+
+ debugC(1, kDebugSound, "Infogrames: Loading song \"%s\"", fileName);
+
+ return _infogrames->loadSong(fileName);
+}
+
+void Sound::infogramesPlay() {
+ if (!_infogrames)
+ return;
+
+ debugC(1, kDebugSound, "Infogrames: Starting playback");
+
+ _infogrames->play();
+}
+
+void Sound::infogramesStop() {
+ if (!_infogrames)
+ return;
+
+ debugC(1, kDebugSound, "Infogrames: Stopping playback");
+
+ _infogrames->stop();
+}
+
+bool Sound::adlibLoad(const char *fileName) {
+ if (!_adlib)
+ return false;
+
+ debugC(1, kDebugSound, "Adlib: Loading data (\"%s\")", fileName);
+
+ return _adlib->load(fileName);
+}
+
+bool Sound::adlibLoad(byte *data, uint32 size, int index) {
+ if (!_adlib)
+ return false;
+
+ debugC(1, kDebugSound, "Adlib: Loading data (%d)", index);
+
+ return _adlib->load(data, size, index);
+}
+
+void Sound::adlibUnload() {
+ if (!_adlib)
+ return;
+
+ debugC(1, kDebugSound, "Adlib: Unloading data");
+
+ _adlib->unload();
+}
+
+void Sound::adlibPlayTrack(const char *trackname) {
+ if (!_adlib || _adlib->isPlaying())
+ return;
+
+ debugC(1, kDebugSound, "Adlib: Playing track \"%s\"", trackname);
+
+ _adlib->unload();
+ _adlib->load(trackname);
+ _adlib->startPlay();
+}
+
+void Sound::adlibPlayBgMusic() {
+ if (!_adlib)
+ return;
+
+ static const char *tracks[] = {
+// "musmac1.adl", // TODO: This track isn't played correctly at all yet
+ "musmac2.adl",
+ "musmac3.adl",
+ "musmac4.adl",
+ "musmac5.adl",
+ "musmac6.adl"
+ };
+
+ int track = _vm->_util->getRandom(ARRAYSIZE(tracks));
+ adlibPlayTrack(tracks[track]);
+}
+
+void Sound::adlibPlay() {
+ if (!_adlib)
+ return;
+
+ debugC(1, kDebugSound, "Adlib: Starting playback");
+
+ _adlib->startPlay();
+}
+
+void Sound::adlibStop() {
+ if (!_adlib)
+ return;
+
+ debugC(1, kDebugSound, "Adlib: Stopping playback");
+
+ _adlib->stopPlay();
+}
+
+bool Sound::adlibIsPlaying() const {
+ if (!_adlib)
+ return false;
+
+ return _adlib->isPlaying();
+}
+
+int Sound::adlibGetIndex() const {
+ if (!_adlib)
+ return -1;
+
+ return _adlib->getIndex();
+}
+
+bool Sound::adlibGetRepeating() const {
+ if (!_adlib)
+ return false;
+
+ return _adlib->getRepeating();
+}
+
+void Sound::adlibSetRepeating(int32 repCount) {
+ if (!_adlib)
+ return;
+
+ _adlib->setRepeating(repCount);
+}
+
+void Sound::blasterPlay(SoundDesc *sndDesc, int16 repCount,
+ int16 frequency, int16 fadeLength) {
+ if (!_blaster || !sndDesc)
+ return;
+
+ debugC(1, kDebugSound, "SoundBlaster: Playing sample (%d, %d, %d)",
+ repCount, frequency, fadeLength);
+
+ _blaster->playSample(*sndDesc, repCount, frequency, fadeLength);
+}
+
+void Sound::blasterStop(int16 fadeLength, SoundDesc *sndDesc) {
+ if (!_blaster)
+ return;
+
+ debugC(1, kDebugSound, "SoundBlaster: Stopping playback");
+
+ _blaster->stopSound(fadeLength, sndDesc);
+}
+
+void Sound::blasterPlayComposition(int16 *composition, int16 freqVal,
+ SoundDesc *sndDescs, int8 sndCount) {
+ if (!_blaster)
+ return;
+
+ debugC(1, kDebugSound, "SoundBlaster: Playing composition (%d, %d)",
+ freqVal, sndCount);
+
+ blasterWaitEndPlay();
+ _blaster->stopComposition();
+
+ if (!sndDescs)
+ sndDescs = _sounds;
+
+ _blaster->playComposition(composition, freqVal, sndDescs, sndCount);
+}
+
+void Sound::blasterStopComposition() {
+ if (!_blaster)
+ return;
+
+ debugC(1, kDebugSound, "SoundBlaster: Stopping composition");
+
+ _blaster->stopComposition();
+}
+
+char Sound::blasterPlayingSound() const {
+ if (!_blaster)
+ return 0;
+
+ return _blaster->getPlayingSound();
+}
+
+void Sound::blasterSetRepeating(int32 repCount) {
+ if (!_blaster)
+ return;
+
+ _blaster->setRepeating(repCount);
+}
+
+void Sound::blasterWaitEndPlay(bool interruptible, bool stopComp) {
+ if (!_blaster)
+ return;
+
+ debugC(1, kDebugSound, "SoundBlaster: Waiting for playback to end");
+
+ if (stopComp)
+ _blaster->endComposition();
+
+ while (_blaster->isPlaying() && !_vm->_quitRequested) {
+ if (interruptible && (_vm->_util->checkKey() == 0x11B)) {
+ WRITE_VAR(57, (uint32) -1);
+ return;
+ }
+ _vm->_util->longDelay(200);
+ }
+
+ _blaster->stopSound(0);
+}
+
+void Sound::cdLoadLIC(const char *fname) {
+ if (!_cdrom)
+ return;
+
+ debugC(1, kDebugSound, "CDROM: Loading LIC \"%s\"", fname);
+
+ int handle = _vm->_dataIO->openData(fname);
+
+ if (handle == -1)
+ return;
+
+ _vm->_dataIO->closeData(handle);
+
+ _vm->_dataIO->getUnpackedData(fname);
+
+ handle = _vm->_dataIO->openData(fname);
+ DataStream *stream = _vm->_dataIO->openAsStream(handle, true);
+
+ _cdrom->readLIC(*stream);
+
+ delete stream;
+}
+
+void Sound::cdUnloadLIC() {
+ if (!_cdrom)
+ return;
+
+ debugC(1, kDebugSound, "CDROM: Unloading LIC");
+
+ _cdrom->freeLICBuffer();
+}
+
+void Sound::cdPlayBgMusic() {
+ if (!_cdrom)
+ return;
+
+ static const char *tracks[][2] = {
+ {"avt00.tot", "mine"},
+ {"avt001.tot", "nuit"},
+ {"avt002.tot", "campagne"},
+ {"avt003.tot", "extsor1"},
+ {"avt004.tot", "interieure"},
+ {"avt005.tot", "zombie"},
+ {"avt006.tot", "zombie"},
+ {"avt007.tot", "campagne"},
+ {"avt008.tot", "campagne"},
+ {"avt009.tot", "extsor1"},
+ {"avt010.tot", "extsor1"},
+ {"avt011.tot", "interieure"},
+ {"avt012.tot", "zombie"},
+ {"avt014.tot", "nuit"},
+ {"avt015.tot", "interieure"},
+ {"avt016.tot", "statue"},
+ {"avt017.tot", "zombie"},
+ {"avt018.tot", "statue"},
+ {"avt019.tot", "mine"},
+ {"avt020.tot", "statue"},
+ {"avt021.tot", "mine"},
+ {"avt022.tot", "zombie"}
+ };
+
+ for (int i = 0; i < ARRAYSIZE(tracks); i++)
+ if (!scumm_stricmp(_vm->_game->_curTotFile, tracks[i][0])) {
+ debugC(1, kDebugSound, "CDROM: Playing background music \"%s\" (\"%s\")",
+ tracks[i][1], _vm->_game->_curTotFile);
+
+ _cdrom->startTrack(tracks[i][1]);
+ break;
+ }
+}
+
+void Sound::cdPlayMultMusic() {
+ if (!_cdrom)
+ return;
+
+ static const char *tracks[][6] = {
+ {"avt005.tot", "fra1", "all1", "ang1", "esp1", "ita1"},
+ {"avt006.tot", "fra2", "all2", "ang2", "esp2", "ita2"},
+ {"avt012.tot", "fra3", "all3", "ang3", "esp3", "ita3"},
+ {"avt016.tot", "fra4", "all4", "ang4", "esp4", "ita4"},
+ {"avt019.tot", "fra5", "all5", "ang5", "esp5", "ita5"},
+ {"avt022.tot", "fra6", "all6", "ang6", "esp6", "ita6"}
+ };
+
+ // Default to "ang?" for other languages (including EN_USA)
+ int language = _vm->_global->_language <= 4 ? _vm->_global->_language : 2;
+ for (int i = 0; i < ARRAYSIZE(tracks); i++)
+ if (!scumm_stricmp(_vm->_game->_curTotFile, tracks[i][0])) {
+ debugC(1, kDebugSound, "CDROM: Playing mult music \"%s\" (\"%s\")",
+ tracks[i][language + 1], _vm->_game->_curTotFile);
+
+ _cdrom->startTrack(tracks[i][language + 1]);
+ break;
+ }
+}
+
+void Sound::cdPlay(const char *trackName) {
+ if (!_cdrom)
+ return;
+
+ debugC(1, kDebugSound, "CDROM: Playing track \"%s\"", trackName);
+ _cdrom->startTrack(trackName);
+}
+
+void Sound::cdStop() {
+ if (!_cdrom)
+ return;
+
+ debugC(1, kDebugSound, "CDROM: Stopping playback");
+ _cdrom->stopPlaying();
+}
+
+bool Sound::cdIsPlaying() const {
+ if (!_cdrom)
+ return false;
+
+ return _cdrom->isPlaying();
+}
+
+int32 Sound::cdGetTrackPos(const char *keyTrack) const {
+ if (!_cdrom)
+ return -1;
+
+ return _cdrom->getTrackPos(keyTrack);
+}
+
+const char *Sound::cdGetCurrentTrack() const {
+ if (!_cdrom)
+ return "";
+
+ return _cdrom->getCurTrack();
+}
+
+void Sound::cdTest(int trySubst, const char *label) {
+ if (!_cdrom)
+ return;
+
+ _cdrom->testCD(trySubst, label);
+}
+
+void Sound::bgPlay(const char *base, int count) {
+ if (!_bgatmos)
+ return;
+
+ debugC(1, kDebugSound, "BackgroundAtmosphere: Playing \"%s\" (%d)", base, count);
+
+ _bgatmos->stop();
+ _bgatmos->queueClear();
+
+ int length = strlen(base) + 7;
+ char *fileName = new char[length];
+ SoundDesc *sndDesc;
+
+ for (int i = 1; i <= count; i++) {
+ snprintf(fileName, length, "%s%02d.SND", base, i);
+
+ sndDesc = new SoundDesc;
+ if (sampleLoad(sndDesc, fileName))
+ _bgatmos->queueSample(*sndDesc);
+ }
+
+ _bgatmos->play();
+}
+
+void Sound::bgStop() {
+ if (!_bgatmos)
+ return;
+
+ debugC(1, kDebugSound, "BackgroundAtmosphere: Stopping playback");
+
+ _bgatmos->stop();
+ _bgatmos->queueClear();
+}
+
+void Sound::bgSetPlayMode(BackgroundAtmosphere::PlayMode mode) {
+ if (!_bgatmos)
+ return;
+
+ _bgatmos->setPlayMode(mode);
+}
+
+void Sound::bgShade() {
+ if (!_bgatmos)
+ return;
+
+ debugC(1, kDebugSound, "BackgroundAtmosphere: Shading playback");
+
+ _bgatmos->shade();
+}
+
+void Sound::bgUnshade() {
+ if (!_bgatmos)
+ return;
+
+ debugC(1, kDebugSound, "BackgroundAtmosphere: Unshading playback");
+
+ _bgatmos->unshade();
+}
+
+} // End of namespace Gob
diff --git a/engines/gob/sound/sound.h b/engines/gob/sound/sound.h
new file mode 100644
index 0000000000..b59510e4bb
--- /dev/null
+++ b/engines/gob/sound/sound.h
@@ -0,0 +1,147 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef GOB_SOUND_SOUND_H
+#define GOB_SOUND_SOUND_H
+
+#include "gob/sound/sounddesc.h"
+#include "gob/sound/pcspeaker.h"
+#include "gob/sound/soundblaster.h"
+#include "gob/sound/adlib.h"
+#include "gob/sound/infogrames.h"
+#include "gob/sound/cdrom.h"
+#include "gob/sound/bgatmosphere.h"
+
+namespace Gob {
+
+class Sound {
+public:
+ static const int kSoundsCount = 60;
+
+ Sound(GobEngine *vm);
+ ~Sound();
+
+ static void convToSigned(byte *buffer, int length);
+
+ // Samples
+ SoundDesc *sampleGetBySlot(int slot);
+ const SoundDesc *sampleGetBySlot(int slot) const;
+ int sampleGetNextFreeSlot() const;
+
+ bool sampleLoad(SoundDesc *sndDesc, const char *fileName, bool tryExist = true);
+ void sampleFree(SoundDesc *sndDesc, bool noteAdlib = false, int index = -1);
+
+
+ // SoundBlaster
+ void blasterPlay(SoundDesc *sndDesc, int16 repCount,
+ int16 frequency, int16 fadeLength = 0);
+ void blasterStop(int16 fadeLength, SoundDesc *sndDesc = 0);
+
+ void blasterPlayComposition(int16 *composition, int16 freqVal,
+ SoundDesc *sndDescs = 0, int8 sndCount = kSoundsCount);
+ void blasterStopComposition();
+
+ char blasterPlayingSound() const;
+
+ void blasterSetRepeating(int32 repCount);
+ void blasterWaitEndPlay(bool interruptible = false, bool stopComp = true);
+
+
+ // PCSpeaker
+ void speakerOn(int16 frequency, int32 length = -1);
+ void speakerOff();
+ void speakerOnUpdate(uint32 millis);
+
+
+ // AdLib
+ bool adlibLoad(const char *fileName);
+ bool adlibLoad(byte *data, uint32 size, int index = -1);
+ void adlibUnload();
+
+ void adlibPlayTrack(const char *trackname);
+ void adlibPlayBgMusic();
+
+ void adlibPlay();
+ void adlibStop();
+
+ bool adlibIsPlaying() const;
+
+ int adlibGetIndex() const;
+ bool adlibGetRepeating() const;
+
+ void adlibSetRepeating(int32 repCount);
+
+
+ // Infogrames
+ bool infogramesLoadInstruments(const char *fileName);
+ bool infogramesLoadSong(const char *fileName);
+
+ void infogramesPlay();
+ void infogramesStop();
+
+
+ // CD-ROM
+ void cdLoadLIC(const char *fname);
+ void cdUnloadLIC();
+
+ void cdPlayBgMusic();
+ void cdPlayMultMusic();
+
+ void cdPlay(const char *trackName);
+ void cdStop();
+
+ bool cdIsPlaying() const;
+
+ int32 cdGetTrackPos(const char *keyTrack = 0) const;
+ const char *cdGetCurrentTrack() const;
+
+ void cdTest(int trySubst, const char *label);
+
+
+ // Background Atmosphere
+ void bgPlay(const char *base, int count);
+ void bgStop();
+
+ void bgSetPlayMode(BackgroundAtmosphere::PlayMode mode);
+
+ void bgShade();
+ void bgUnshade();
+
+private:
+ GobEngine *_vm;
+
+ SoundDesc _sounds[kSoundsCount];
+
+ PCSpeaker *_pcspeaker;
+ SoundBlaster *_blaster;
+ AdLib *_adlib;
+ Infogrames *_infogrames;
+ CDROM *_cdrom;
+ BackgroundAtmosphere *_bgatmos;
+};
+
+} // End of namespace Gob
+
+#endif // GOB_SOUND_H
diff --git a/engines/gob/sound/soundblaster.cpp b/engines/gob/sound/soundblaster.cpp
new file mode 100644
index 0000000000..eeedfaa3cb
--- /dev/null
+++ b/engines/gob/sound/soundblaster.cpp
@@ -0,0 +1,126 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "gob/sound/soundblaster.h"
+
+namespace Gob {
+
+SoundBlaster::SoundBlaster(Audio::Mixer &mixer) : SoundMixer(mixer, Audio::Mixer::kSFXSoundType) {
+ _curSoundDesc = 0;
+
+ _compositionSamples = 0;
+ _compositionSampleCount = 0;
+ _compositionPos = -1;
+}
+
+SoundBlaster::~SoundBlaster() {
+}
+
+void SoundBlaster::playSample(SoundDesc &sndDesc, int16 repCount,
+ int16 frequency, int16 fadeLength) {
+ SoundMixer::play(sndDesc, repCount, frequency, fadeLength);
+}
+
+void SoundBlaster::stopSound(int16 fadeLength, SoundDesc *sndDesc) {
+ Common::StackLock slock(_mutex);
+
+ if (sndDesc && (sndDesc != _curSoundDesc))
+ return;
+
+ if (fadeLength <= 0)
+ _curSoundDesc = 0;
+
+ SoundMixer::stop(fadeLength);
+}
+
+void SoundBlaster::stopComposition() {
+ if (_compositionPos != -1) {
+ stopSound(0);
+ _compositionPos = -1;
+ }
+}
+
+void SoundBlaster::endComposition() {
+ _compositionPos = -1;
+}
+
+void SoundBlaster::nextCompositionPos() {
+ int8 slot;
+
+ while ((++_compositionPos < 50) &&
+ ((slot = _composition[_compositionPos]) != -1)) {
+ if ((slot >= 0) && (slot < _compositionSampleCount)) {
+ SoundDesc &sample = _compositionSamples[slot];
+ if (!sample.empty() && (sample.getType() == SOUND_SND)) {
+ setSample(sample, 1, 0, 0);
+ return;
+ }
+ }
+ if (_compositionPos == 49)
+ _compositionPos = -1;
+ }
+ _compositionPos = -1;
+}
+
+void SoundBlaster::playComposition(int16 *composition, int16 freqVal,
+ SoundDesc *sndDescs, int8 sndCount) {
+
+ _compositionSamples = sndDescs;
+ _compositionSampleCount = sndCount;
+
+ int i = -1;
+ do {
+ i++;
+ _composition[i] = composition[i];
+ } while ((i < 50) && (composition[i] != -1));
+
+ _compositionPos = -1;
+ nextCompositionPos();
+}
+
+void SoundBlaster::setSample(SoundDesc &sndDesc, int16 repCount, int16 frequency,
+ int16 fadeLength) {
+
+ _curSoundDesc = &sndDesc;
+ SoundMixer::setSample(sndDesc, repCount, frequency, fadeLength);
+}
+
+void SoundBlaster::checkEndSample() {
+ if (_compositionPos != -1)
+ nextCompositionPos();
+ else
+ SoundMixer::checkEndSample();
+}
+
+void SoundBlaster::endFade() {
+ if (_fadeVolStep > 0) {
+ _compositionPos = -1;
+ _curSoundDesc = 0;
+ }
+
+ SoundMixer::endFade();
+}
+
+} // End of namespace Gob
diff --git a/engines/gob/sound/soundblaster.h b/engines/gob/sound/soundblaster.h
new file mode 100644
index 0000000000..c57e4a443e
--- /dev/null
+++ b/engines/gob/sound/soundblaster.h
@@ -0,0 +1,71 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef GOB_SOUND_SOUNDBLASTER_H
+#define GOB_SOUND_SOUNDBLASTER_H
+
+#include "common/mutex.h"
+#include "sound/mixer.h"
+
+#include "gob/sound/sounddesc.h"
+#include "gob/sound/soundmixer.h"
+
+namespace Gob {
+
+class SoundBlaster : public SoundMixer {
+public:
+ SoundBlaster(Audio::Mixer &mixer);
+ ~SoundBlaster();
+
+ void playSample(SoundDesc &sndDesc, int16 repCount,
+ int16 frequency, int16 fadeLength = 0);
+ void stopSound(int16 fadeLength, SoundDesc *sndDesc = 0);
+
+ void playComposition(int16 *composition, int16 freqVal,
+ SoundDesc *sndDescs = 0, int8 sndCount = 60);
+ void stopComposition();
+ void endComposition();
+
+protected:
+ Common::Mutex _mutex;
+
+ SoundDesc *_compositionSamples;
+ int8 _compositionSampleCount;
+ int16 _composition[50];
+ int8 _compositionPos;
+
+ SoundDesc *_curSoundDesc;
+
+ void setSample(SoundDesc &sndDesc, int16 repCount,
+ int16 frequency, int16 fadeLength);
+ void checkEndSample();
+ void endFade();
+
+ void nextCompositionPos();
+};
+
+} // End of namespace Gob
+
+#endif // GOB_SOUND_SOUNDBLASTER_H
diff --git a/engines/gob/sound/sounddesc.cpp b/engines/gob/sound/sounddesc.cpp
new file mode 100644
index 0000000000..e0885d9faa
--- /dev/null
+++ b/engines/gob/sound/sounddesc.cpp
@@ -0,0 +1,116 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/util.h"
+
+#include "gob/sound/sounddesc.h"
+
+namespace Gob {
+
+SoundDesc::SoundDesc() {
+ _data = _dataPtr = 0;
+ _size = 0;
+
+ _type = SOUND_SND;
+ _source = SOUND_FILE;
+
+ _repCount = 0;
+ _frequency = 0;
+ _flag = 0;
+ _id = 0;
+}
+
+SoundDesc::~SoundDesc() {
+ free();
+}
+
+void SoundDesc::set(SoundType type, SoundSource src,
+ byte *data, uint32 dSize) {
+
+ free();
+
+ _type = type;
+ _source = src;
+ _data = _dataPtr = data;
+ _size = dSize;
+}
+
+void SoundDesc::load(SoundType type, SoundSource src,
+ byte *data, uint32 dSize) {
+
+ free();
+
+ _source = src;
+ switch (type) {
+ case SOUND_ADL:
+ loadADL(data, dSize);
+ break;
+ case SOUND_SND:
+ loadSND(data, dSize);
+ break;
+ }
+}
+
+void SoundDesc::free() {
+ if (_source != SOUND_TOT)
+ delete[] _data;
+ _data = _dataPtr = 0;
+ _id = 0;
+}
+
+void SoundDesc::convToSigned() {
+ if ((_type == SOUND_SND) && _data && _dataPtr)
+ for (uint32 i = 0; i < _size; i++)
+ _dataPtr[i] ^= 0x80;
+}
+
+int16 SoundDesc::calcFadeOutLength(int16 frequency) {
+ return (10 * (_size / 2)) / frequency;
+}
+
+uint32 SoundDesc::calcLength(int16 repCount, int16 frequency, bool fade) {
+ uint32 fadeSize = fade ? _size / 2 : 0;
+ return ((_size * repCount - fadeSize) * 1000) / frequency;
+}
+
+void SoundDesc::loadSND(byte *data, uint32 dSize) {
+ assert(dSize > 6);
+
+ _type = SOUND_SND;
+ _data = data;
+ _dataPtr = data + 6;
+ _frequency = MAX((int16) READ_BE_UINT16(data + 4), (int16) 4700);
+ _flag = data[0] ? (data[0] & 0x7F) : 8;
+ data[0] = 0;
+ _size = MIN(READ_BE_UINT32(data), dSize - 6);
+}
+
+void SoundDesc::loadADL(byte *data, uint32 dSize) {
+ _type = SOUND_ADL;
+ _data = _dataPtr = data;
+ _size = dSize;
+}
+
+} // End of namespace Gob
diff --git a/engines/gob/sound/sounddesc.h b/engines/gob/sound/sounddesc.h
new file mode 100644
index 0000000000..ed4447254c
--- /dev/null
+++ b/engines/gob/sound/sounddesc.h
@@ -0,0 +1,85 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef GOB_SOUND_SOUNDDESC_H
+#define GOB_SOUND_SOUNDDESC_H
+
+#include "common/endian.h"
+
+namespace Gob {
+
+enum SoundType {
+ SOUND_SND,
+ SOUND_ADL
+};
+
+enum SoundSource {
+ SOUND_FILE,
+ SOUND_TOT,
+ SOUND_EXT
+};
+
+class SoundDesc {
+public:
+ int16 _repCount;
+ int16 _frequency;
+ int16 _flag;
+ int16 _id;
+
+ byte *getData() { return _dataPtr; }
+
+ uint32 size() const { return _size; }
+ bool empty() const { return !_dataPtr; }
+ SoundType getType() const { return _type; }
+
+ bool isId(int16 id) const { return _dataPtr && (_id == id); }
+
+ void set(SoundType type, SoundSource src, byte *data, uint32 dSize);
+ void load(SoundType type, SoundSource src, byte *data, uint32 dSize);
+ void free();
+ void convToSigned();
+
+ // Which fade out length to use when the fade starts half-way through?
+ int16 calcFadeOutLength(int16 frequency);
+ uint32 calcLength(int16 repCount, int16 frequency, bool fade);
+
+ SoundDesc();
+ ~SoundDesc();
+
+private:
+ byte *_data;
+ byte *_dataPtr;
+ uint32 _size;
+
+ SoundType _type;
+ SoundSource _source;
+
+ void loadSND(byte *data, uint32 dSize);
+ void loadADL(byte *data, uint32 dSize);
+};
+
+} // End of namespace Gob
+
+#endif // GOB_SOUND_SOUNDDESC_H
diff --git a/engines/gob/sound/soundmixer.cpp b/engines/gob/sound/soundmixer.cpp
new file mode 100644
index 0000000000..1a287d782f
--- /dev/null
+++ b/engines/gob/sound/soundmixer.cpp
@@ -0,0 +1,204 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "gob/sound/soundmixer.h"
+
+namespace Gob {
+
+SoundMixer::SoundMixer(Audio::Mixer &mixer, Audio::Mixer::SoundType type) : _mixer(&mixer) {
+ _playingSound = 0;
+
+ _rate = _mixer->getOutputRate();
+ _end = true;
+ _data = 0;
+ _length = 0;
+ _freq = 0;
+ _repCount = 0;
+
+ _offset = 0;
+ _offsetFrac = 0;
+ _offsetInc = 0;
+
+ _cur = 0;
+ _last = 0;
+
+ _fade = false;
+ _fadeVol = 65536;
+ _fadeVolStep = 0;
+ _fadeSamples = 0;
+ _curFadeSamples = 0;
+
+ _mixer->playInputStream(type, &_handle, this, -1, 255, 0, false, true);
+}
+
+SoundMixer::~SoundMixer() {
+ _mixer->stopHandle(_handle);
+}
+
+bool SoundMixer::isPlaying() const {
+ return !_end;
+}
+
+char SoundMixer::getPlayingSound() const {
+ return _playingSound;
+}
+
+void SoundMixer::stop(int16 fadeLength) {
+ Common::StackLock slock(_mutex);
+
+ if (fadeLength <= 0) {
+ _data = 0;
+ _end = true;
+ _playingSound = 0;
+ return;
+ }
+
+ _fade = true;
+ _fadeVol = 65536;
+ _fadeSamples = (int) (fadeLength * (((double) _rate) / 10.0));
+ _fadeVolStep = MAX((int32) 1, (int32) (65536 / _fadeSamples));
+ _curFadeSamples = 0;
+}
+
+void SoundMixer::setRepeating(int32 repCount) {
+ Common::StackLock slock(_mutex);
+
+ _repCount = repCount;
+}
+
+void SoundMixer::setSample(SoundDesc &sndDesc, int16 repCount, int16 frequency,
+ int16 fadeLength) {
+
+ if (frequency <= 0)
+ frequency = sndDesc._frequency;
+
+ sndDesc._repCount = repCount - 1;
+ sndDesc._frequency = frequency;
+
+ _data = (int8 *) sndDesc.getData();
+ _length = sndDesc.size();
+ _freq = frequency;
+
+ _repCount = repCount;
+ _end = false;
+ _playingSound = 1;
+
+ _offset = 0;
+ _offsetFrac = 0;
+ _offsetInc = (_freq << FRAC_BITS) / _rate;
+
+ _last = _cur;
+ _cur = _data[0];
+
+ _curFadeSamples = 0;
+ if (fadeLength == 0) {
+ _fade = false;
+ _fadeVol = 65536;
+ _fadeSamples = 0;
+ _fadeVolStep = 0;
+ } else {
+ _fade = true;
+ _fadeVol = 0;
+ _fadeSamples = (int) (fadeLength * (((double) _rate) / 10.0));
+ _fadeVolStep = - MAX((int32) 1, (int32) (65536 / _fadeSamples));
+ }
+}
+
+void SoundMixer::play(SoundDesc &sndDesc, int16 repCount, int16 frequency,
+ int16 fadeLength) {
+ Common::StackLock slock(_mutex);
+
+ if (!_end)
+ return;
+
+ setSample(sndDesc, repCount, frequency, fadeLength);
+}
+
+void SoundMixer::checkEndSample() {
+ if ((_repCount == -1) || (--_repCount > 0)) {
+ _offset = 0;
+ _offsetFrac = 0;
+ _end = false;
+ _playingSound = 1;
+ } else {
+ _end = true;
+ _playingSound = 0;
+ }
+}
+
+int SoundMixer::readBuffer(int16 *buffer, const int numSamples) {
+ Common::StackLock slock(_mutex);
+
+ for (int i = 0; i < numSamples; i++) {
+ if (!_data)
+ return i;
+ if (_end || (_offset >= _length))
+ checkEndSample();
+ if (_end)
+ return i;
+
+ // Linear interpolation. See sound/rate.cpp
+
+ int16 val = (_last + (((_cur - _last) * _offsetFrac +
+ FRAC_HALF) >> FRAC_BITS)) << 8;
+ *buffer++ = (val * _fadeVol) >> 16;
+
+ _offsetFrac += _offsetInc;
+
+ // Was there an integral change?
+ if (fracToInt(_offsetFrac) > 0) {
+ _last = _cur;
+ _cur = _data[_offset];
+ _offset += fracToInt(_offsetFrac);
+ _offsetFrac &= FRAC_LO_MASK;
+ }
+
+ if (_fade) {
+
+ if (++_curFadeSamples >= _fadeSamples)
+ endFade();
+ else
+ _fadeVol -= _fadeVolStep;
+
+ if (_fadeVol < 0)
+ _fadeVol = 0;
+
+ }
+ }
+ return numSamples;
+}
+
+void SoundMixer::endFade() {
+ if (_fadeVolStep > 0) {
+ _data = 0;
+ _end = true;
+ _playingSound = 0;
+ } else {
+ _fadeVol = 65536;
+ _fade = false;
+ }
+}
+
+} // End of namespace Gob
diff --git a/engines/gob/sound/soundmixer.h b/engines/gob/sound/soundmixer.h
new file mode 100644
index 0000000000..5789885a99
--- /dev/null
+++ b/engines/gob/sound/soundmixer.h
@@ -0,0 +1,95 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef GOB_SOUND_SOUNDMIXER_H
+#define GOB_SOUND_SOUNDMIXER_H
+
+#include "common/mutex.h"
+#include "common/frac.h"
+#include "sound/audiostream.h"
+#include "sound/mixer.h"
+
+#include "gob/sound/sounddesc.h"
+
+namespace Gob {
+
+class SoundMixer : public Audio::AudioStream {
+public:
+ SoundMixer(Audio::Mixer &mixer, Audio::Mixer::SoundType type = Audio::Mixer::kPlainSoundType);
+ ~SoundMixer();
+
+ virtual void play(SoundDesc &sndDesc, int16 repCount,
+ int16 frequency, int16 fadeLength = 0);
+ virtual void stop(int16 fadeLength);
+
+ bool isPlaying() const;
+ char getPlayingSound() const;
+
+ void setRepeating(int32 repCount);
+
+ int readBuffer(int16 *buffer, const int numSamples);
+ bool isStereo() const { return false; }
+ bool endOfData() const { return _end; }
+ bool endOfStream() const { return false; }
+ int getRate() const { return _rate; }
+
+protected:
+ Audio::Mixer *_mixer;
+
+ Audio::SoundHandle _handle;
+ Common::Mutex _mutex;
+
+ bool _end;
+ int8 *_data;
+ uint32 _length;
+ uint32 _rate;
+ int32 _freq;
+ int32 _repCount;
+
+ uint32 _offset;
+ frac_t _offsetFrac;
+ frac_t _offsetInc;
+
+ int16 _cur;
+ int16 _last;
+
+ bool _fade;
+ int32 _fadeVol;
+ int32 _fadeVolStep;
+ uint8 _fadeLength;
+ uint32 _fadeSamples;
+ uint32 _curFadeSamples;
+
+ char _playingSound;
+
+ virtual void setSample(SoundDesc &sndDesc, int16 repCount,
+ int16 frequency, int16 fadeLength);
+ virtual void checkEndSample();
+ virtual void endFade();
+};
+
+} // End of namespace Gob
+
+#endif // GOB_SOUND_SOUNDMIXER_H
diff --git a/engines/gob/util.cpp b/engines/gob/util.cpp
index 8e573ddb1a..4987426fe0 100644
--- a/engines/gob/util.cpp
+++ b/engines/gob/util.cpp
@@ -23,7 +23,6 @@
*
*/
-
#include "common/events.h"
#include "gob/gob.h"
@@ -32,8 +31,8 @@
#include "gob/dataio.h"
#include "gob/draw.h"
#include "gob/game.h"
-#include "gob/sound.h"
#include "gob/video.h"
+#include "gob/sound/sound.h"
namespace Gob {
@@ -60,7 +59,7 @@ void Util::beep(int16 freq) {
if (_vm->_global->_soundFlags == 0)
return;
- _vm->_snd->speakerOn(freq, 50);
+ _vm->_sound->speakerOn(freq, 50);
}
void Util::delay(uint16 msecs) {
diff --git a/engines/gob/variables.cpp b/engines/gob/variables.cpp
new file mode 100644
index 0000000000..0eea2f6547
--- /dev/null
+++ b/engines/gob/variables.cpp
@@ -0,0 +1,311 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/endian.h"
+
+#include "gob/gob.h"
+#include "gob/variables.h"
+
+namespace Gob {
+
+Variables::Variables(uint32 size) {
+ _size = size;
+
+ _vars = new byte[_size];
+ _sizes = new byte[_size];
+
+ clear();
+}
+
+Variables::~Variables() {
+ delete[] _vars;
+ delete[] _sizes;
+}
+
+void Variables::clear() {
+ memset(_vars, 0, _size);
+
+ // All variables are 32 bit wide per default
+ memset(_sizes, 0, _size);
+ for (uint32 i = 0; i < _size; i += 4)
+ _sizes[i] = kSize32;
+}
+
+void Variables::clearSize(uint32 offset) {
+ uint32 inVar = offset % 4;
+ uint32 varOff = (offset >> 2) << 2;
+
+ // Clearing out the old size
+ for (uint32 i = 0; i < 4; i++) {
+ if (_sizes[varOff + i] == kSize32)
+ _sizes[varOff + i] = kSize8;
+ else if ((inVar == (i + 1)) && (_sizes[varOff + i] == kSize16))
+ _sizes[varOff + i] = kSize8;
+ }
+}
+
+void Variables::writeSize(uint32 offset, byte n) {
+ clearSize(offset);
+
+ _sizes[offset] = n;
+ // Setting following bytes of size to 8 bit, for easy clearing out afterwards
+ for (; n > 0; n--)
+ _sizes[offset + n] = kSize8;
+}
+
+void Variables::writeSizeString(uint32 offset, uint32 length) {
+ clearSize(offset);
+
+ memset(_sizes + offset, kSize8, length);
+}
+
+void Variables::writeVar8(uint32 var, uint8 value) {
+ writeOff8(var * 4, value);
+}
+
+void Variables::writeVar16(uint32 var, uint16 value) {
+ writeOff16(var * 4, value);
+}
+
+void Variables::writeVar32(uint32 var, uint32 value) {
+ writeOff32(var * 4, value);
+}
+
+void Variables::writeVarString(uint32 var, const char *value) {
+ writeOffString(var * 4, value);
+}
+
+void Variables::writeOff8(uint32 offset, uint8 value) {
+ write8(_vars + offset, value);
+ writeSize(offset, kSize8);
+}
+
+void Variables::writeOff16(uint32 offset, uint16 value) {
+ write16(_vars + offset, value);
+ writeSize(offset, kSize16);
+}
+
+void Variables::writeOff32(uint32 offset, uint32 value) {
+ write32(_vars + offset, value);
+ writeSize(offset, kSize32);
+}
+
+void Variables::writeOffString(uint32 offset, const char *value) {
+ strcpy((char *) (_vars + offset), value);
+ writeSizeString(offset, strlen(value));
+}
+
+uint8 Variables::readVar8(uint32 var) const {
+ return readOff8(var * 4);
+}
+
+uint16 Variables::readVar16(uint32 var) const {
+ return readOff16(var * 4);
+}
+
+uint32 Variables::readVar32(uint32 var) const {
+ return readOff32(var * 4);
+}
+
+void Variables::readVarString(uint32 var, char *value, uint32 length) {
+ readOffString(var * 4, value, length);
+}
+
+uint8 Variables::readOff8(uint32 offset) const {
+ return read8(_vars + offset);
+}
+
+uint16 Variables::readOff16(uint32 offset) const {
+ return read16(_vars + offset);
+}
+
+uint32 Variables::readOff32(uint32 offset) const {
+ return read32(_vars + offset);
+}
+
+void Variables::readOffString(uint32 offset, char *value, uint32 length) {
+ strncpy0(value, (const char *) (_vars + offset), length - 1);
+}
+
+const uint8 *Variables::getAddressVar8(uint32 var) const {
+ return getAddressOff8(var * 4);
+}
+
+uint8 *Variables::getAddressVar8(uint32 var, uint32 n) {
+ return getAddressOff8(var * 4, n);
+}
+
+const uint16 *Variables::getAddressVar16(uint32 var) const {
+ return getAddressOff16(var * 4);
+}
+
+uint16 *Variables::getAddressVar16(uint32 var, uint32 n) {
+ return getAddressOff16(var * 4, n);
+}
+
+const uint32 *Variables::getAddressVar32(uint32 var) const {
+ return getAddressOff32(var * 4);
+}
+
+uint32 *Variables::getAddressVar32(uint32 var, uint32 n) {
+ return getAddressOff32(var * 4, n);
+}
+
+const char *Variables::getAddressVarString(uint32 var) const {
+ return getAddressOffString(var * 4);
+}
+
+char *Variables::getAddressVarString(uint32 var, uint32 n) {
+ return getAddressOffString(var * 4, n);
+}
+
+const uint8 *Variables::getAddressOff8(uint32 offset) const {
+ return ((const uint8 *) (_vars + offset));
+}
+
+uint8 *Variables::getAddressOff8(uint32 offset, uint32 n) {
+ for (uint32 i = 0; i < n; i++)
+ writeSize(offset + i, kSize8);
+
+ return ((uint8 *) (_vars + offset));
+}
+
+const uint16 *Variables::getAddressOff16(uint32 offset) const {
+ return ((const uint16 *) (_vars + offset));
+}
+
+uint16 *Variables::getAddressOff16(uint32 offset, uint32 n) {
+ for (uint32 i = 0; i < n; i++)
+ writeSize(offset + i * 2, kSize16);
+
+ return ((uint16 *) (_vars + offset));
+}
+
+const uint32 *Variables::getAddressOff32(uint32 offset) const {
+ return ((const uint32 *) (_vars + offset));
+}
+
+uint32 *Variables::getAddressOff32(uint32 offset, uint32 n) {
+ for (uint32 i = 0; i < n; i++)
+ writeSize(offset + i * 4, kSize32);
+
+ return ((uint32 *) (_vars + offset));
+}
+
+const char *Variables::getAddressOffString(uint32 offset) const {
+ return ((const char *) (_vars + offset));
+}
+
+char *Variables::getAddressOffString(uint32 offset, uint32 n) {
+ writeSizeString(offset, (n == 0xFFFFFFFF) ? strlen((char *) (_vars + offset)) : n);
+
+ return ((char *) (_vars + offset));
+}
+
+bool Variables::copyTo(uint32 offset, byte *variables, byte *sizes, uint32 n) const {
+ if ((offset + n) > _size)
+ return false;
+
+ if (variables)
+ memcpy(variables, _vars + offset, n);
+ if (sizes)
+ memcpy(sizes, _sizes + offset, n);
+
+ return true;
+}
+
+bool Variables::copyFrom(uint32 offset, const byte *variables, const byte *sizes, uint32 n) {
+ if (((offset + n) > _size) || !variables || !sizes)
+ return false;
+
+ memcpy(_vars + offset, variables, n);
+ memcpy(_sizes + offset, sizes, n);
+
+ return true;
+}
+
+
+VariablesLE::VariablesLE(uint32 size) : Variables(size) {
+}
+
+VariablesLE::~VariablesLE() {
+}
+
+void VariablesLE::write8(byte *buf, uint8 data) const {
+ *buf = (byte) data;
+}
+
+void VariablesLE::write16(byte *buf, uint16 data) const {
+ WRITE_LE_UINT16(buf, data);
+}
+
+void VariablesLE::write32(byte *buf, uint32 data) const {
+ WRITE_LE_UINT32(buf, data);
+}
+
+uint8 VariablesLE::read8(const byte *buf) const {
+ return (uint8) *buf;
+}
+
+uint16 VariablesLE::read16(const byte *buf) const {
+ return READ_LE_UINT16(buf);
+}
+
+uint32 VariablesLE::read32(const byte *buf) const {
+ return READ_LE_UINT32(buf);
+}
+
+
+VariablesBE::VariablesBE(uint32 size) : Variables(size) {
+}
+
+VariablesBE::~VariablesBE() {
+}
+
+void VariablesBE::write8(byte *buf, uint8 data) const {
+ *buf = (byte) data;
+}
+
+void VariablesBE::write16(byte *buf, uint16 data) const {
+ WRITE_BE_UINT16(buf, data);
+}
+
+void VariablesBE::write32(byte *buf, uint32 data) const {
+ WRITE_BE_UINT32(buf, data);
+}
+
+uint8 VariablesBE::read8(const byte *buf) const {
+ return (uint8) *buf;
+}
+
+uint16 VariablesBE::read16(const byte *buf) const {
+ return READ_BE_UINT16(buf);
+}
+
+uint32 VariablesBE::read32(const byte *buf) const {
+ return READ_BE_UINT32(buf);
+}
+
+} // End of namespace Gob
diff --git a/engines/gob/variables.h b/engines/gob/variables.h
new file mode 100644
index 0000000000..5989ed38ee
--- /dev/null
+++ b/engines/gob/variables.h
@@ -0,0 +1,147 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef GOB_VARIABLES_H
+#define GOB_VARIABLES_H
+
+namespace Gob {
+
+class Variables {
+public:
+ Variables(uint32 size);
+ virtual ~Variables();
+
+ void writeVar8(uint32 var, uint8 value);
+ void writeVar16(uint32 var, uint16 value);
+ void writeVar32(uint32 var, uint32 value);
+
+ void writeVarString(uint32 var, const char *value);
+
+ void writeOff8(uint32 offset, uint8 value);
+ void writeOff16(uint32 offset, uint16 value);
+ void writeOff32(uint32 offset, uint32 value);
+
+ void writeOffString(uint32 offset, const char *value);
+
+ uint8 readVar8(uint32 var) const;
+ uint16 readVar16(uint32 var) const;
+ uint32 readVar32(uint32 var) const;
+
+ void readVarString(uint32 var, char *value, uint32 length);
+
+ uint8 readOff8(uint32 offset) const;
+ uint16 readOff16(uint32 offset) const;
+ uint32 readOff32(uint32 offset) const;
+
+ void readOffString(uint32 offset, char *value, uint32 length);
+
+
+ const uint8 *getAddressVar8(uint32 var) const;
+ uint8 *getAddressVar8(uint32 var, uint32 n = 1);
+
+ const uint16 *getAddressVar16(uint32 var) const;
+ uint16 *getAddressVar16(uint32 var, uint32 n = 1);
+
+ const uint32 *getAddressVar32(uint32 var) const;
+ uint32 *getAddressVar32(uint32 var, uint32 n = 1);
+
+ const char *getAddressVarString(uint32 var) const;
+ char *getAddressVarString(uint32 var, uint32 n = 0xFFFFFFFF);
+
+ const uint8 *getAddressOff8(uint32 offset) const;
+ uint8 *getAddressOff8(uint32 offset, uint32 n = 1);
+
+ const uint16 *getAddressOff16(uint32 offset) const;
+ uint16 *getAddressOff16(uint32 offset, uint32 n = 1);
+
+ const uint32 *getAddressOff32(uint32 offset) const;
+ uint32 *getAddressOff32(uint32 offset, uint32 n = 1);
+
+ const char *getAddressOffString(uint32 offset) const;
+ char *getAddressOffString(uint32 offset, uint32 n = 0xFFFFFFFF);
+
+
+ bool copyTo(uint32 offset, byte *variables, byte *sizes, uint32 n) const;
+ bool copyFrom(uint32 offset, const byte *variables, const byte *sizes, uint32 n);
+
+protected:
+ virtual void write8(byte *buf, uint8 data) const = 0;
+ virtual void write16(byte *buf, uint16 data) const = 0;
+ virtual void write32(byte *buf, uint32 data) const = 0;
+
+ virtual uint8 read8(const byte *buf) const = 0;
+ virtual uint16 read16(const byte *buf) const = 0;
+ virtual uint32 read32(const byte *buf) const = 0;
+
+private:
+ // Basically the number of additional bytes occupied
+ static const byte kSize8 = 0;
+ static const byte kSize16 = 1;
+ static const byte kSize32 = 3;
+
+ uint32 _size;
+
+ byte *_vars;
+ byte *_sizes;
+
+ void clear();
+ void clearSize(uint32 offset);
+ void writeSize(uint32 offset, byte n);
+ void writeSizeString(uint32 offset, uint32 length);
+};
+
+class VariablesLE : public Variables {
+public:
+ VariablesLE(uint32 size);
+ ~VariablesLE();
+
+protected:
+ void write8(byte *buf, uint8 data) const;
+ void write16(byte *buf, uint16 data) const;
+ void write32(byte *buf, uint32 data) const;
+
+ uint8 read8(const byte *buf) const;
+ uint16 read16(const byte *buf) const;
+ uint32 read32(const byte *buf) const;
+};
+
+class VariablesBE : public Variables {
+public:
+ VariablesBE(uint32 size);
+ ~VariablesBE();
+
+protected:
+ void write8(byte *buf, uint8 data) const;
+ void write16(byte *buf, uint16 data) const;
+ void write32(byte *buf, uint32 data) const;
+
+ uint8 read8(const byte *buf) const;
+ uint16 read16(const byte *buf) const;
+ uint32 read32(const byte *buf) const;
+};
+
+} // End of namespace Gob
+
+#endif // GOB_VARIABLES_H
diff --git a/engines/gob/video.cpp b/engines/gob/video.cpp
index 9a004318b8..453613d1ae 100644
--- a/engines/gob/video.cpp
+++ b/engines/gob/video.cpp
@@ -23,7 +23,6 @@
*
*/
-
#include "common/endian.h"
#include "graphics/cursorman.h"
@@ -87,10 +86,14 @@ void SurfaceDesc::swap(SurfaceDesc &surf) {
Video::Video(GobEngine *vm) : _vm(vm) {
_doRangeClamp = false;
_videoDriver = 0;
+
_surfWidth = 320;
_surfHeight = 200;
+
_scrollOffsetX = 0;
_scrollOffsetY = 0;
+
+ _splitSurf = 0;
_splitHeight1 = 200;
_splitHeight2 = 0;
_splitStart = 0;
@@ -179,21 +182,34 @@ void Video::retrace(bool mouse) {
int screenOffset = _scrollOffsetY * _surfWidth + _scrollOffsetX;
int screenX = _screenDeltaX;
int screenY = _screenDeltaY;
- int screenWidth = _vm->_width;
- int screenHeight = _splitHeight1;
+ int screenWidth = MIN<int>(_surfWidth - _scrollOffsetX, _vm->_width);
+ int screenHeight = MIN<int>(_surfHeight - _splitHeight2 - _scrollOffsetY, _vm->_height);
g_system->copyRectToScreen(_vm->_global->_primarySurfDesc->getVidMem() + screenOffset,
_surfWidth, screenX, screenY, screenWidth, screenHeight);
- if (_splitHeight2 > 0) {
+ if (_splitSurf) {
+
+ screenOffset = 0;
+ screenX = 0;
+ screenY = _vm->_height - _splitSurf->getHeight();
+ screenWidth = MIN<int>(_vm->_width, _splitSurf->getWidth());
+ screenHeight = _splitSurf->getHeight();
+
+ g_system->copyRectToScreen(_splitSurf->getVidMem() + screenOffset,
+ _splitSurf->getWidth(), screenX, screenY, screenWidth, screenHeight);
+
+ } else if (_splitHeight2 > 0) {
+
screenOffset = _splitStart * _surfWidth;
screenX = 0;
screenY = _vm->_height - _splitHeight2;
- screenWidth = _vm->_width;
+ screenWidth = MIN<int>(_surfWidth, _vm->_width);
screenHeight = _splitHeight2;
g_system->copyRectToScreen(_vm->_global->_primarySurfDesc->getVidMem() + screenOffset,
_surfWidth, screenX, screenY, screenWidth, screenHeight);
+
}
g_system->updateScreen();
diff --git a/engines/gob/video.h b/engines/gob/video.h
index 4a585d8857..1338885588 100644
--- a/engines/gob/video.h
+++ b/engines/gob/video.h
@@ -37,10 +37,11 @@ class SurfaceDesc : public ReferenceCounter<SurfaceDesc> {
public:
int16 _vidMode;
- int16 getWidth() { return _width; }
- int16 getHeight() { return _height; }
+ int16 getWidth() const { return _width; }
+ int16 getHeight() const { return _height; }
byte *getVidMem() { return _vidMem; }
- bool hasOwnVidMem() { return _ownVidMem; }
+ const byte *getVidMem() const { return _vidMem; }
+ bool hasOwnVidMem() const { return _ownVidMem; }
void setVidMem(byte *vidMem);
void resize(int16 width, int16 height);
@@ -97,13 +98,18 @@ public:
};
bool _doRangeClamp;
+
int16 _surfWidth;
int16 _surfHeight;
+
int16 _scrollOffsetX;
int16 _scrollOffsetY;
+
+ SurfaceDesc::Ptr _splitSurf;
int16 _splitHeight1;
int16 _splitHeight2;
int16 _splitStart;
+
int16 _screenDeltaX;
int16 _screenDeltaY;
diff --git a/engines/gob/video_v1.cpp b/engines/gob/video_v1.cpp
index 4ed3b04bad..3c9627c041 100644
--- a/engines/gob/video_v1.cpp
+++ b/engines/gob/video_v1.cpp
@@ -23,7 +23,6 @@
*
*/
-
#include "common/endian.h"
#include "gob/gob.h"
diff --git a/engines/gob/video_v2.cpp b/engines/gob/video_v2.cpp
index 52b349ca67..ab0c7e52db 100644
--- a/engines/gob/video_v2.cpp
+++ b/engines/gob/video_v2.cpp
@@ -23,7 +23,6 @@
*
*/
-
#include "common/endian.h"
#include "gob/gob.h"
diff --git a/engines/gob/videoplayer.cpp b/engines/gob/videoplayer.cpp
index e088646498..909d39a63b 100644
--- a/engines/gob/videoplayer.cpp
+++ b/engines/gob/videoplayer.cpp
@@ -33,6 +33,7 @@
#include "gob/palanim.h"
#include "gob/inter.h"
#include "gob/map.h"
+#include "gob/sound/sound.h"
namespace Gob {
@@ -289,6 +290,8 @@ void VideoPlayer::primaryPlay(int16 startFrame, int16 lastFrame, int16 breakKey,
if (doPlay(startFrame, breakKey, palCmd, palStart, palEnd, palFrame, endFrame))
break;
+ evalBgShading(video);
+
if (fade) {
_vm->_palAnim->fade(_vm->_global->_pPaletteDesc, -2, 0);
fade = false;
@@ -299,18 +302,27 @@ void VideoPlayer::primaryPlay(int16 startFrame, int16 lastFrame, int16 breakKey,
startFrame++;
}
+ evalBgShading(video);
+
if (reverseTo >= 0) {
int16 toFrame = video.getFramesCount() - reverseTo;
for (int i = video.getCurrentFrame(); i >= toFrame; i--) {
video.seekFrame(i, SEEK_SET, true);
- if (doPlay(i, breakKey, 0, 0, 0, 0, 0)) {
+
+ bool b = doPlay(i, breakKey, 0, 0, 0, 0, 0);
+ evalBgShading(video);
+
+ if (b) {
_vm->_palAnim->fade(0, -2, 0);
memset((char *) _vm->_draw->_vgaPalette, 0, 768);
}
+
if (!_noCursorSwitch)
video.waitEndFrame();
}
}
+
+ evalBgShading(video);
}
void VideoPlayer::primaryClose() {
@@ -334,17 +346,32 @@ int VideoPlayer::slotOpen(const char *videoFile, Type which) {
}
video->getVideo()->setVideoMemory();
- video->getVideo()->disableSound();
+ video->getVideo()->enableSound(*_vm->_mixer);
+
+ int slot = getNextFreeSlot();
- _videoSlots.push_back(video);
+ _videoSlots[slot] = video;
WRITE_VAR(7, video->getVideo()->getFramesCount());
- return _videoSlots.size() - 1;
+ return slot;
+}
+
+int VideoPlayer::getNextFreeSlot() {
+ uint slot;
+
+ for (slot = 0; slot < _videoSlots.size(); slot++)
+ if (!_videoSlots[slot])
+ break;
+
+ if (slot == _videoSlots.size())
+ _videoSlots.push_back(0);
+
+ return slot;
}
void VideoPlayer::slotPlay(int slot, int16 frame) {
- if ((slot < 0) || (((uint) slot) >= _videoSlots.size()))
+ if ((slot < 0) || (((uint) slot) >= _videoSlots.size()) || !_videoSlots[slot])
return;
CoktelVideo &video = *(_videoSlots[slot]->getVideo());
@@ -360,21 +387,23 @@ void VideoPlayer::slotPlay(int slot, int16 frame) {
_videoSlots[slot]->nextFrame();
WRITE_VAR(11, frame);
+
+ evalBgShading(video);
}
void VideoPlayer::slotClose(int slot) {
- if ((slot < 0) || (((uint) slot) >= _videoSlots.size()))
+ if ((slot < 0) || (((uint) slot) >= _videoSlots.size()) || !_videoSlots[slot])
return;
delete _videoSlots[slot];
- _videoSlots.remove_at(slot);
+ _videoSlots[slot] = 0;
}
void VideoPlayer::slotCopyFrame(int slot, byte *dest,
uint16 left, uint16 top, uint16 width, uint16 height,
uint16 x, uint16 y, uint16 pitch, int16 transp) {
- if ((slot < 0) || (((uint) slot) >= _videoSlots.size()))
+ if ((slot < 0) || (((uint) slot) >= _videoSlots.size()) || !_videoSlots[slot])
return;
_videoSlots[slot]->getVideo()->copyCurrentFrame(dest,
@@ -382,14 +411,24 @@ void VideoPlayer::slotCopyFrame(int slot, byte *dest,
}
void VideoPlayer::slotCopyPalette(int slot, int16 palStart, int16 palEnd) {
- if ((slot < 0) || (((uint) slot) >= _videoSlots.size()))
+ if ((slot < 0) || (((uint) slot) >= _videoSlots.size()) || !_videoSlots[slot])
return;
copyPalette(*(_videoSlots[slot]->getVideo()), palStart, palEnd);
}
+void VideoPlayer::slotWaitEndFrame(int slot, bool onlySound) {
+ if ((slot < 0) || (((uint) slot) >= _videoSlots.size()) || !_videoSlots[slot])
+ return;
+
+ CoktelVideo &video = *(_videoSlots[slot]->getVideo());
+
+ if (!onlySound || (video.getFeatures() & CoktelVideo::kFeaturesSound))
+ video.waitEndFrame();
+}
+
bool VideoPlayer::slotIsOpen(int slot) const {
- if ((slot >= 0) && (((uint) slot) < _videoSlots.size()))
+ if ((slot >= 0) && (((uint) slot) < _videoSlots.size()) && _videoSlots[slot])
return true;
return false;
@@ -399,7 +438,7 @@ const VideoPlayer::Video *VideoPlayer::getVideoBySlot(int slot) const {
if (slot < 0) {
if (_primaryVideo->isOpen())
return _primaryVideo;
- } else if (((uint) slot) < _videoSlots.size())
+ } else if (((uint) slot) < _videoSlots.size() && _videoSlots[slot])
return _videoSlots[slot];
return 0;
@@ -503,7 +542,7 @@ bool VideoPlayer::doPlay(int16 frame, int16 breakKey,
_vm->_draw->_noInvalidated = true;
}
- if (state.flags & CoktelVideo::kStatePalette) {
+ if ((state.flags & CoktelVideo::kStatePalette) && (palCmd > 1)) {
copyPalette(*(_primaryVideo->getVideo()), palStart, palEnd);
if (!_backSurf)
@@ -563,14 +602,13 @@ void VideoPlayer::writeVideoInfo(const char *videoFile, int16 varX, int16 varY,
if (primaryOpen(videoFile)) {
int16 x, y, width, height;
- if ((VAR_OFFSET(varX) != 0xFFFFFFFF) ||
- !_primaryVideo->getVideo()->getAnchor(1, 2, x, y, width, height)) {
+ x = _primaryVideo->getVideo()->getX();
+ y = _primaryVideo->getVideo()->getY();
+ width = _primaryVideo->getVideo()->getWidth();
+ height = _primaryVideo->getVideo()->getHeight();
- x = _primaryVideo->getVideo()->getX();
- y = _primaryVideo->getVideo()->getY();
- width = _primaryVideo->getVideo()->getWidth();
- height = _primaryVideo->getVideo()->getHeight();
- }
+ if (VAR_OFFSET(varX) == 0xFFFFFFFF)
+ _primaryVideo->getVideo()->getAnchor(1, 2, x, y, width, height);
WRITE_VAR_OFFSET(varX, x);
WRITE_VAR_OFFSET(varY, y);
@@ -580,12 +618,28 @@ void VideoPlayer::writeVideoInfo(const char *videoFile, int16 varX, int16 varY,
primaryClose();
} else {
- WRITE_VAR_OFFSET(varX, -1);
- WRITE_VAR_OFFSET(varY, -1);
- WRITE_VAR_OFFSET(varFrames, -1);
- WRITE_VAR_OFFSET(varWidth, -1);
- WRITE_VAR_OFFSET(varHeight, -1);
+ WRITE_VAR_OFFSET(varX, (uint32) -1);
+ WRITE_VAR_OFFSET(varY, (uint32) -1);
+ WRITE_VAR_OFFSET(varFrames, (uint32) -1);
+ WRITE_VAR_OFFSET(varWidth, (uint32) -1);
+ WRITE_VAR_OFFSET(varHeight, (uint32) -1);
}
}
+void VideoPlayer::evalBgShading(CoktelVideo &video) {
+ if (video.isSoundPlaying())
+ _vm->_sound->bgShade();
+ else
+ _vm->_sound->bgUnshade();
+}
+
+void VideoPlayer::notifyPaused(uint32 duration) {
+ if (_primaryVideo->isOpen())
+ _primaryVideo->getVideo()->notifyPaused(duration);
+
+ for (uint i = 0; i < _videoSlots.size(); i++)
+ if (_videoSlots[i] && _videoSlots[i]->isOpen())
+ _videoSlots[i]->getVideo()->notifyPaused(duration);
+}
+
} // End of namespace Gob
diff --git a/engines/gob/videoplayer.h b/engines/gob/videoplayer.h
index fd3c68aa1a..b7aa7313b0 100644
--- a/engines/gob/videoplayer.h
+++ b/engines/gob/videoplayer.h
@@ -68,6 +68,7 @@ public:
uint16 left, uint16 top, uint16 width, uint16 height,
uint16 x, uint16 y, uint16 pitch, int16 transp = -1);
void slotCopyPalette(int slot, int16 palStart = -1, int16 palEnd = -1);
+ void slotWaitEndFrame(int slot, bool onlySound = false);
bool slotIsOpen(int slot) const;
@@ -82,6 +83,8 @@ public:
void writeVideoInfo(const char *videoFile, int16 varX, int16 varY,
int16 varFrames, int16 varWidth, int16 varHeight);
+ void notifyPaused(uint32 duration);
+
private:
class Video {
public:
@@ -127,10 +130,13 @@ private:
const Video *getVideoBySlot(int slot = -1) const;
+ int getNextFreeSlot();
+
void copyPalette(CoktelVideo &video, int16 palStart = -1, int16 palEnd = -1);
bool doPlay(int16 frame, int16 breakKey,
uint16 palCmd, int16 palStart, int16 palEnd,
int16 palFrame, int16 endFrame);
+ void evalBgShading(CoktelVideo &video);
};
} // End of namespace Gob