aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaweł Kołodziejski2002-08-24 15:31:37 +0000
committerPaweł Kołodziejski2002-08-24 15:31:37 +0000
commit9f993a1d29120120b3d9c08d56ca1990f4222ae5 (patch)
tree751e3cfdc133f1abf27d6ff35b9b6a2c329bf3a0
parentfa181fcd8b6956821f4f8585f3124e9cf0214303 (diff)
downloadscummvm-rg350-9f993a1d29120120b3d9c08d56ca1990f4222ae5.tar.gz
scummvm-rg350-9f993a1d29120120b3d9c08d56ca1990f4222ae5.tar.bz2
scummvm-rg350-9f993a1d29120120b3d9c08d56ca1990f4222ae5.zip
synced with scummvm
svn-id: r4821
-rw-r--r--gui/dialog.cpp4
-rw-r--r--gui/gui.cpp4
-rw-r--r--scumm/imuse.cpp2
-rw-r--r--scumm/insane.cpp4
-rw-r--r--scumm/saveload.cpp2
-rw-r--r--scumm/script_v2.cpp18
-rw-r--r--scumm/smush/blitter.cpp221
-rw-r--r--scumm/smush/blitter.h79
-rw-r--r--scumm/smush/brenderer.cpp75
-rw-r--r--scumm/smush/brenderer.h86
-rw-r--r--scumm/smush/channel.h157
-rw-r--r--scumm/smush/chunck.cpp288
-rw-r--r--scumm/smush/chunck.h121
-rw-r--r--scumm/smush/chunck_type.h57
-rw-r--r--scumm/smush/codec1.cpp76
-rw-r--r--scumm/smush/codec1.h48
-rw-r--r--scumm/smush/codec37.cpp436
-rw-r--r--scumm/smush/codec37.h86
-rw-r--r--scumm/smush/codec44.cpp71
-rw-r--r--scumm/smush/codec44.h47
-rw-r--r--scumm/smush/codec47.cpp51
-rw-r--r--scumm/smush/codec47.h38
-rw-r--r--scumm/smush/color.cpp69
-rw-r--r--scumm/smush/color.h57
-rw-r--r--scumm/smush/config.h42
-rw-r--r--scumm/smush/decoder.h51
-rw-r--r--scumm/smush/frenderer.cpp232
-rw-r--r--scumm/smush/frenderer.h164
-rw-r--r--scumm/smush/imuse_channel.cpp329
-rw-r--r--scumm/smush/mixer.h58
-rw-r--r--scumm/smush/palette.cpp56
-rw-r--r--scumm/smush/palette.h45
-rw-r--r--scumm/smush/player.cpp760
-rw-r--r--scumm/smush/player.h104
-rw-r--r--scumm/smush/rect.cpp62
-rw-r--r--scumm/smush/rect.h101
-rw-r--r--scumm/smush/renderer.h123
-rw-r--r--scumm/smush/saud_channel.cpp274
-rw-r--r--scumm/smush/scumm_renderer.cpp266
-rw-r--r--scumm/smush/scumm_renderer.h66
-rw-r--r--simon/simon.cpp25
-rw-r--r--simon/vga.cpp2
-rw-r--r--sound/mididrv.cpp2
-rw-r--r--sound/mixer.cpp449
-rw-r--r--sound/mixer.h140
-rw-r--r--sound/sound.cpp40
46 files changed, 5117 insertions, 371 deletions
diff --git a/gui/dialog.cpp b/gui/dialog.cpp
index 59355cc031..13651a1a80 100644
--- a/gui/dialog.cpp
+++ b/gui/dialog.cpp
@@ -489,8 +489,8 @@ void SoundDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data)
scumm->_imuse->set_music_volume(_soundVolumeMusic);
scumm->_imuse->set_master_volume(_soundVolumeMaster);
- scumm->_mixer->set_volume(_soundVolumeSfx);
- scumm->_mixer->set_music_volume(_soundVolumeMusic);
+ scumm->_mixer->setVolume(_soundVolumeSfx);
+ scumm->_mixer->setMusicVolume(_soundVolumeMusic);
scummcfg->set("master_volume", _soundVolumeMaster);
scummcfg->set("music_volume", _soundVolumeMusic);
diff --git a/gui/gui.cpp b/gui/gui.cpp
index 270641ae17..8b2515e4b5 100644
--- a/gui/gui.cpp
+++ b/gui/gui.cpp
@@ -621,8 +621,8 @@ void Gui::handleSoundDialogCommand(int cmd)
_s->_imuse->set_music_volume(_s->_sound->_sound_volume_music);
_s->_imuse->set_master_volume(_s->_sound->_sound_volume_master);
- _s->_mixer->set_volume(_s->_sound->_sound_volume_sfx);
- _s->_mixer->set_music_volume(_s->_sound->_sound_volume_music);
+ _s->_mixer->setVolume(_s->_sound->_sound_volume_sfx);
+ _s->_mixer->setMusicVolume(_s->_sound->_sound_volume_music);
scummcfg->set("master_volume", _s->_sound->_sound_volume_master);
scummcfg->set("music_volume", _s->_sound->_sound_volume_music);
diff --git a/scumm/imuse.cpp b/scumm/imuse.cpp
index 7a6742fbd4..2fe1351594 100644
--- a/scumm/imuse.cpp
+++ b/scumm/imuse.cpp
@@ -3302,7 +3302,7 @@ void IMuseAdlib::init(IMuseInternal *eng, OSystem *syst)
adlib_write(0xBD, 0x00);
create_lookup_table();
- _mixer->setup_premix(this, premix_proc);
+ _mixer->setupPremix(this, premix_proc);
}
void IMuseAdlib::adlib_write(byte port, byte value)
diff --git a/scumm/insane.cpp b/scumm/insane.cpp
index ef9dd779eb..a4ad1f59d8 100644
--- a/scumm/insane.cpp
+++ b/scumm/insane.cpp
@@ -1467,7 +1467,7 @@ void SmushPlayer::startVideo(short int arg, byte *videoFile) {
for (idx = 0; idx < MAX_STREAMER; idx++) {
if (_imusTrk[idx] != 0) {
if (_imusNewMixer[idx]) {
- _scumm->_mixer->play_stream(NULL, idx, _imusBuf[idx], _imusFinalSize[idx], _imusRate[idx], _imusFlags[idx]);
+ _scumm->_mixer->playStream(NULL, idx, _imusBuf[idx], _imusFinalSize[idx], _imusRate[idx], _imusFlags[idx]);
} else {
_scumm->_mixer->append(idx, _imusBuf[idx], _imusFinalSize[idx], _imusRate[idx], _imusFlags[idx]);
}
@@ -1479,7 +1479,7 @@ void SmushPlayer::startVideo(short int arg, byte *videoFile) {
for (idx = 0; idx < MAX_STREAMER; idx++) {
if (_psadTrk[idx] != 0) {
if (_strkNewMixer[idx]) {
- _scumm->_mixer->play_stream(NULL, idx, _strkBuf[idx], _strkFinalSize[idx], _strkRate[idx], SoundMixer::FLAG_UNSIGNED | SoundMixer::FLAG_AUTOFREE);
+ _scumm->_mixer->playStream(NULL, idx, _strkBuf[idx], _strkFinalSize[idx], _strkRate[idx], SoundMixer::FLAG_UNSIGNED | SoundMixer::FLAG_AUTOFREE);
} else {
_scumm->_mixer->append(idx, _strkBuf[idx], _strkFinalSize[idx], _strkRate[idx], SoundMixer::FLAG_UNSIGNED | SoundMixer::FLAG_AUTOFREE);
}
diff --git a/scumm/saveload.cpp b/scumm/saveload.cpp
index 0f3011721b..e2e11d555b 100644
--- a/scumm/saveload.cpp
+++ b/scumm/saveload.cpp
@@ -597,7 +597,7 @@ void Scumm::saveOrLoad(Serializer *s)
int var98Backup;
if (_mixer && !s->isSaving())
- _mixer->stop_all();
+ _mixer->stopAll();
if (_current_version == VER_V9)
s->saveLoadEntries(this, mainEntriesV9);
diff --git a/scumm/script_v2.cpp b/scumm/script_v2.cpp
index 5f85f746c2..5487e9dc1e 100644
--- a/scumm/script_v2.cpp
+++ b/scumm/script_v2.cpp
@@ -24,7 +24,8 @@
#include "stdafx.h"
#include "scumm.h"
#include "actor.h"
-#include "smush.h"
+#include "smush/player.h"
+#include "smush/scumm_renderer.h"
#include "sound/mididrv.h"
#include "scumm/imuse.h"
@@ -2699,7 +2700,6 @@ void Scumm::o6_miscOps()
Actor *a;
IMuse *se = _imuse; //yazoo: not very nice
- SmushPlayer * sp;
getStackList(args, sizeof(args) / sizeof(args[0]));
@@ -2708,11 +2708,15 @@ void Scumm::o6_miscOps()
case 4:
grabCursor(args[1], args[2], args[3], args[4]);
break;
- case 6:
- sp = new SmushPlayer(this);
- sp->startVideo(args[1], getStringAddressVar(VAR_VIDEONAME));
- delete sp;
- break;
+ case 6: {
+ ScummRenderer sr(this);
+ SmushPlayer sp(&sr);
+ char filename[512];
+ strcpy(filename, _gameDataPath);
+ strcat(filename, "video/");
+ strcat(filename, (char*)getStringAddressVar(VAR_VIDEONAME));
+ sp.play(filename);
+ }
case 7:
warning("o6_miscOps: stub7()");
break;
diff --git a/scumm/smush/blitter.cpp b/scumm/smush/blitter.cpp
new file mode 100644
index 0000000000..bbeb7a1864
--- /dev/null
+++ b/scumm/smush/blitter.cpp
@@ -0,0 +1,221 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2001/2002 The ScummVM project
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ *
+ */
+
+#include <stdafx.h>
+#include "blitter.h"
+#include "chunck.h"
+
+#include <assert.h>
+#include <string.h> // for memcpy
+
+#ifndef min
+#define min(x, y) ((x) > (y) ? (y) : (x))
+#endif
+
+Blitter::Blitter(char * ptr, const Point & dstsize, const Rect & src) :
+ _ptr(ptr),
+ _clip(dstsize),
+ _src(src),
+ _cur(src.left(), src.top()),
+ _outside(false) {
+#ifdef DEBUG_CLIPPER
+ _clipped = 0;
+ _clippedBlock = 0;
+#endif
+ assert(_ptr);
+ assert(_clip.getX() > 0 && _clip.getY() > 0);
+ assert(_src.width() > 0 && _src.height() > 0);
+ assert(_src.left() < _clip.getX() && _src.right() <= _clip.getX());
+ assert(_src.top() < _clip.getY() && _src.bottom() <= _clip.getY());
+ _offset = _ptr + _clip.getX() * _cur.getY() + _cur.getX();
+}
+
+Blitter::~Blitter() {
+#ifdef DEBUG_CLIPPER
+ if(_clipped || _clippedBlock) {
+ debug(3, "blitter clipped %d pixels and %d blocks", _clipped, _clippedBlock);
+ }
+#endif
+}
+
+void Blitter::advance(int x, int y) {
+ if(y != 0) {
+ _cur.set(_src.left() + x, _cur.getY() + y);
+ } else {
+ _cur.getX() += x;
+ if(_cur.getX() >= _src.right()) {
+ _cur.set(_src.left(), _cur.getY()+1);
+ }
+ }
+ _offset = _ptr + _clip.getX() * _cur.getY() + _cur.getX();
+ _outside = ! _src.isInside(_cur);
+}
+
+void Blitter::advanceBlock(int x, int y) {
+ advance(x*4, y*4);
+}
+
+void Blitter::put(char data) {
+ if(!_outside) {
+ *_offset = data;
+ advance();
+ }
+#ifdef DEBUG_CLIPPER
+ else _clipped ++;
+#endif
+}
+
+void Blitter::put(char data, unsigned int len) {
+ while(len) {
+ if(_outside) {
+#ifdef DEBUG_CLIPPER
+ _clipped += len;
+#endif
+ break;
+ }
+ int l = min((int)len, min(_clip.getX() - _cur.getX(), _src.right() - _cur.getX()));
+ len -= l;
+ memset(_offset, data, l);
+ advance(l);
+ }
+}
+
+void Blitter::blit(char * ptr, unsigned int len) {
+ while(len) {
+ if(_outside) {
+#ifdef DEBUG_CLIPPER
+ _clipped += len;
+#endif
+ break;
+ }
+ int l = min((int)len, min(_clip.getX() - _cur.getX(), _src.right() - _cur.getX()));
+ len -= l;
+ memcpy(_offset, ptr, l);
+ ptr += l;
+ advance(l);
+ }
+}
+
+void Blitter::blit(Chunck & src, unsigned int len) {
+ while(len) {
+ if(_outside) {
+#ifdef DEBUG_CLIPPER
+ _clipped += len;
+#endif
+ break;
+ }
+ int l = min((int)len, min(_clip.getX() -_cur.getX(), _src.right() - _cur.getX()));
+ len -= l;
+ src.read(_offset, l);
+ advance(l);
+ }
+}
+
+void Blitter::putBlock(unsigned int data) {
+ if(_cur.getX() + 3 < _src.right() && _cur.getY() + 3 < _src.bottom()) { // This is clipping
+ assert((_clip.getX() & 3) == 0);
+ unsigned int * dst = (unsigned int *)_offset;
+ int line_size = _clip.getX() >> 2;
+
+ *dst = data; dst += line_size;
+ *dst = data; dst += line_size;
+ *dst = data; dst += line_size;
+ *dst = data;
+
+#ifdef DEBUG_CLIPPER
+ } else {
+ _clippedBlock ++;
+#endif
+ }
+ advanceBlock();
+}
+
+void Blitter::putBlock(unsigned int d1, unsigned int d2, unsigned int d3, unsigned int d4) {
+ if(_cur.getX() + 3 < _src.right() && _cur.getY() + 3 < _src.bottom()) { // This is clipping
+ assert((_clip.getX() & 3) == 0);
+ unsigned int * dst = (unsigned int *)_offset;
+ int line_size = _clip.getX() >> 2;
+
+ *dst = d4; dst += line_size;
+ *dst = d3; dst += line_size;
+ *dst = d2; dst += line_size;
+ *dst = d1;
+
+#ifdef DEBUG_CLIPPER
+ } else {
+ _clippedBlock ++;
+#endif
+ }
+ advanceBlock();
+}
+
+void Blitter::putBlock(unsigned char * data) {
+ if(_cur.getX() + 3 < _src.right() && _cur.getY() + 3 < _src.bottom()) { // This is clipping
+ assert((_clip.getX() & 3) == 0);
+ unsigned int * dst = (unsigned int *)_offset;
+ int line_size = _clip.getX() >> 2;
+ unsigned int * src = (unsigned int *)data;
+ *dst = *src++; dst += line_size;
+ *dst = *src++; dst += line_size;
+ *dst = *src++; dst += line_size;
+ *dst = *src++;
+#ifdef DEBUG_CLIPPER
+ } else {
+ _clippedBlock ++;
+#endif
+ }
+ advanceBlock();
+}
+
+void Blitter::putBlock(Chunck & src) {
+ if(_cur.getX() + 3 < _src.right() && _cur.getY() + 3 < _src.bottom()) { // This is clipping
+ assert((_clip.getX() & 3) == 0);
+ unsigned int * dst = (unsigned int *)_offset;
+ int line_size = _clip.getX() >> 2;
+ *dst = src.getDword(); dst += line_size;
+ *dst = src.getDword(); dst += line_size;
+ *dst = src.getDword(); dst += line_size;
+ *dst = src.getDword();
+#ifdef DEBUG_CLIPPER
+ } else {
+ _clippedBlock ++;
+#endif
+ }
+ advanceBlock();
+}
+
+void Blitter::blockCopy(int offset) {
+ if(_cur.getX() + 3 < _src.right() && _cur.getY() + 3 < _src.bottom()) {// This is clipping
+ char * dst = _offset;
+ *((unsigned int *)dst) = *((unsigned int *)(dst + offset));
+ dst += _clip.getX();
+ *((unsigned int *)dst) = *((unsigned int *)(dst + offset));
+ dst += _clip.getX();
+ *((unsigned int *)dst) = *((unsigned int *)(dst + offset));
+ dst += _clip.getX();
+ *((unsigned int *)dst) = *((unsigned int *)(dst + offset));
+#ifdef DEBUG_CLIPPER
+ } else {
+ _clippedBlock ++;
+#endif
+ }
+ advanceBlock();
+}
diff --git a/scumm/smush/blitter.h b/scumm/smush/blitter.h
new file mode 100644
index 0000000000..3515ba0a20
--- /dev/null
+++ b/scumm/smush/blitter.h
@@ -0,0 +1,79 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2001/2002 The ScummVM project
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ *
+ */
+
+#ifndef __BLITTER_H_
+#define __BLITTER_H_
+
+#include "config.h"
+
+#ifdef DEBUG
+# ifndef NO_DEBUG_CLIPPER
+# define DEBUG_CLIPPER
+# endif
+#else
+# ifdef DEBUG_CLIPPER
+# error DEBUG_CLIPPER defined without DEBUG
+# endif
+#endif
+
+#include "rect.h"
+
+class Chunck;
+/*! @brief class for handling blitting on a frame buffer
+
+ This class allows to perform secure blitting to a frame buffer in several ways.
+ This means that clipping is performed, so that only the part that you want to modify can be modified.
+*/
+class Blitter {
+private:
+ char * _ptr; //!< This is the pointer to the start of the frame buffer
+ char * _offset; //!< This is the current pointer in the frame buffer
+ Point _clip; //!< This is the size of the frame buffer (width/height)
+ Rect _src; //!< This is the size and position of the destination rectangle
+ Point _cur; //!< This is the current position in the destination rectangle
+ bool _outside; //!< flag that is set to \c true when the blitter reach the end of the destination rectangle
+#ifdef DEBUG_CLIPPER
+ int _clipped;
+ int _clippedBlock;
+#endif
+public:
+ /*! @brief constructor
+
+ @param buffer the frame buffer to blit to
+ @param dstsize the size of the frame buffer
+ @param src the rectangle to blit to
+ */
+ Blitter(char * buffer, const Point & dstsize, const Rect & src);
+ virtual ~Blitter();
+ void blit(char *, unsigned int); //!< This method allows to blit directly some data from a buffer
+ void blit(Chunck &, unsigned int); //!< This method allows to blit directly some data from a chunck
+ void put(char); //!< This method allows to blit one byte
+ void put(char, unsigned int); //!< This method allows to blit one byte several times
+ void advance(int = 1, int = 0); //!< This method allows to advance the current position in the blitter
+ void advanceBlock(int = 1, int = 0); //!< This method allows to advance the current position in the blitter in terms of blocks
+ void putBlock(unsigned int); //!< This method allows to blit one block from an int value repeated 4 time
+ void putBlock(Chunck &); //!< This method allows to blit one block directly read from a chunck
+ void putBlock(unsigned char *); //!< This method allows to blit one block directly from a buffer
+ void putBlock(unsigned int, unsigned int, unsigned int, unsigned int); //!< This method allows to blit one block from a 4 int value
+ void blockCopy(int); //!< This method allows to copy one block from another separated by the given offset
+};
+
+#endif
diff --git a/scumm/smush/brenderer.cpp b/scumm/smush/brenderer.cpp
new file mode 100644
index 0000000000..1efa8be5b0
--- /dev/null
+++ b/scumm/smush/brenderer.cpp
@@ -0,0 +1,75 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2001/2002 The ScummVM project
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ *
+ */
+
+#include <stdafx.h>
+#include "brenderer.h"
+
+#include <assert.h>
+
+void BaseRenderer::clean() {
+ if(_data) {
+ delete[] _data;
+ _data = 0;
+ _width = _height = 0;
+ }
+}
+
+BaseRenderer::BaseRenderer() :
+ _data(0),
+ _frame(0),
+ _nbframes(0),
+ _width(0),
+ _height(0) {
+}
+
+BaseRenderer::~BaseRenderer() {
+ clean();
+}
+
+bool BaseRenderer::initFrame(const Point & p) {
+ clean();
+ _width = p.getX();
+ _height = p.getY();
+ assert(_width && _height);
+ _data = new char[_width * _height];
+ if(!_data) error("base_renderer unable to allocate frame buffer");
+ return true;
+}
+
+char * BaseRenderer::lockFrame(int frame) {
+ _frame = frame;
+ if(!_data) error("no allocated image buffer in lock_frame");
+ return _data;
+}
+
+bool BaseRenderer::unlockFrame() {
+ return true;
+}
+
+bool BaseRenderer::flipFrame() {
+ save();
+ return true;
+}
+
+bool BaseRenderer::setPalette(const Palette & pal) {
+ _pal = pal;
+ return true;
+}
diff --git a/scumm/smush/brenderer.h b/scumm/smush/brenderer.h
new file mode 100644
index 0000000000..792fd034c4
--- /dev/null
+++ b/scumm/smush/brenderer.h
@@ -0,0 +1,86 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2001/2002 The ScummVM project
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ *
+ */
+
+#ifndef __BRENDERER_H_
+#define __BRENDERER_H_
+
+#include "config.h"
+
+#include "renderer.h"
+#include "palette.h"
+#include "rect.h"
+
+/*! @brief base class for easily creating ::renderer instances
+
+ This class implements some function available in the ::renderer abstract class, so that
+ creation of subclasses of ::renderer is easier.
+*/
+class BaseRenderer : public Renderer {
+private:
+ Palette _pal; //!< The current palette
+ char * _data; //!< The current frame buffer
+ int _frame; //!< The current frame number
+ int _nbframes; //!< The number of frames in the animation
+ int _width; //!< The current frame's width
+ int _height; //!< The current frame's height
+ const char * _fname; //!< The filename of the animation being played
+protected:
+ virtual void save(int frame = -1) = 0;
+
+protected:
+ const char * getFilename() const { return _fname; }; //!< accessor for animation filename
+ int getNbframes() const { return _nbframes; }; //!< accessor for number of frames
+ int getWidth() const { return _width; }; //!< accessor for current width
+ int getHeight() const { return _height; }; //!< accessor for current height
+ const Palette & pal() const { return _pal; }; //!< accessor for current palette
+ const char * data() const { return _data; }; //!< accessor for current frame buffer
+ void clean(); //!< memory cleanup (deletes frame buffer)
+ void setFrame(int f) { _frame = f; }; //!< allows to change the frame number
+public:
+ int getFrame() const { return _frame; }; //!< accessor for current frame number
+ BaseRenderer();
+ virtual ~BaseRenderer();
+
+ virtual bool initFrame(const Point & size);
+ virtual char * lockFrame(int frame);
+ virtual bool unlockFrame();
+ virtual bool flipFrame();
+ virtual bool setPalette(const Palette & pal);
+ virtual bool startDecode(const char * fname, int version, int nbframes) { _fname = fname; _nbframes = nbframes; return true; }
+ virtual Mixer * getMixer() { return 0; };
+ virtual bool prematureClose() { return false; };
+};
+
+/*! @brief A null ::renderer
+
+ This class completely implements ::renderer, without actually doing anything.
+ This class is useful for performance measurements.
+*/
+class NullRenderer : public BaseRenderer {
+protected:
+ void save(int frame = -1) {};
+public:
+ NullRenderer() {};
+ virtual ~NullRenderer() {};
+ bool wait(int ms) { return true; };
+};
+
+#endif
diff --git a/scumm/smush/channel.h b/scumm/smush/channel.h
new file mode 100644
index 0000000000..5010c3f581
--- /dev/null
+++ b/scumm/smush/channel.h
@@ -0,0 +1,157 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2001/2002 The ScummVM project
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ *
+ */
+
+#ifndef __CHANNEL_H_
+#define __CHANNEL_H_
+
+#include "config.h"
+
+#ifdef DEBUG
+# ifndef NO_DEBUG_CHANNEL
+# define DEBUG_CHANNEL
+# endif
+#else
+# ifdef DEBUG_CHANNEL
+# error DEBUG_CHANNEL defined without DEBUG
+# endif
+#endif
+
+class Chunck;
+class ContChunck;
+
+/*! @brief interface for a sound channel (a track)
+
+ This is the interface for sound channels.
+*/
+class _Channel {
+public:
+ virtual ~_Channel() {};
+ // called by the smush_player
+ virtual bool appendData(Chunck & b, int size) = 0;
+ virtual bool setParameters(int, int, int, int) = 0;
+ virtual bool checkParameters(int, int, int, int, int) = 0;
+ // called by the mixer
+ virtual bool isTerminated() const = 0;
+ virtual int availableSoundData() const = 0;
+ virtual void getSoundData(short * sound_buffer, int size) = 0; // size is in sample
+ virtual void getSoundData(char * sound_buffer, int size) = 0;
+ virtual bool getParameters(int &rate, bool &stereo, bool &is_16bit) = 0;
+ virtual int getTrackIdentifier() const = 0;
+};
+
+class SaudChannel : public _Channel {
+private:
+ int _track; //!< The track identifier
+ int _nbframes; //!< number of frames of the track (unused)
+ int _dataSize; //!< the size of the sound buffer
+ int _frequency; //!< the frequency target of the track (always 22050)
+ bool _inData; //!< are we processing data ?
+ bool _markReached; //!< set to \c true when the SMRK tag is reached
+ int _flags; //!< current flags of the track (unused)
+ int _volume; //!< the current track volume
+ int _balance; //!< the current track balance
+ int _index; //!< the current PSAD index (for coherency checking)
+ short _voltable[2][256]; //!< the precalculated volume table (stereo 16 bits)
+ unsigned char * _tbuffer; //!< data temporary buffer
+ int _tbufferSize; //!< temporary buffer size
+ unsigned char * _sbuffer; //!< sound buffer
+ int _sbufferSize; //!< sound buffer size
+
+protected:
+ void handleStrk(Chunck & c);
+ void handleSmrk(Chunck & c);
+ void handleShdr(Chunck & c);
+ bool handleSubTags(int & offset);
+ bool processBuffer();
+ void recalcVolumeTable();
+
+public:
+ SaudChannel(int track, int freq);
+ virtual ~SaudChannel();
+ bool isTerminated() const;
+ bool setParameters(int duration, int flags, int vol1, int vol2);
+ bool checkParameters(int index, int duration, int flags, int vol1, int vol2);
+ bool appendData(Chunck & b, int size);
+ int availableSoundData() const;
+ void getSoundData(short * sound_buffer, int size);
+ void getSoundData(char * sound_buffer, int size) { error("16bit request for SAUD channel should never happen"); };
+ bool getParameters(int &rate, bool &stereo, bool &is_16bit) {
+ rate = _frequency;
+ stereo = true;
+ is_16bit = true;
+ return true;
+ };
+ virtual int getTrackIdentifier() const { return _track; };
+};
+
+/*! @brief class for a IACT sound ::channel (a The Dig track)
+
+ This class implements a channel specifically for The Dig.
+
+ \bug for unknown reason, some sound have a too long duration, or repeat themselves.
+*/
+class ImuseChannel : public _Channel {
+private:
+ int _track; //!< the track number
+ unsigned char * _tbuffer; //!< data temporary buffer
+ int _tbufferSize; //!< temporary buffer size
+ unsigned char * _sbuffer; //!< sound buffer
+ int _sbufferSize; //!< sound buffer size
+ int _srbufferSize;
+ int _frequency; //!< the target frequency of the ::mixer
+ int _dataSize; //!< remaining size of sound data in the iMUS buffer
+ bool _inData;
+
+ int _bitsize; //!< the bitsize of the original data
+ int _rate; //!< the sampling rate of the original data
+ int _channels; //!< the number of channels of the original data
+
+protected:
+ int decode(int size, int &ret);
+ void decode();
+ bool processBuffer();
+ bool handleMap(Chunck &);
+ bool handleFormat(Chunck &);
+ bool handleText(Chunck &);
+ bool handleRegion(Chunck &);
+ bool handleStop(Chunck &);
+ bool handleSubTags(int & offset);
+
+public:
+ ImuseChannel(int track, int freq);
+ virtual ~ImuseChannel();
+ bool isTerminated() const;
+ bool setParameters(int nbframes, int size, int unk1, int unk2);
+ bool checkParameters(int index, int nbframes, int size, int unk1, int unk2);
+ bool appendData(Chunck & b, int size);
+ int availableSoundData() const;
+ void getSoundData(short * sound_buffer, int size);
+ void getSoundData(char * sound_buffer, int size);
+ bool getParameters(int &rate, bool &stereo, bool &is_16bit) {
+ rate = _frequency;
+ stereo = (_channels == 2);
+ is_16bit = (_bitsize > 8);
+ return true;
+ };
+ virtual int getTrackIdentifier() const { return _track; };
+};
+
+#endif
diff --git a/scumm/smush/chunck.cpp b/scumm/smush/chunck.cpp
new file mode 100644
index 0000000000..b4bf99fcbc
--- /dev/null
+++ b/scumm/smush/chunck.cpp
@@ -0,0 +1,288 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2001/2002 The ScummVM project
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ *
+ */
+
+#include <stdafx.h>
+#include "chunck.h"
+
+#include <stdio.h> // for FILE, fopen, fclose, fseek and ftell
+#include <string.h> // for memcpy
+
+/*! @brief very small and fast wrapper for a ifstream.
+
+ implements reference counting, so that ::file_chunck does not leak memory !
+*/
+class FilePtr {
+ char * _filename;
+ FILE * _ifs;
+ int _refcount;
+ int _curPos;
+public:
+ FilePtr(const char * fname) : _refcount(1), _curPos(0) {
+ debug(9, "FilePtr created for %s", fname);
+ _filename = strdup(fname);
+ _ifs = fopen(fname, "rb");
+ if(_ifs == NULL) error("FilePtr unable to read file \"%s\"", fname);
+ }
+ ~FilePtr() {
+ debug(9, "FilePtr destroyed for %s", _filename);
+ free(_filename);
+ fclose(_ifs);
+ }
+ int tell() {
+ return _curPos;
+ }
+ bool seek(int pos) {
+ if(pos != _curPos) {
+ fseek(_ifs, pos, SEEK_SET);
+ _curPos = pos;
+ }
+ return true;
+ }
+ bool read(void * ptr, int size) {
+ fread(ptr, size, 1, _ifs);
+ _curPos += size;
+ return true;
+ }
+ void incRef() {
+ _refcount++;
+ }
+ void decRef() {
+ if(--_refcount == 0)
+ delete this;
+ }
+};
+
+const char * Chunck::ChunckString(Chunck::type t) {
+ static char data[5];
+ data[0] = (char)((t >> 24) & 0xFF);
+ data[1] = (char)((t >> 16) & 0xFF);
+ data[2] = (char)((t >> 8) & 0xFF);
+ data[3] = (char)((t >> 0) & 0xFF);
+ data[4] = 0;
+ return data;
+}
+
+FileChunck::FileChunck() : _data(0), _type(0), _size(0), _curPos(0) {
+}
+
+FileChunck::~FileChunck() {
+ if(_data) _data->decRef();
+}
+
+FileChunck::FileChunck(const char * fname) {
+ _data = new FilePtr(fname);
+ _data->read(&_type, 4);
+ _type = TO_BE_32(_type);
+ _data->read(&_size, 4);
+ _size = TO_BE_32(_size);
+ _offset = _data->tell();
+ _curPos = 0;
+}
+
+Chunck::type FileChunck::getType() const {
+ return _type;
+}
+
+unsigned int FileChunck::getSize() const {
+ return _size;
+}
+
+Chunck * FileChunck::subBlock() {
+ FileChunck * ptr = new FileChunck;
+ ptr->_data = _data;
+ _data->incRef();
+ _data->seek(_offset + _curPos);
+ unsigned int temp;
+ _data->read(&temp, 4);
+ ptr->_type = TO_BE_32(temp);
+ _data->read(&temp, 4);
+ ptr->_size = TO_BE_32(temp);
+ ptr->_offset = _offset + _curPos + 8;
+ ptr->_curPos = 0;
+ seek(8 + ptr->getSize());
+ return ptr;
+}
+
+bool FileChunck::eof() const {
+ return _curPos >= _size;
+}
+
+unsigned int FileChunck::tell() const {
+ return _curPos;
+}
+
+bool FileChunck::seek(int delta, seek_type dir) {
+ switch(dir) {
+ case seek_cur:
+ _curPos += delta;
+ break;
+ case seek_start:
+ if(delta < 0) error("invalid seek request");
+ _curPos = (unsigned int)delta;
+ break;
+ case seek_end:
+ if(delta > 0 || (_size + delta) < 0) error("invalid seek request");
+ _curPos = (unsigned int)(_size + delta);
+ break;
+ }
+ if(_curPos > _size) {
+ error("invalid seek request : %d > %d (delta == %d)", _curPos, _size, delta);
+ }
+ return true;
+}
+
+bool FileChunck::read(void * buffer, unsigned int size) {
+ if(size <= 0 || (_curPos + size) > _size) error("invalid buffer read request");
+ _data->seek(_offset + _curPos);
+ _data->read(buffer, size);
+ _curPos += size;
+ return true;
+}
+
+char FileChunck::getChar() {
+ if(_curPos >= _size) error("invalid char read request");
+ _data->seek(_offset + _curPos);
+ char buffer;
+ _data->read(&buffer, sizeof(buffer));
+ _curPos+= sizeof(buffer);
+ return buffer;
+}
+
+unsigned char FileChunck::getByte() {
+ if(_curPos >= _size) error("invalid byte read request");
+ _data->seek(_offset + _curPos);
+ unsigned char buffer;
+ _data->read(&buffer, sizeof(buffer));
+ _curPos+= sizeof(buffer);
+ return buffer;
+}
+
+short FileChunck::getShort() {
+ unsigned short buffer = getWord();
+ return *((short*)&buffer);
+}
+
+unsigned short FileChunck::getWord() {
+ if(_curPos >= _size - 1) error("invalid word read request");
+ _data->seek(_offset + _curPos);
+ unsigned short buffer;
+ _data->read(&buffer, sizeof(buffer));
+ _curPos+= sizeof(buffer);
+ return TO_LE_16(buffer);
+}
+
+unsigned int FileChunck::getDword() {
+ if(_curPos >= _size - 3) error("invalid dword read request");
+ _data->seek(_offset + _curPos);
+ unsigned int buffer;
+ _data->read(&buffer, sizeof(buffer));
+ _curPos+= sizeof(buffer);
+ return TO_LE_32(buffer);
+}
+
+ContChunck::ContChunck(char * data) {
+ if(data == 0) error("Chunck() called with NULL pointer");
+ _type = (Chunck::type)READ_BE_UINT32(data);
+ _size = READ_BE_UINT32(data+4);
+ _data = data + sizeof(Chunck::type) + sizeof(unsigned int);
+ _curPos = 0;
+}
+
+Chunck::type ContChunck::getType() const {
+ return _type;
+}
+
+unsigned int ContChunck::getSize() const {
+ return _size;
+}
+
+Chunck * ContChunck::subBlock() {
+ ContChunck * ptr = new ContChunck(_data + _curPos);
+ seek(sizeof(Chunck::type) + sizeof(unsigned int) + ptr->getSize());
+ return ptr;
+}
+
+bool ContChunck::eof() const {
+ return _curPos >= _size;
+}
+
+unsigned int ContChunck::tell() const {
+ return _curPos;
+}
+
+bool ContChunck::seek(int delta, seek_type dir) {
+ switch(dir) {
+ case seek_cur:
+ _curPos += delta;
+ break;
+ case seek_start:
+ if(delta < 0) error("invalid seek request");
+ _curPos = (unsigned int)delta;
+ break;
+ case seek_end:
+ if(delta > 0 || (_size + delta) < 0) error("invalid seek request");
+ _curPos = (unsigned int)(_size + delta);
+ break;
+ }
+ if(_curPos > _size) {
+ error("invalid seek request : %d > %d (delta == %d)", _curPos, _size, delta);
+ }
+ return true;
+}
+
+bool ContChunck::read(void * buffer, unsigned int size) {
+ if(size <= 0 || (_curPos + size) > _size) error("invalid buffer read request");
+ memcpy(buffer, _data + _curPos, size);
+ _curPos += size;
+ return true;
+}
+
+char ContChunck::getChar() {
+ if(_curPos >= _size) error("invalid char read request");
+ return _data[_curPos++];
+}
+
+unsigned char ContChunck::getByte() {
+ if(_curPos >= _size) error("invalid byte read request");
+ unsigned char * ptr = (unsigned char *)(_data + _curPos);
+ _curPos += 1;
+ return *ptr;
+}
+
+short ContChunck::getShort() {
+ if(_curPos >= _size - 1) error("invalid short read request");
+ unsigned short buffer = getWord();
+ return *((short*)&buffer);
+}
+
+unsigned short ContChunck::getWord() {
+ if(_curPos >= _size - 1) error("invalid word read request");
+ unsigned short * ptr = (unsigned short *)(_data + _curPos);
+ _curPos += 2;
+ return READ_LE_UINT16(ptr);
+}
+
+unsigned int ContChunck::getDword() {
+ if(_curPos >= _size - 3) error("invalid dword read request");
+ unsigned int * ptr = (unsigned int *)(_data + _curPos);
+ _curPos += 4;
+ return READ_LE_UINT32(ptr);
+}
diff --git a/scumm/smush/chunck.h b/scumm/smush/chunck.h
new file mode 100644
index 0000000000..3a1ec6adda
--- /dev/null
+++ b/scumm/smush/chunck.h
@@ -0,0 +1,121 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2001/2002 The ScummVM project
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ *
+ */
+
+#ifndef __CHUNCK_H_
+#define __CHUNCK_H_
+
+#include "config.h"
+
+/*! @brief Interface for chunck handling
+
+ This class is an interface for reading from a chunck.
+
+ \todo handle big endian system.
+*/
+class Chunck {
+public:
+ enum seek_type { seek_start, seek_end, seek_cur };
+ virtual ~Chunck() {};
+ typedef unsigned int type; //!< type of a chunck (i.e. The first 4byte field of the chunck structure).
+ /*! @brief convert a type to a string
+
+ Utility function that convert a type to a string.
+
+ @param t the type to convert to a string
+
+ @return the converted string
+ */
+ static const char * ChunckString(type t);
+
+ virtual type getType() const = 0; //!< return the type of the chunck
+ virtual unsigned int getSize() const = 0; //!< return the size of the chunck
+ virtual Chunck * subBlock() = 0; //!< extract a subchunck from the current read position
+ virtual bool eof() const = 0; //!< is the chunck completely read ?
+ virtual unsigned int tell() const = 0; //!< get the chunck current read position
+ virtual bool seek(int delta, seek_type dir = seek_cur) = 0; //!< move the current read position inside the chunck
+ virtual bool read(void * buffer, unsigned int size) = 0; //!< read some data for the current read position
+ virtual char getChar() = 0; //!< extract the character at the current read position
+ virtual unsigned char getByte() = 0; //!< extract the byte at the current read position
+ virtual short getShort() = 0; //!< extract the short at the current read position
+ virtual unsigned short getWord() = 0; //!< extract the word at the current read position
+ virtual unsigned int getDword()= 0; //!< extract the dword at the current read position
+};
+
+class FilePtr;
+
+/*! @brief file based ::chunck
+
+ This class is an implementation of ::chunck that handles file.
+
+*/
+class FileChunck : public Chunck {
+private:
+ FilePtr * _data;
+ type _type;
+ unsigned int _size;
+ unsigned int _offset;
+ unsigned int _curPos;
+protected:
+ FileChunck();
+public:
+ FileChunck(const char * fname);
+ virtual ~FileChunck();
+ type getType() const;
+ unsigned int getSize() const;
+ Chunck * subBlock();
+ bool eof() const;
+ unsigned int tell() const;
+ bool seek(int delta, seek_type dir = seek_cur);
+ bool read(void * buffer, unsigned int size);
+ char getChar();
+ unsigned char getByte();
+ short getShort();
+ unsigned short getWord();
+ unsigned int getDword();
+};
+
+/*! @brief memory based ::chunck
+
+ This class is an implementation of ::chunck that handles a memory buffer.
+*/
+class ContChunck : public Chunck {
+private:
+ char * _data;
+ Chunck::type _type;
+ unsigned int _size;
+ unsigned int _curPos;
+public:
+ ContChunck(char * data);
+ Chunck::type getType() const;
+ unsigned int getSize() const;
+ Chunck * subBlock();
+ bool eof() const;
+ unsigned int tell() const;
+ bool seek(int delta, seek_type dir = seek_cur);
+ bool read(void * buffer, unsigned int size);
+ char getChar();
+ unsigned char getByte();
+ short getShort();
+ unsigned short getWord();
+ unsigned int getDword();
+};
+
+#endif
diff --git a/scumm/smush/chunck_type.h b/scumm/smush/chunck_type.h
new file mode 100644
index 0000000000..e3e2596175
--- /dev/null
+++ b/scumm/smush/chunck_type.h
@@ -0,0 +1,57 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2001/2002 The ScummVM project
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ *
+ */
+
+#ifndef __CHUNCK_TYPE_H
+#define __CHUNCK_TYPE_H
+
+#include "chunck.h"
+
+#define MAKE_TYPE(a,b,c,d) (Chunck::type)( ((a) << 24) | ((b) << 16) | ((c) << 8) | (d) )
+
+static const Chunck::type TYPE_ANIM = MAKE_TYPE('A', 'N', 'I', 'M');
+static const Chunck::type TYPE_AHDR = MAKE_TYPE('A', 'H', 'D', 'R');
+static const Chunck::type TYPE_FRME = MAKE_TYPE('F', 'R', 'M', 'E');
+static const Chunck::type TYPE_NPAL = MAKE_TYPE('N', 'P', 'A', 'L');
+static const Chunck::type TYPE_FOBJ = MAKE_TYPE('F', 'O', 'B', 'J');
+static const Chunck::type TYPE_PSAD = MAKE_TYPE('P', 'S', 'A', 'D');
+static const Chunck::type TYPE_TRES = MAKE_TYPE('T', 'R', 'E', 'S');
+static const Chunck::type TYPE_XPAL = MAKE_TYPE('X', 'P', 'A', 'L');
+static const Chunck::type TYPE_IACT = MAKE_TYPE('I', 'A', 'C', 'T');
+static const Chunck::type TYPE_STOR = MAKE_TYPE('S', 'T', 'O', 'R');
+static const Chunck::type TYPE_FTCH = MAKE_TYPE('F', 'T', 'C', 'H');
+static const Chunck::type TYPE_SKIP = MAKE_TYPE('S', 'K', 'I', 'P');
+static const Chunck::type TYPE_STRK = MAKE_TYPE('S', 'T', 'R', 'K');
+static const Chunck::type TYPE_SMRK = MAKE_TYPE('S', 'M', 'R', 'K');
+static const Chunck::type TYPE_SHDR = MAKE_TYPE('S', 'H', 'D', 'R');
+static const Chunck::type TYPE_SDAT = MAKE_TYPE('S', 'D', 'A', 'T');
+static const Chunck::type TYPE_SAUD = MAKE_TYPE('S', 'A', 'U', 'D');
+static const Chunck::type TYPE_iMUS = MAKE_TYPE('i', 'M', 'U', 'S');
+static const Chunck::type TYPE_FRMT = MAKE_TYPE('F', 'R', 'M', 'T');
+static const Chunck::type TYPE_TEXT = MAKE_TYPE('T', 'E', 'X', 'T');
+static const Chunck::type TYPE_REGN = MAKE_TYPE('R', 'E', 'G', 'N');
+static const Chunck::type TYPE_STOP = MAKE_TYPE('S', 'T', 'O', 'P');
+static const Chunck::type TYPE_MAP_ = MAKE_TYPE('M', 'A', 'P', ' ');
+static const Chunck::type TYPE_DATA = MAKE_TYPE('D', 'A', 'T', 'A');
+static const Chunck::type TYPE_ETRS = MAKE_TYPE('E', 'T', 'R', 'S');
+
+#undef MAKE_TYPE
+
+#endif
diff --git a/scumm/smush/codec1.cpp b/scumm/smush/codec1.cpp
new file mode 100644
index 0000000000..495b50404f
--- /dev/null
+++ b/scumm/smush/codec1.cpp
@@ -0,0 +1,76 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2001/2002 The ScummVM project
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ *
+ */
+
+#include <stdafx.h>
+#include "codec1.h"
+#include "chunck.h"
+#include "blitter.h"
+
+Codec1Decoder::~Codec1Decoder() {
+}
+
+bool Codec1Decoder::decode(Blitter & dst, Chunck & src) {
+ int val;
+ int size_line;
+ int code, length;
+ int h, height = getRect().height();
+
+ for(h = 0; h < height; h++) {
+ size_line = src.getWord(); // size of compressed line !
+#ifdef DEBUG_CODEC1
+ debug(7, "codec1 : h == %d, size_line == %d", h, size_line);
+#endif
+ while(size_line > 0) {
+ code = src.getByte();
+ size_line --;
+ length = (code >> 1) + 1;
+#ifdef DEBUG_CODEC1
+ debug(7, "codec1 : length == %d", length);
+#endif
+ if(code & 1) {
+ val = src.getByte();
+ size_line --;
+ if(val) dst.put(val, length);
+ else dst.advance(length);
+#ifdef DEBUG_CODEC1
+ debug(7, "codec1 : blitting %d times %d", length, val);
+#endif
+ } else {
+ size_line -= length;
+#ifdef DEBUG_CODEC1
+ debug(7, "codec1 : blitting %d entries", length);
+#endif
+ while(length--) {
+ val = src.getByte();
+ if(val) dst.put(val);
+ else dst.advance();
+ }
+ }
+ }
+ }
+#ifdef DEBUG_CODEC1
+ if(!src.eof()) {
+ int len = src.getSize() - src.tell();
+ debug(7, "codec1: remaining length after decode == %d", len);
+ }
+#endif
+ return true;
+}
diff --git a/scumm/smush/codec1.h b/scumm/smush/codec1.h
new file mode 100644
index 0000000000..ae60518d6a
--- /dev/null
+++ b/scumm/smush/codec1.h
@@ -0,0 +1,48 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2001/2002 The ScummVM project
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ *
+ */
+
+#ifndef __CODEC1_H_
+#define __CODEC1_H_
+
+#include "config.h"
+
+#ifdef DEBUG
+# ifndef NO_DEBUG_CODEC1
+# define DEBUG_CODEC1
+# endif
+#else
+# ifdef DEBUG_CODEC1
+# error DEBUG_CODEC1 defined without DEBUG
+# endif
+#endif
+
+#include "decoder.h"
+
+/*! @brief ::decoder for codec 1 and 3.
+
+*/
+class Codec1Decoder : public Decoder {
+public:
+ virtual ~Codec1Decoder();
+ bool decode(Blitter &, Chunck &);
+};
+
+#endif
diff --git a/scumm/smush/codec37.cpp b/scumm/smush/codec37.cpp
new file mode 100644
index 0000000000..5adaa56d54
--- /dev/null
+++ b/scumm/smush/codec37.cpp
@@ -0,0 +1,436 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2001/2002 The ScummVM project
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ *
+ */
+
+#include <stdafx.h>
+#include "codec37.h"
+#include "chunck.h"
+#include "blitter.h"
+
+#include <assert.h>
+#include <string.h> // for memset
+
+bool Codec37Decoder::initSize(const Point & p, const Rect & r) {
+ if(r.width() != getRect().width() && r.height() != getRect().height()) {
+ if(
+ (r.width() != 320 || r.height() != 200) &&
+ (r.width() != 384 || r.height() != 242) &&
+ (r.width() != 640 || r.height() != 480)
+ )
+ return false;
+ Decoder::initSize(p, r);
+ clean();
+ int frame_size = getRect().width() * getRect().height();
+ _deltaSize = frame_size * 2 + DELTA_ADD * 4;
+ _deltaBuf = new unsigned char[_deltaSize];
+ if(_deltaBuf == 0) error("unable to allocate decoder buffer");
+ _deltaBufs[0] = _deltaBuf + DELTA_ADD;
+ _deltaBufs[1] = _deltaBuf + frame_size + DELTA_ADD * 3;
+ _offsetTable = new short[255];
+ if(_offsetTable == 0) error("unable to allocate decoder offset table");
+ _tableLastPitch = -1;
+ _tableLastIndex = -1;
+ return true;
+ }
+ return false;
+}
+
+Codec37Decoder::Codec37Decoder() {
+ _deltaSize = 0;
+ _deltaBuf = 0;
+ _deltaBufs[0] = 0;
+ _deltaBufs[1] = 0;
+ _curtable = 0;
+ _offsetTable = 0;
+ _tableLastPitch = -1;
+ _tableLastIndex = -1;
+ _prevSeqNb = 32768; // Some invalid number
+}
+
+void Codec37Decoder::clean() {
+ if(_offsetTable) {
+ delete []_offsetTable;
+ _offsetTable = 0;
+ _tableLastPitch = -1;
+ _tableLastIndex = -1;
+ }
+ if(_deltaBuf) {
+ delete []_deltaBuf;
+ _deltaSize = 0;
+ _deltaBuf = 0;
+ _deltaBufs[0] = 0;
+ _deltaBufs[1] = 0;
+ }
+}
+
+Codec37Decoder::~Codec37Decoder() {
+ clean();
+}
+
+void Codec37Decoder::maketable(int pitch, int index) {
+ static const char maketable_bytes[] = {
+ 0, 0, 1, 0, 2, 0, 3, 0, 5, 0, 8, 0, 13, 0, 21, 0,
+ -1, 0, -2, 0, -3, 0, -5, 0, -8, 0, -13, 0, -17, 0, -21, 0,
+ 0, 1, 1, 1, 2, 1, 3, 1, 5, 1, 8, 1, 13, 1, 21, 1,
+ -1, 1, -2, 1, -3, 1, -5, 1, -8, 1, -13, 1, -17, 1, -21, 1,
+ 0, 2, 1, 2, 2, 2, 3, 2, 5, 2, 8, 2, 13, 2, 21, 2,
+ -1, 2, -2, 2, -3, 2, -5, 2, -8, 2, -13, 2, -17, 2, -21, 2,
+ 0, 3, 1, 3, 2, 3, 3, 3, 5, 3, 8, 3, 13, 3, 21, 3,
+ -1, 3, -2, 3, -3, 3, -5, 3, -8, 3, -13, 3, -17, 3, -21, 3,
+ 0, 5, 1, 5, 2, 5, 3, 5, 5, 5, 8, 5, 13, 5, 21, 5,
+ -1, 5, -2, 5, -3, 5, -5, 5, -8, 5, -13, 5, -17, 5, -21, 5,
+ 0, 8, 1, 8, 2, 8, 3, 8, 5, 8, 8, 8, 13, 8, 21, 8,
+ -1, 8, -2, 8, -3, 8, -5, 8, -8, 8, -13, 8, -17, 8, -21, 8,
+ 0, 13, 1, 13, 2, 13, 3, 13, 5, 13, 8, 13, 13, 13, 21, 13,
+ -1, 13, -2, 13, -3, 13, -5, 13, -8, 13, -13, 13, -17, 13, -21, 13,
+ 0, 21, 1, 21, 2, 21, 3, 21, 5, 21, 8, 21, 13, 21, 21, 21,
+ -1, 21, -2, 21, -3, 21, -5, 21, -8, 21, -13, 21, -17, 21, -21, 21,
+ 0, -1, 1, -1, 2, -1, 3, -1, 5, -1, 8, -1, 13, -1, 21, -1,
+ -1, -1, -2, -1, -3, -1, -5, -1, -8, -1, -13, -1, -17, -1, -21, -1,
+ 0, -2, 1, -2, 2, -2, 3, -2, 5, -2, 8, -2, 13, -2, 21, -2,
+ -1, -2, -2, -2, -3, -2, -5, -2, -8, -2, -13, -2, -17, -2, -21, -2,
+ 0, -3, 1, -3, 2, -3, 3, -3, 5, -3, 8, -3, 13, -3, 21, -3,
+ -1, -3, -2, -3, -3, -3, -5, -3, -8, -3, -13, -3, -17, -3, -21, -3,
+ 0, -5, 1, -5, 2, -5, 3, -5, 5, -5, 8, -5, 13, -5, 21, -5,
+ -1, -5, -2, -5, -3, -5, -5, -5, -8, -5, -13, -5, -17, -5, -21, -5,
+ 0, -8, 1, -8, 2, -8, 3, -8, 5, -8, 8, -8, 13, -8, 21, -8,
+ -1, -8, -2, -8, -3, -8, -5, -8, -8, -8, -13, -8, -17, -8, -21, -8,
+ 0, -13, 1, -13, 2, -13, 3, -13, 5, -13, 8, -13, 13, -13, 21, -13,
+ -1, -13, -2, -13, -3, -13, -5, -13, -8, -13, -13, -13, -17, -13, -21, -13,
+ 0, -17, 1, -17, 2, -17, 3, -17, 5, -17, 8, -17, 13, -17, 21, -17,
+ -1, -17, -2, -17, -3, -17, -5, -17, -8, -17, -13, -17, -17, -17, -21, -17,
+ 0, -21, 1, -21, 2, -21, 3, -21, 5, -21, 8, -21, 13, -21, 21, -21,
+ -1, -21, -2, -21, -3, -21, -5, -21, -8, -21, -13, -21, -17, -21, 0, 0,
+ -8, -29, 8, -29, -18, -25, 17, -25, 0, -23, -6, -22, 6, -22, -13, -19,
+ 12, -19, 0, -18, 25, -18, -25, -17, -5, -17, 5, -17, -10, -15, 10, -15,
+ 0, -14, -4, -13, 4, -13, 19, -13, -19, -12, -8, -11, -2, -11, 0, -11,
+ 2, -11, 8, -11, -15, -10, -4, -10, 4, -10, 15, -10, -6, -9, -1, -9,
+ 1, -9, 6, -9, -29, -8, -11, -8, -8, -8, -3, -8, 3, -8, 8, -8,
+ 11, -8, 29, -8, -5, -7, -2, -7, 0, -7, 2, -7, 5, -7, -22, -6,
+ -9, -6, -6, -6, -3, -6, -1, -6, 1, -6, 3, -6, 6, -6, 9, -6,
+ 22, -6, -17, -5, -7, -5, -4, -5, -2, -5, 0, -5, 2, -5, 4, -5,
+ 7, -5, 17, -5, -13, -4, -10, -4, -5, -4, -3, -4, -1, -4, 0, -4,
+ 1, -4, 3, -4, 5, -4, 10, -4, 13, -4, -8, -3, -6, -3, -4, -3,
+ -3, -3, -2, -3, -1, -3, 0, -3, 1, -3, 2, -3, 4, -3, 6, -3,
+ 8, -3, -11, -2, -7, -2, -5, -2, -3, -2, -2, -2, -1, -2, 0, -2,
+ 1, -2, 2, -2, 3, -2, 5, -2, 7, -2, 11, -2, -9, -1, -6, -1,
+ -4, -1, -3, -1, -2, -1, -1, -1, 0, -1, 1, -1, 2, -1, 3, -1,
+ 4, -1, 6, -1, 9, -1, -31, 0, -23, 0, -18, 0, -14, 0, -11, 0,
+ -7, 0, -5, 0, -4, 0, -3, 0, -2, 0, -1, 0, 0, -31, 1, 0,
+ 2, 0, 3, 0, 4, 0, 5, 0, 7, 0, 11, 0, 14, 0, 18, 0,
+ 23, 0, 31, 0, -9, 1, -6, 1, -4, 1, -3, 1, -2, 1, -1, 1,
+ 0, 1, 1, 1, 2, 1, 3, 1, 4, 1, 6, 1, 9, 1, -11, 2,
+ -7, 2, -5, 2, -3, 2, -2, 2, -1, 2, 0, 2, 1, 2, 2, 2,
+ 3, 2, 5, 2, 7, 2, 11, 2, -8, 3, -6, 3, -4, 3, -2, 3,
+ -1, 3, 0, 3, 1, 3, 2, 3, 3, 3, 4, 3, 6, 3, 8, 3,
+ -13, 4, -10, 4, -5, 4, -3, 4, -1, 4, 0, 4, 1, 4, 3, 4,
+ 5, 4, 10, 4, 13, 4, -17, 5, -7, 5, -4, 5, -2, 5, 0, 5,
+ 2, 5, 4, 5, 7, 5, 17, 5, -22, 6, -9, 6, -6, 6, -3, 6,
+ -1, 6, 1, 6, 3, 6, 6, 6, 9, 6, 22, 6, -5, 7, -2, 7,
+ 0, 7, 2, 7, 5, 7, -29, 8, -11, 8, -8, 8, -3, 8, 3, 8,
+ 8, 8, 11, 8, 29, 8, -6, 9, -1, 9, 1, 9, 6, 9, -15, 10,
+ -4, 10, 4, 10, 15, 10, -8, 11, -2, 11, 0, 11, 2, 11, 8, 11,
+ 19, 12, -19, 13, -4, 13, 4, 13, 0, 14, -10, 15, 10, 15, -5, 17,
+ 5, 17, 25, 17, -25, 18, 0, 18, -12, 19, 13, 19, -6, 22, 6, 22,
+ 0, 23, -17, 25, 18, 25, -8, 29, 8, 29, 0, 31, 0, 0, -6, -22,
+ 6, -22, -13, -19, 12, -19, 0, -18, -5, -17, 5, -17, -10, -15, 10, -15,
+ 0, -14, -4, -13, 4, -13, 19, -13, -19, -12, -8, -11, -2, -11, 0, -11,
+ 2, -11, 8, -11, -15, -10, -4, -10, 4, -10, 15, -10, -6, -9, -1, -9,
+ 1, -9, 6, -9, -11, -8, -8, -8, -3, -8, 0, -8, 3, -8, 8, -8,
+ 11, -8, -5, -7, -2, -7, 0, -7, 2, -7, 5, -7, -22, -6, -9, -6,
+ -6, -6, -3, -6, -1, -6, 1, -6, 3, -6, 6, -6, 9, -6, 22, -6,
+ -17, -5, -7, -5, -4, -5, -2, -5, -1, -5, 0, -5, 1, -5, 2, -5,
+ 4, -5, 7, -5, 17, -5, -13, -4, -10, -4, -5, -4, -3, -4, -2, -4,
+ -1, -4, 0, -4, 1, -4, 2, -4, 3, -4, 5, -4, 10, -4, 13, -4,
+ -8, -3, -6, -3, -4, -3, -3, -3, -2, -3, -1, -3, 0, -3, 1, -3,
+ 2, -3, 3, -3, 4, -3, 6, -3, 8, -3, -11, -2, -7, -2, -5, -2,
+ -4, -2, -3, -2, -2, -2, -1, -2, 0, -2, 1, -2, 2, -2, 3, -2,
+ 4, -2, 5, -2, 7, -2, 11, -2, -9, -1, -6, -1, -5, -1, -4, -1,
+ -3, -1, -2, -1, -1, -1, 0, -1, 1, -1, 2, -1, 3, -1, 4, -1,
+ 5, -1, 6, -1, 9, -1, -23, 0, -18, 0, -14, 0, -11, 0, -7, 0,
+ -5, 0, -4, 0, -3, 0, -2, 0, -1, 0, 0, -23, 1, 0, 2, 0,
+ 3, 0, 4, 0, 5, 0, 7, 0, 11, 0, 14, 0, 18, 0, 23, 0,
+ -9, 1, -6, 1, -5, 1, -4, 1, -3, 1, -2, 1, -1, 1, 0, 1,
+ 1, 1, 2, 1, 3, 1, 4, 1, 5, 1, 6, 1, 9, 1, -11, 2,
+ -7, 2, -5, 2, -4, 2, -3, 2, -2, 2, -1, 2, 0, 2, 1, 2,
+ 2, 2, 3, 2, 4, 2, 5, 2, 7, 2, 11, 2, -8, 3, -6, 3,
+ -4, 3, -3, 3, -2, 3, -1, 3, 0, 3, 1, 3, 2, 3, 3, 3,
+ 4, 3, 6, 3, 8, 3, -13, 4, -10, 4, -5, 4, -3, 4, -2, 4,
+ -1, 4, 0, 4, 1, 4, 2, 4, 3, 4, 5, 4, 10, 4, 13, 4,
+ -17, 5, -7, 5, -4, 5, -2, 5, -1, 5, 0, 5, 1, 5, 2, 5,
+ 4, 5, 7, 5, 17, 5, -22, 6, -9, 6, -6, 6, -3, 6, -1, 6,
+ 1, 6, 3, 6, 6, 6, 9, 6, 22, 6, -5, 7, -2, 7, 0, 7,
+ 2, 7, 5, 7, -11, 8, -8, 8, -3, 8, 0, 8, 3, 8, 8, 8,
+ 11, 8, -6, 9, -1, 9, 1, 9, 6, 9, -15, 10, -4, 10, 4, 10,
+ 15, 10, -8, 11, -2, 11, 0, 11, 2, 11, 8, 11, 19, 12, -19, 13,
+ -4, 13, 4, 13, 0, 14, -10, 15, 10, 15, -5, 17, 5, 17, 0, 18,
+ -12, 19, 13, 19, -6, 22, 6, 22, 0, 23,
+ };
+
+ if (_tableLastPitch == pitch && _tableLastIndex == index)
+ return;
+#ifdef DEBUG_CODEC37
+ debug(7, "codec37::maketable(%d, %d) called", pitch, index);
+#endif
+ _tableLastPitch = pitch;
+ _tableLastIndex = index;
+ index *= 255;
+ assert(index + 254 < (int)(sizeof(maketable_bytes) / 2));
+
+ for (int i = 0; i < 255; i++) {
+ int j = (i + index) << 1; // * 2
+ _offsetTable[i] = maketable_bytes[j + 1] * pitch + maketable_bytes[j];
+ }
+}
+
+void Codec37Decoder::proc1(Blitter & dst, Chunck & src, int next_offs, int bw, int bh, int size) {
+ unsigned char * decoded = new unsigned char[size];
+ int w = 0;
+ while(!src.eof()) {
+ int code = src.getByte();
+ int length = (code >> 1) + 1;
+ if (code & 1) {
+ unsigned char val = src.getByte();
+ while(length--)
+ decoded[w++] = val;
+ } else {
+ while(length--) {
+ decoded[w++] = src.getByte();
+ }
+ }
+ }
+ assert(w == size);
+ w = 0;
+ // Now we have our stream ready...
+ for(int i = 0; i < size; i++) {
+ if(decoded[i] == 0xFF) {
+ dst.putBlock(decoded + i + 1);
+ i += 16;
+ } else {
+ dst.blockCopy(_offsetTable[decoded[i]] + next_offs);
+ }
+ if(++w == bw) {
+ w = 0;
+ dst.advance(0, 3);
+ }
+ }
+ delete []decoded;
+}
+
+void Codec37Decoder::proc2(Blitter & dst, Chunck & src, int size) { // This is codec1 like...
+#ifdef DEBUG_CODEC37_PROC2
+ int decoded_size = 0;
+ int coded_size = 0;
+#endif
+ do {
+ int code = src.getByte();
+ int length = (code >> 1) + 1;
+ size -= length;
+#ifdef DEBUG_CODEC37_PROC2
+ decoded_size += length;
+ coded_size += 1 + ((code & 1) ? 1 : length);
+
+ debug(7, "proc2() : code == %d : length == %d : decoded_size == %d : coded_size == %d : seek - header == %d : size == %d",
+ code, length, decoded_size, coded_size, src.tell() - 31, size + decoded_size);
+#endif
+ if (code & 1)
+ dst.put(src.getChar(), length);
+ else
+ // while(length--) dst.put(src.get_char());
+ dst.blit(src, length);
+ } while (size);
+}
+
+void Codec37Decoder::proc3WithFDFE(Blitter & dst, Chunck & src, int next_offs, int bw, int bh) {
+ do {
+ int i = bw;
+ do {
+ int code = src.getByte();
+ if (code == 0xFD) {
+#ifdef USE_COLOR_CODE_FOR_BLOCK
+ dst.putBlock(expand(1));
+#else
+ dst.putBlock(expand(src.getByte()));
+#endif
+ } else if (code == 0xFE) {
+#ifdef USE_COLOR_CODE_FOR_BLOCK
+ dst.putBlock(expand(2));
+#else
+ dst.putBlock(expand(src.getByte()), expand(src.getByte()), expand(src.getByte()), expand(src.getByte()));
+#endif
+ } else if (code == 0xFF) {
+#ifdef USE_COLOR_CODE_FOR_BLOCK
+ dst.putBlock(expand(3));
+#else
+ dst.putBlock(src);
+#endif
+ } else {
+#ifdef USE_COLOR_CODE_FOR_BLOCK
+ dst.putBlock(expand(4));
+#else
+ dst.blockCopy(_offsetTable[code] + next_offs); // copy from an offset !
+#endif
+ }
+ } while (--i);
+ dst.advance(0, 3); // advance 3 lines
+ } while (--bh);
+}
+
+void Codec37Decoder::proc3WithoutFDFE(Blitter & dst, Chunck & src, int next_offs, int bw, int bh) {
+ do {
+ int i = bw;
+ do {
+ int code = src.getByte();
+ if (code == 0xFF) {
+#ifdef USE_COLOR_CODE_FOR_BLOCK
+ dst.putBlock(expand(5));
+#else
+ dst.putBlock(src);
+#endif
+ } else {
+#ifdef USE_COLOR_CODE_FOR_BLOCK
+ dst.putBlock(expand(6));
+#else
+ dst.blockCopy(_offsetTable[code] + next_offs); // copy from an offset !
+#endif
+ }
+ } while (--i);
+ dst.advance(0, 3); // advance 3 lines
+ } while (--bh);
+}
+
+void Codec37Decoder::proc4(Blitter & dst, Chunck & src, int next_offs, int bw, int bh) {
+#ifdef DEBUG_CODEC37_PROC4
+ int b_nb = 0;
+#endif
+ do {
+ int i = bw;
+ do {
+ int code = src.getByte();
+ if (code == 0xFD) {
+#ifdef USE_COLOR_CODE_FOR_BLOCK
+ dst.putBlock(expand(7));
+#else
+ dst.putBlock(expand(src.getByte()));
+#endif
+ } else if (code == 0xFE) {
+#ifdef USE_COLOR_CODE_FOR_BLOCK
+ dst.putBlock(expand(8));
+#else
+ dst.putBlock(expand(src.getByte()), expand(src.getByte()), expand(src.getByte()), expand(src.getByte()));
+#endif
+ } else if (code == 0xFF) {
+#ifdef USE_COLOR_CODE_FOR_BLOCK
+ dst.putBlock(expand(9));
+#else
+ dst.putBlock(src);
+#endif
+ } else if (code == 0x00) {
+ int length = src.getByte() + 1;
+ for (int l = 0; l < length; l++) {
+#ifdef USE_COLOR_CODE_FOR_BLOCK
+ dst.putBlock(expand(10));
+#else
+ dst.blockCopy(next_offs);
+#endif
+ i--;
+ if (i == 0) {
+ dst.advance(0, 3); // advance 3 lines
+ bh--;
+ i = bw;
+ }
+ }
+ if(bh == 0) return;
+ i++;
+ } else {
+#ifdef USE_COLOR_CODE_FOR_BLOCK
+ dst.putBlock(expand(11));
+#else
+ dst.blockCopy(_offsetTable[code] + next_offs); // copy from an offset !
+#endif
+ }
+ } while (--i);
+ dst.advance(0, 3); // advance 3 lines
+ } while (--bh);
+}
+
+bool Codec37Decoder::decode(Blitter & dst, Chunck & src) {
+ int width = getRect().width();
+ int height = getRect().height();
+ int bw = (width + 3) >> 2, bh = (height + 3) >> 2;
+ int pitch = bw << 2;
+#ifdef DEBUG_CODEC37
+ debug(7, "codec37::decode() : width == %d : height == %d : pitch == %d : _prevSeqNb == %d",
+ width, height, pitch, _prevSeqNb);
+#endif
+ int code = src.getByte(); // 0 -> 1 (1)
+ int index = src.getByte(); // 1 -> 2 (1)
+ unsigned short seq_nb = src.getWord(); // 2 -> 4 (2)
+ unsigned int decoded_size = src.getDword(); // 4 -> 8 (4)
+#ifdef DEBUG_CODEC37
+ unsigned int coded_size = src.getDword(); // 8 -> 12 (4)
+#else
+ src.seek(4);
+#endif
+ unsigned int mask_flag = src.getDword(); // 12 -> 16 (4)
+#ifdef DEBUG_CODEC37
+ debug(7, "codec37::decode() : code == %d : index == %d : seq_nb == %d : decoded_size == %d : coded_size == %d : mask_flag == %d",
+ code, index, seq_nb, decoded_size, coded_size, mask_flag);
+#endif
+ maketable(pitch, index);
+ if(code == 3 || code == 4 || code == 1) {
+ assert(seq_nb && _prevSeqNb + 1 == seq_nb);
+ if (seq_nb & 1 || !(mask_flag & 1)) _curtable ^= 1;
+ }
+ Blitter blit((char *)_deltaBufs[_curtable], Point(width, height), Rect(0, 0, width, height));
+ switch(code) {
+ case 0:
+ memset(_deltaBuf, 0, _deltaBufs[_curtable] - _deltaBuf);
+ memset(_deltaBufs[_curtable] + decoded_size, 0, _deltaBuf + _deltaSize - _deltaBufs[_curtable] - decoded_size);
+ blit.blit(src, decoded_size);
+ break;
+ case 1:
+ proc1(blit, src, _deltaBufs[_curtable ^ 1] - _deltaBufs[_curtable], bw, bh, decoded_size);
+ break;
+ case 2:
+ memset(_deltaBuf, 0, _deltaBufs[_curtable] - _deltaBuf);
+ memset(_deltaBufs[_curtable] + decoded_size, 0, _deltaBuf + _deltaSize - _deltaBufs[_curtable] - decoded_size);
+ proc2(blit, src, decoded_size);
+ break;
+ case 3:
+ if(mask_flag & 1)
+ proc3WithFDFE(blit, src, _deltaBufs[_curtable ^ 1] - _deltaBufs[_curtable], bw, bh);
+ else
+ proc3WithoutFDFE(blit, src, _deltaBufs[_curtable ^ 1] - _deltaBufs[_curtable], bw, bh);
+ break;
+ case 4:
+ proc4(blit, src, _deltaBufs[_curtable ^ 1] - _deltaBufs[_curtable], bw, bh);
+ break;
+ default:
+#ifdef DEBUG_CODEC37
+ error("codec37::decode() received an invalid code : %d", code);
+#endif
+ break;
+ }
+ dst.blit((char*)_deltaBufs[_curtable], width * height);
+ _prevSeqNb = seq_nb;
+ return true;
+}
+
diff --git a/scumm/smush/codec37.h b/scumm/smush/codec37.h
new file mode 100644
index 0000000000..65fd7c1195
--- /dev/null
+++ b/scumm/smush/codec37.h
@@ -0,0 +1,86 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2001/2002 The ScummVM project
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ *
+ */
+
+#ifndef __CODEC37_H_
+#define __CODEC37_H_
+
+#include "config.h"
+
+#ifdef DEBUG
+# ifndef NO_DEBUG_CODEC37
+# define DEBUG_CODEC37
+# endif
+#else
+# ifdef DEBUG_CODEC37
+# error DEBUG_CODEC37 defined without DEBUG
+# endif
+#endif
+
+#ifdef DEBUG_CODEC37
+# ifndef NO_DEBUG_CODEC37_PROCS
+# define DEBUG_CODEC37_PROC1
+# define DEBUG_CODEC37_PROC2
+# define DEBUG_CODEC37_PROC3
+# define DEBUG_CODEC37_PROC4
+# endif
+#endif
+
+#include "decoder.h"
+
+/*! @brief ::decoder for codec 37.
+
+*/
+
+#define DELTA_ADD 0x3E00 // what is this 0x3E00 ?? == 320*200/4 - 128
+ // It looks like it is a safe-guarding protection from bugs., but maybe not...
+
+class Codec37Decoder : public Decoder {
+private:
+ int _deltaSize;
+ unsigned char * _deltaBufs[2];
+ unsigned char * _deltaBuf;
+ short * _offsetTable;
+ int _curtable;
+ unsigned short _prevSeqNb;
+ int _tableLastPitch;
+ int _tableLastIndex;
+
+public:
+ bool initSize(const Point &, const Rect &);
+ Codec37Decoder();
+ void clean();
+ virtual ~Codec37Decoder();
+protected:
+ static inline unsigned int expand(unsigned char b) {
+ unsigned int r = b | (b << 8);
+ return r | (r << 16);
+ }
+ void maketable(int, int);
+ void proc1(Blitter &, Chunck &, int, int, int, int);
+ void proc2(Blitter &, Chunck &, int);
+ void proc3WithFDFE(Blitter &, Chunck &, int, int, int);
+ void proc3WithoutFDFE(Blitter &, Chunck &, int, int, int);
+ void proc4(Blitter &, Chunck &, int, int, int);
+public:
+ bool decode(Blitter &, Chunck &);
+};
+
+#endif
diff --git a/scumm/smush/codec44.cpp b/scumm/smush/codec44.cpp
new file mode 100644
index 0000000000..9795842e76
--- /dev/null
+++ b/scumm/smush/codec44.cpp
@@ -0,0 +1,71 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2001/2002 The ScummVM project
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ *
+ */
+
+#include <stdafx.h>
+#include "codec44.h"
+#include "chunck.h"
+#include "blitter.h"
+
+bool Codec44Decoder::decode(Blitter & dst, Chunck & src) {
+ int size_line;
+ int num;
+ int w, width = getRect().width() + 1;
+ int h, height = getRect().height() + 1;
+ bool zero;
+#ifdef DEBUG_CODEC44
+ debug(7, "codec44 : %dx%d", width, height);
+#endif
+
+ for(h = 0; h < height - 1; h++) {
+ w = width;
+ size_line = src.getWord(); // size of compressed line !
+#ifdef DEBUG_CODEC44
+ debug(7, "codec44 : h == %d, size_line == %d", h, size_line);
+#endif
+ zero = true;
+ while(size_line > 1) {
+ num = src.getWord();
+ size_line -= 2;
+ if(zero) {
+#ifdef DEBUG_CODEC44
+ debug(7, "codec44 : zeroing %d, entries", num);
+#endif
+ if(w == num)
+ num--;
+ w -= num;
+ if(num)
+ dst.put(0, num);
+ } else {
+ num += 1;
+#ifdef DEBUG_CODEC44
+ debug(7, "codec44 : blitting %d, entries", num);
+#endif
+ if(w == num)
+ num--;
+ w -= num;
+ dst.blit(src, num);
+ size_line -= num;
+ }
+ zero = !zero;
+ }
+ }
+ return true;
+}
diff --git a/scumm/smush/codec44.h b/scumm/smush/codec44.h
new file mode 100644
index 0000000000..a7c39b02fb
--- /dev/null
+++ b/scumm/smush/codec44.h
@@ -0,0 +1,47 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2001/2002 The ScummVM project
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ *
+ */
+
+#ifndef __CODEC44_H_
+#define __CODEC44_H_
+
+#include "config.h"
+
+#ifdef DEBUG
+# ifndef NO_DEBUG_CODEC44
+# define DEBUG_CODEC44
+# endif
+#else
+# ifdef DEBUG_CODEC44
+# error DEBUG_CODEC44 defined without DEBUG
+# endif
+#endif
+
+#include "decoder.h"
+
+/*! @brief ::decoder for codec 21 and 44.
+
+*/
+class Codec44Decoder : public Decoder {
+public:
+ bool decode(Blitter & dst, Chunck & src);
+};
+
+#endif
diff --git a/scumm/smush/codec47.cpp b/scumm/smush/codec47.cpp
new file mode 100644
index 0000000000..88038bb94d
--- /dev/null
+++ b/scumm/smush/codec47.cpp
@@ -0,0 +1,51 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2001/2002 The ScummVM project
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ *
+ */
+
+#include <stdafx.h>
+#include "codec47.h"
+#include "chunck.h"
+#include "blitter.h"
+
+DumpDecoder::~DumpDecoder() {
+}
+
+bool DumpDecoder::decode(Blitter & dst, Chunck & src) {
+ int n = 0, i = 0;
+ int seq = src.getWord();
+ int codec = src.getByte();
+ int flags = src.getByte();
+ int unknown[22];
+ for(i = 0; i < 0; i++) {
+ unknown[i] = src.getByte();
+ }
+ if(codec == 5 || codec == 1) {
+ do {
+ int code = src.getByte();
+ int length = (code >> 1) + 1;
+ if (code & 1)
+ dst.put(src.getChar(), length);
+ else
+ dst.blit(src, length);
+ } while (!src.eof());
+ }
+
+ return true;
+}
diff --git a/scumm/smush/codec47.h b/scumm/smush/codec47.h
new file mode 100644
index 0000000000..ecf34f7e70
--- /dev/null
+++ b/scumm/smush/codec47.h
@@ -0,0 +1,38 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2001/2002 The ScummVM project
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ *
+ */
+
+#ifndef __CODEC_47_H_
+#define __CODEC_47_H_
+
+#include "config.h"
+
+#include "decoder.h"
+
+/*! @brief ::decoder for debugging purpose.
+
+*/
+class DumpDecoder : public Decoder {
+public:
+ virtual ~DumpDecoder();
+ bool decode(Blitter &, Chunck &);
+};
+
+#endif
diff --git a/scumm/smush/color.cpp b/scumm/smush/color.cpp
new file mode 100644
index 0000000000..e88785ccbd
--- /dev/null
+++ b/scumm/smush/color.cpp
@@ -0,0 +1,69 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2001/2002 The ScummVM project
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ *
+ */
+
+#include <stdafx.h>
+#include "color.h"
+
+Color::Color() : _r(0), _g(0), _b(0) {
+}
+
+Color::Color(value_type r, value_type g, value_type b) : _r(r), _g(g), _b(b) {
+}
+
+Color::Color(const Color & c) : _r(c._r), _g(c._g), _b(c._b) {
+}
+
+Color & Color::operator=(const Color & c) {
+ _r = c._r;
+ _g = c._g;
+ _b = c._b;
+ return *this;
+}
+
+Color::~Color() {
+}
+
+Color::value_type Color::red() const {
+ return _r;
+}
+
+Color::value_type Color::green() const {
+ return _g;
+}
+
+Color::value_type Color::blue() const {
+ return _b;
+}
+
+void Color::delta(short * ptr) {
+ // This is a very specific method for XPALs.
+ int t;
+#define UPDATE_COLOR(c, inc) (((int)((c)) << 7) + (c) + (inc)) >> 7
+#define CHECK_BOUNDS(c) (((c) > 255) ? 255 : (((c) < 0) ? 0 : (c)))
+ t = UPDATE_COLOR(_r, ptr[0]);
+ _r = CHECK_BOUNDS(t);
+ t = UPDATE_COLOR(_g, ptr[1]);
+ _g = CHECK_BOUNDS(t);
+ t = UPDATE_COLOR(_b, ptr[2]);
+ _b = CHECK_BOUNDS(t);
+#undef UPDATE_COLOR
+#undef CHECK_BOUNDS
+}
diff --git a/scumm/smush/color.h b/scumm/smush/color.h
new file mode 100644
index 0000000000..00c8978162
--- /dev/null
+++ b/scumm/smush/color.h
@@ -0,0 +1,57 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2001/2002 The ScummVM project
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ *
+ */
+
+#ifndef __COLOR_H_
+#define __COLOR_H_
+
+#include "config.h"
+
+/*! @brief simple class for handling a color.
+
+ This small class is an helper for colors.
+*/
+class Color {
+public:
+ typedef unsigned char value_type; //!< The type of the color components.
+private:
+ value_type _r; //!< The red component.
+ value_type _g; //!< The green component.
+ value_type _b; //!< The blue component.
+public:
+ Color();
+ Color(value_type, value_type, value_type);
+ Color(const Color &);
+ Color & operator=(const Color &);
+ virtual ~Color();
+ value_type red() const;
+ value_type green() const;
+ value_type blue() const;
+ /*! @brief handle delta palette modification
+
+ This method is used specifically by player::handleDeltaPalette().
+ It updates the color component using delta values given as short.
+
+ @param ptr pointer to a table of 3 shorts that contain delta values to use.
+ */
+ void delta(short * ptr);
+};
+
+#endif
diff --git a/scumm/smush/config.h b/scumm/smush/config.h
new file mode 100644
index 0000000000..4734413f2e
--- /dev/null
+++ b/scumm/smush/config.h
@@ -0,0 +1,42 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2001/2002 The ScummVM project
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ *
+ */
+
+#ifndef __CONFIG_H_
+#define __CONFIG_H_
+
+#include <stdafx.h>
+#include <scumm.h>
+
+#ifndef NDEBUG
+#define DEBUG
+#endif
+
+//~ #define NO_DEBUG_MIXER
+//~ #define NO_DEBUG_CHANNEL
+//~ #define NO_DEBUG_CLIPPER
+#define NO_DEBUG_CODEC1
+#define NO_DEBUG_CODEC37
+#define NO_DEBUG_CODEC44
+//~ #define NO_DEBUG_WIN32
+//~ #define NO_DEBUG_FONT_RENDERER
+
+
+#endif
diff --git a/scumm/smush/decoder.h b/scumm/smush/decoder.h
new file mode 100644
index 0000000000..a216d2b6b1
--- /dev/null
+++ b/scumm/smush/decoder.h
@@ -0,0 +1,51 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2001/2002 The ScummVM project
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ *
+ */
+
+#ifndef __DECODER_H_
+#define __DECODER_H_
+
+#include "config.h"
+
+#include "rect.h"
+
+class Blitter;
+class Chunck;
+
+/*! @brief base class for codec decompression.
+
+ This class provides an interface for codec decompression.
+
+*/
+class Decoder {
+private:
+ Rect _r; //!< current size of the frame object to decode
+ Point _p; //!< position of the frame object to decode
+protected:
+ const Rect & getRect() const{ return _r; }
+ const Point & getSize() const { return _p; }
+public:
+ Decoder() {};
+ virtual ~Decoder() {};
+ virtual bool initSize(const Point & p, const Rect & r) { _p = p; _r = r; return true; };
+ virtual bool decode(Blitter &, Chunck &) = 0;
+};
+
+#endif
diff --git a/scumm/smush/frenderer.cpp b/scumm/smush/frenderer.cpp
new file mode 100644
index 0000000000..7f3f08cae8
--- /dev/null
+++ b/scumm/smush/frenderer.cpp
@@ -0,0 +1,232 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2001/2002 The ScummVM project
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ *
+ */
+
+#include <stdafx.h>
+#include "frenderer.h"
+#include "rect.h"
+
+#include <assert.h>
+#include <string.h> // for memcpy, strcat, strdup
+
+#ifndef max
+#define max(x, y) ((x) > (y) ? (x) : (y))
+#endif
+
+FontRenderer::FontRenderer(bool use_original_colors) : _nbChars(0), _color(-1), _original(use_original_colors) {
+}
+
+FontRenderer::~FontRenderer() {
+ for(int i = 0; i < _nbChars; i++) {
+ if(_chars[i].chr) delete []_chars[i].chr;
+ }
+}
+
+void FontRenderer::save(int frame) {
+ _chars[_nbChars].width = getWidth();
+ _chars[_nbChars].height = getHeight();
+ int size = getWidth() * getHeight();
+ _chars[_nbChars].chr = new char[size];
+ memcpy(_chars[_nbChars].chr, data(), size);
+ _nbChars++;
+}
+
+int FontRenderer::charWidth(int v) const {
+ if(v < 0) v = 256 + v;
+ if(v < 0 || v >= _nbChars) error("invalid character in FontRenderer::charWidth : %d (%d)", v, _nbChars);
+ return _chars[v].width;
+}
+
+int FontRenderer::charHeight(int v) const {
+ if(v < 0) v = 256 + v;
+ if(v < 0 || v >= _nbChars) error("invalid character in FontRenderer::charHeight : %d (%d)", v, _nbChars);
+ return _chars[v].height;
+}
+
+int FontRenderer::stringWidth(const char * str) const {
+ int ret = 0;
+
+ while(*str) {
+ ret += charWidth(*str++);
+ }
+
+ return ret;
+}
+
+int FontRenderer::stringHeight(const char * str) const {
+ int ret = 0;
+
+ for(int i = 0; str[i] != 0; i++) {
+ int h = charHeight(str[i]);
+ ret = max(ret, h);
+ }
+
+ return ret;
+}
+
+int FontRenderer::drawChar(char * buffer, const Point & size, int x, int y, int chr) const {
+ int w = _chars[chr].width;
+ int h = _chars[chr].height;
+ char * src = _chars[chr].chr;
+ char * dst = buffer + size.getX() * y + x;
+
+ if(_original) {
+ for(int j = 0; j < h; j++) {
+ for(int i = 0; i < w; i++) {
+ int value = *src++;
+ if(value) dst[i] = value;
+ }
+ dst += size.getX();
+ }
+ } else {
+ int color = (_color != -1) ? _color : 1;
+ for(int j = 0; j < h; j++) {
+ for(int i = 0; i < w; i++) {
+ int value = *src++;
+ if(value == 1) {
+ dst[i] = color;
+ } else if(value) {
+ dst[i] = 0;
+ }
+ }
+ dst += size.getX();
+ }
+ }
+ return w;
+}
+
+static char * * split(const char * str, char sep) {
+ char * * ret = new char *[32];
+ int n = 0;
+ const char * i = str, * j = strchr(i, sep);
+
+ while(j != NULL) {
+ assert(n < 30);
+ ret[n] = new char[j - i + 1];
+ memcpy(ret[n], i, j - i);
+ ret[n++][j - i] = 0;
+ i = j+1;
+ j = strchr(i, sep);
+ }
+
+ ret[n] = new char[strlen(i) + 1];
+ memcpy(ret[n], i, strlen(i));
+ ret[n++][strlen(i)] = 0;
+ ret[n] = 0;
+ return ret;
+}
+
+void FontRenderer::drawSubstring(const unsigned char * str, char * buffer, const Point & size, int x, int y) const {
+ for(int i = 0; str[i] != 0; i++)
+ x += drawChar(buffer, size, x, y, str[i]);
+}
+
+bool FontRenderer::drawStringAbsolute(const char * str, char * buffer, const Point & size, int x, int y) const {
+ debug(9, "FontRenderer::drawStringAbsolute(%s, %d, %d)", str, x, y);
+ while(str) {
+ char line[256];
+ char * pos = strchr(str, '\n');
+ if(pos) {
+ memcpy(line, str, pos - str - 1);
+ line[pos - str - 1] = 0;
+ str = pos + 1;
+ } else {
+ strcpy(line, str);
+ str = 0;
+ }
+ drawSubstring((const unsigned char *)line, buffer, size, x, y);
+ y += stringHeight(line);
+ }
+ return true;
+}
+
+bool FontRenderer::drawStringCentered(const char * str, char * buffer, const Point & size, int y, int xmin, int width, int offset) const {
+ debug(9, "FontRenderer::drawStringCentered(%s, %d, %d)", str, xmin, y);
+ assert(strchr(str, '\n') == 0);
+ char * * words = split(str, ' ');
+ int nb_sub = 0;
+
+ while(words[nb_sub]) nb_sub++;
+
+ int * sizes = new int[nb_sub];
+ int i = 0, max_width = 0, height = 0, nb_subs = 0;
+
+ for(i = 0; i < nb_sub; i++)
+ sizes[i] = stringWidth(words[i]);
+
+ char * * substrings = new char *[nb_sub];
+ int * substr_widths = new int[nb_sub];
+ int space_width = charWidth(' ');
+
+ while(i < nb_sub) {
+ int substr_width = sizes[i];
+ char * substr = new char[1000];
+ strcpy(substr, words[i]);
+ int j = i + 1;
+
+ while(j < nb_sub && (substr_width + space_width + sizes[j]) < width) {
+ substr_width += sizes[j++] + space_width;
+ }
+
+ for(int k = i + 1; k < j; k++) {
+ strcat(substr, " ");
+ strcat(substr, words[k]);
+ }
+
+ substrings[nb_subs] = substr;
+ substr_widths[nb_subs++] = substr_width;
+ if(substr_width > max_width)
+ max_width = substr_width;
+ i = j;
+ height += stringHeight(substr);
+ }
+
+ delete []sizes;
+ for(i = 0; i < nb_sub; i++) {
+ delete []words[i];
+ }
+ delete []words;
+
+ max_width = (max_width + 1) >> 1;
+ // we have a box from 0 -> max_width
+ // we want a box from (xmin + offset) - max_width / 2, (xmin + offset) + max_width / 2
+ int x = xmin + width / 2;
+ x += offset - size.getX() / 2;
+
+ if(x < max_width) x = max_width;
+ if(x + max_width > size.getX()) {
+ x = size.getX() - max_width;
+ }
+
+ if(y + height > size.getY()) {
+ y = size.getY() - height;
+ }
+
+ for(i = 0; i < nb_subs; i++) {
+ int substr_width = substr_widths[i];
+ drawSubstring((const unsigned char *)substrings[i], buffer, size, x - substr_width / 2, y);
+ y += stringHeight(substrings[i]);
+ delete []substrings[i];
+ }
+
+ delete []substr_widths;
+ delete []substrings;
+ return true;
+}
diff --git a/scumm/smush/frenderer.h b/scumm/smush/frenderer.h
new file mode 100644
index 0000000000..2ed9cd98cc
--- /dev/null
+++ b/scumm/smush/frenderer.h
@@ -0,0 +1,164 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2001/2002 The ScummVM project
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ *
+ */
+
+#ifndef __FRENDERER_H_
+#define __FRENDERER_H_
+
+#include "config.h"
+
+#ifdef DEBUG
+# ifndef NO_DEBUG_FONT_RENDERER
+# define DEBUG_FONT_RENDERER
+# endif
+#else
+# ifdef DEBUG_FONT_RENDERER
+# error DEBUG_FONT_RENDERER defined without DEBUG
+# endif
+#endif
+
+#include "brenderer.h"
+#include "rect.h"
+#include "blitter.h"
+
+/*! @brief ::renderer implementation specifically designed for font files.
+
+ This class is a valid ::renderer implementation. The frames are kept in memory, as bitmap representing characters, so that
+ they can be rendered again in another frame as strings.
+
+ This class also contains some functions useful for printing strings. This is used to show subtitles and more generally texts
+ in animations.
+
+ @todo update the mehod to use the ::blitter class, instead of direct pointers.
+*/
+class FontRenderer : public BaseRenderer {
+private:
+ int _nbChars; //!< The number of frames in the font
+ int _color; //!< A color parameter used for font printing.
+ bool _original; //!< flag for color selection
+ struct {
+ int width;
+ int height;
+ char * chr;
+ } _chars[256]; //!< array that contains the size of the different frames (i.e. characters) of the font.
+public:
+ /*! @brief font_renderer constructor
+
+ @param use_original_colors flag to indicate if the font use it's own color, or if the base color are set at runtime.
+ */
+ FontRenderer(bool use_original_colors = false);
+ virtual ~FontRenderer();
+ virtual bool wait(int ms) { return true; };
+protected:
+ virtual void save(int frame = -1);
+ /*! @brief get the width of a character.
+
+ @param c the character we want the width from.
+
+ @return the width of the character
+ */
+ int charWidth(int c) const;
+ /*! @brief get the width of a string.
+
+ @param str the string we want the width from.
+
+ @return the complete width of the string
+ */
+ int stringWidth(const char * str) const;
+ /*! @brief get the height of a character.
+
+ @param c the character we want the height from.
+
+ @return the height of the character
+ */
+ int charHeight(int c) const;
+ /*! @brief get the height of a string.
+
+ @param str the string we want the height from.
+
+ @return the complete height of the string
+ */
+ int stringHeight(const char * str) const;
+ /*! @brief draw a character in the given frame buffer.
+
+ @param buffer the frame buffer to draw into.
+ @param size the size of the frame buffer.
+ @param x the horizontal position of the topleft corner of the character.
+ @param y the vertical position of the topleft corner of the character.
+ @param c the character to draw.
+
+ @bug This method does not clip. This is not really a bug, as it should always be correctly called, but some asserts would be welcome.
+
+ @return the width of the character
+ */
+ int drawChar(char * buffer, const Point & size, int x, int y, int c) const;
+ /*! @brief draw a string in the given frame buffer.
+
+ @param str the string to draw.
+ @param buffer the frame buffer to draw into.
+ @param size the size of the frame buffer.
+ @param x the horizontal position of the topleft corner of the string.
+ @param y the vertical position of the topleft corner of the string.
+
+ @bug This method does not clip. This is not really a bug, as it should always be correctly called, but some asserts would be welcome.
+ */
+ void drawSubstring(const unsigned char * str, char * buffer, const Point & size, int x, int y) const;
+public:
+ /*! @brief change the programmable color of the font.
+
+ @param c the new color to use.
+
+ @return \c true if everything went fine, \c false otherwise
+ */
+ bool setColor(int c) { _color = c; return true; }
+ /*! @brief draw a centered and possibly using multiple lines string.
+
+ This method performs calculation of the string size before choosing where to draw it.
+ As I still not have figured out exactly what is the meaning of the fields in the TRES chunck,
+ the real meaning of the parameters can be quite difficult to understand.
+
+ @remark The current implementation is incorrect in the sense that it does not conform to the original game.
+ @todo rewrite and rethink this to better match the original implementation.
+
+ @param str the string to draw.
+ @param buffer the frame buffer to draw into.
+ @param size the size of the frame buffer.
+ @param y the vertical position of the topleft corner of the string. This position may be changed if it is too low to be correctly drawn.
+ @param xmin the minimum horizontal position of the topleft corner of the string.
+ @param width the maximum width of the string. If the string is too long, it will wrap.
+ @param offset offset to give to the horizontal position.
+
+ @return \c true if everything went fine, \c false otherwise
+ */
+ bool drawStringCentered(const char * str, char * buffer, const Point & size, int y, int xmin, int width, int offset) const;
+ /*! @brief draw a string at an absolute position.
+
+ @param str the string to draw.
+ @param buffer the frame buffer to draw into.
+ @param size the size of the frame buffer.
+ @param x the horizontal position of the topleft corner of the string.
+ @param y the vertical position of the topleft corner of the string. This position may be changed if it is too low to be correctly drawn.
+
+ @return \c true if everything went fine, \c false otherwise
+ */
+ bool drawStringAbsolute(const char * str, char * buffer, const Point & size, int x, int y) const;
+};
+
+#endif
diff --git a/scumm/smush/imuse_channel.cpp b/scumm/smush/imuse_channel.cpp
new file mode 100644
index 0000000000..f082407abd
--- /dev/null
+++ b/scumm/smush/imuse_channel.cpp
@@ -0,0 +1,329 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2001/2002 The ScummVM project
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ *
+ */
+
+#include <stdafx.h>
+#include "channel.h"
+#include "chunck.h"
+#include "chunck_type.h"
+
+#include <assert.h>
+#include <string.h> // for memcpy.h
+#ifndef min
+#define min(x, y) ((x) > (y) ? (y) : (x))
+#endif
+
+ImuseChannel::ImuseChannel(int track, int freq) :
+ _track(track),
+ _tbuffer(0),
+ _tbufferSize(0),
+ _sbuffer(0),
+ _sbufferSize(0),
+ _frequency(freq),
+ _dataSize(-1),
+ _inData(false) {
+}
+
+ImuseChannel::~ImuseChannel() {
+ if(_tbuffer) {
+ delete []_tbuffer;
+ }
+ if(_sbuffer) {
+ warning("_sbuffer should be 0 !!!");
+ delete []_sbuffer;
+ }
+}
+
+bool ImuseChannel::isTerminated() const {
+ return (_dataSize <= 0 && _sbuffer == 0);
+}
+
+bool ImuseChannel::setParameters(int nbframes, int size, int unk1, int unk2) {
+ return true;
+}
+
+bool ImuseChannel::checkParameters(int index, int nbframes, int size, int unk1, int unk2) {
+ return true;
+}
+
+bool ImuseChannel::appendData(Chunck & b, int size) {
+ if(_dataSize == -1) { // First call
+ assert(size > 8);
+ Chunck::type imus_type = b.getDword(); imus_type = TO_BE_32(imus_type);
+ unsigned int imus_size = b.getDword(); imus_size = TO_BE_32(imus_size);
+ if(imus_type != TYPE_iMUS) error("Invalid CHUNCK for imuse_channel");
+ size -= 8;
+ _tbufferSize = size;
+ assert(_tbufferSize);
+ _tbuffer = new unsigned char[_tbufferSize];
+ if(!_tbuffer) error("imuse_channel failed to allocate memory");
+ b.read(_tbuffer, size);
+ _dataSize = -2; // even if _in_data does not get set, this won't be called again
+ } else {
+ if(_tbuffer) { // remaining from last call
+ unsigned char * old = _tbuffer;
+ int new_size = size + _tbufferSize;
+ _tbuffer = new unsigned char[new_size];
+ if(!_tbuffer) error("imuse_channel failed to allocate memory");
+ memcpy(_tbuffer, old, _tbufferSize);
+ delete []old;
+ b.read(_tbuffer + _tbufferSize, size);
+ _tbufferSize += size;
+ } else {
+ _tbufferSize = size;
+ _tbuffer = new unsigned char[_tbufferSize];
+ if(!_tbuffer) error("imuse_channel failed to allocate memory");
+ b.read(_tbuffer, size);
+ }
+ }
+ return processBuffer();
+}
+
+bool ImuseChannel::handleFormat(Chunck & src) {
+ if(src.getSize() != 20) error("invalid size for FRMT chunck");
+ unsigned imuse_start = src.getDword();
+ imuse_start = TO_BE_32(imuse_start);
+ src.seek(4);
+ _bitsize = src.getDword();
+ _bitsize = TO_BE_32(_bitsize);
+ _rate = src.getDword();
+ _rate = TO_BE_32(_rate);
+ _channels = src.getDword();
+ _channels = TO_BE_32(_channels);
+ assert(_channels == 1 || _channels == 2);
+ return true;
+}
+
+bool ImuseChannel::handleText(Chunck & src) {
+ return true;
+}
+
+bool ImuseChannel::handleRegion(Chunck & src) {
+ if(src.getSize() != 8) error("invalid size for REGN chunck");
+ return true;
+}
+
+bool ImuseChannel::handleStop(Chunck & src) {
+ if(src.getSize() != 4) error("invalid size for STOP chunck");
+ return true;
+}
+
+bool ImuseChannel::handleMap(Chunck & map) {
+ while(!map.eof()) {
+ Chunck * sub = map.subBlock();
+ switch(sub->getType()) {
+ case TYPE_FRMT:
+ handleFormat(*sub);
+ break;
+ case TYPE_TEXT:
+ handleText(*sub);
+ break;
+ case TYPE_REGN:
+ handleRegion(*sub);
+ break;
+ case TYPE_STOP:
+ handleStop(*sub);
+ break;
+ default:
+ error("Unknown iMUS subchunck found : %s, %d", Chunck::ChunckString(sub->getType()), sub->getSize());
+ }
+ delete sub;
+ }
+ return true;
+}
+
+void ImuseChannel::decode() {
+ int remaining_size = _sbufferSize % 3;
+ if(remaining_size) {
+ _srbufferSize -= remaining_size;
+ assert(_inData);
+ if(_tbuffer == 0) {
+ _tbuffer = new unsigned char[remaining_size];
+ memcpy(_tbuffer, _sbuffer + _sbufferSize - remaining_size, remaining_size);
+ _tbufferSize = remaining_size;
+ _sbufferSize -= remaining_size;
+ } else {
+ warning("impossible ! : %p, %d, %d, %p(%d), %p(%d, %d)",
+ this, _dataSize, _inData, _tbuffer, _tbufferSize, _sbuffer, _sbufferSize, _srbufferSize);
+ unsigned char * old = _tbuffer;
+ int new_size = remaining_size + _tbufferSize;
+ _tbuffer = new unsigned char[new_size];
+ if(!_tbuffer) error("imuse_channel failed to allocate memory");
+ memcpy(_tbuffer, old, _tbufferSize);
+ delete []old;
+ memcpy(_tbuffer + _tbufferSize, _sbuffer + _sbufferSize - remaining_size, remaining_size);
+ _tbufferSize += remaining_size;
+ }
+ }
+ int loop_size = _sbufferSize / 3;
+ int new_size = loop_size * 2;
+ short * keep, * decoded;
+ keep = decoded = new short[new_size];
+ assert(keep);
+ unsigned char * source = _sbuffer;
+ while(loop_size--) {
+ int v1 = *source++;
+ int v2 = *source++;
+ int v3 = *source++;
+ int value = (((v2 & 0x0f) << 12) | (v1 << 4)) - 0x8000;
+ *decoded++ = (short)value;
+ value = (((v2 & 0xf0) << 8) | (v3 << 4)) - 0x8000;
+ *decoded++ = (short)value;
+ }
+ delete []_sbuffer;
+ _sbuffer = (unsigned char*)keep;
+ _sbufferSize = new_size * sizeof(short);
+}
+
+bool ImuseChannel::handleSubTags(int & offset) {
+ int available_size = _tbufferSize - offset;
+ if(available_size >= 8) {
+ Chunck::type type = READ_BE_UINT32(_tbuffer + offset);
+ unsigned int size = READ_BE_UINT32(_tbuffer + offset + 4);
+ switch(type) {
+ case TYPE_MAP_:
+ _inData = false;
+ if(available_size >= (size + 8)) {
+ ContChunck c((char*)_tbuffer + offset);
+ handleMap(c);
+ }
+ break;
+ case TYPE_DATA: // Sound data !!!
+ _inData = true;
+ _dataSize = size;
+ offset += 8;
+ {
+ int reqsize = 1;
+ if(_channels == 2) reqsize *= 2;
+ if(_bitsize == 16) reqsize *= 2;
+ else if(_bitsize == 12) {
+ if(reqsize > 1)
+ reqsize = reqsize * 3 / 2;
+ else reqsize = 3;
+ }
+ if((size % reqsize) != 0) {
+ warning("Invalid iMUS sound data size : (%d %% %d) != 0, correcting...", size, reqsize);
+ size += 3 - (size % reqsize);
+ }
+ }
+ return false;
+ default:
+ error("unknown chunck in iMUS track : %s ", Chunck::ChunckString(type));
+ }
+ offset += size + 8;
+ return true;
+ }
+ return false;
+}
+
+bool ImuseChannel::processBuffer() {
+ // see comments in saud_channel::processBuffer for an explanation
+ assert(_tbuffer != 0);
+ assert(_tbufferSize != 0);
+ assert(_sbuffer == 0);
+ assert(_sbufferSize == 0);
+
+ if(_inData) {
+ if(_dataSize < _tbufferSize) {
+ int offset= _dataSize;
+ while(handleSubTags(offset));
+ _sbufferSize = _dataSize;
+ _sbuffer = _tbuffer;
+ if(offset < _tbufferSize) { // there is still some unprocessed data
+ int new_size = _tbufferSize - offset;
+ _tbuffer = new unsigned char[new_size];
+ if(!_tbuffer) error("imuse_channel failed to allocate memory");
+ memcpy(_tbuffer, _sbuffer + offset, new_size);
+ _tbufferSize = new_size;
+ } else {
+ _tbuffer = 0;
+ _tbufferSize = 0;
+ }
+ if(_sbufferSize == 0) {
+ // this never happened yet, but who knows
+ delete []_sbuffer;
+ _sbuffer = 0;
+ }
+ } else {
+ // easy, swap the buffer
+ _sbufferSize = _tbufferSize;
+ _sbuffer = _tbuffer;
+ _tbufferSize = 0;
+ _tbuffer = 0;
+ }
+ } else {
+ int offset = 0;
+ while(handleSubTags(offset));
+ if(_inData) {
+ //~ unsigned char * old = _tbuffer;
+ _sbufferSize = _tbufferSize - offset;
+ assert(_sbufferSize);
+ _sbuffer = new unsigned char[_sbufferSize];
+ if(!_sbuffer) error("imuse_channel failed to allocate memory");
+ memcpy(_sbuffer, _tbuffer + offset, _sbufferSize);
+ delete []_tbuffer;
+ _tbuffer = 0;
+ _tbufferSize = 0;
+ } else {
+ if(offset) { // maybe I should assert() this to avoid a lock...
+ unsigned char * old = _tbuffer;
+ int new_size = _tbufferSize - offset;
+ _tbuffer = new unsigned char[new_size];
+ if(!_tbuffer) error("imuse_channel failed to allocate memory");
+ memcpy(_tbuffer, old + offset, new_size);
+ _tbufferSize = new_size;
+ delete []old;
+ }
+ }
+ }
+ _srbufferSize = _sbufferSize;
+ if(_sbuffer && _bitsize == 12) decode();
+ return true;
+}
+
+int ImuseChannel::availableSoundData(void) const {
+ int ret = _sbufferSize;
+ if(_channels == 2) ret /= 2;
+ if(_bitsize > 8) ret /= 2;
+ return ret;
+}
+
+void ImuseChannel::getSoundData(short * snd, int size) {
+ if(_dataSize <= 0 || _bitsize <= 8) error("invalid call to imuse_channel::read_sound_data()");
+ if(_channels == 2) size *= 2;
+ for(int i = 0; i < size; i++)
+ snd[i] = READ_BE_UINT16(_sbuffer + 2 * i);
+ delete []_sbuffer;
+ assert(_sbufferSize == 2 * size);
+ _sbuffer = 0;
+ _sbufferSize = 0;
+ _dataSize -= _srbufferSize;
+}
+
+void ImuseChannel::getSoundData(char * snd, int size) {
+ if(_dataSize <= 0 || _bitsize > 8) error("invalid call to imuse_channel::read_sound_data()");
+ if(_channels == 2) size *= 2;
+ for(int i = 0; i < size; i++)
+ snd[i] = _sbuffer[i];
+ delete []_sbuffer;
+ _sbuffer = 0;
+ _sbufferSize = 0;
+ _dataSize -= _srbufferSize;
+}
diff --git a/scumm/smush/mixer.h b/scumm/smush/mixer.h
new file mode 100644
index 0000000000..30858b6c29
--- /dev/null
+++ b/scumm/smush/mixer.h
@@ -0,0 +1,58 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2001/2002 The ScummVM project
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ *
+ */
+
+#ifndef __MIXER_H_
+#define __MIXER_H_
+
+#include "config.h"
+
+#ifdef DEBUG
+# ifndef NO_DEBUG_MIXER
+# define DEBUG_MIXER
+# endif
+#else
+# ifdef DEBUG_MIXER
+# error DEBUG_MIXER defined without DEBUG
+# endif
+#endif
+
+class _Channel;
+
+class SoundRenderer;
+
+/*! @brief The class for the player's sound mixer
+
+ This class is used for sound mixing.
+ It contains a list of current track and request them to mix.
+ It then sends the mixed sound samples to the sound renderer.
+
+*/
+class Mixer {
+public:
+ virtual ~Mixer() {};
+ virtual bool init() = 0;
+ virtual _Channel * findChannel(int track) = 0;
+ virtual bool addChannel(_Channel * c) = 0;
+ virtual bool handleFrame() = 0;
+ virtual bool stop() = 0;
+};
+
+#endif
diff --git a/scumm/smush/palette.cpp b/scumm/smush/palette.cpp
new file mode 100644
index 0000000000..033c6b2563
--- /dev/null
+++ b/scumm/smush/palette.cpp
@@ -0,0 +1,56 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2001/2002 The ScummVM project
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ *
+ */
+
+#include <stdafx.h>
+#include "palette.h"
+#include "assert.h"
+
+Palette::Palette() {
+}
+
+Palette::Palette(unsigned char * ptr) {
+ for(int i = 0; i < 256; i++) {
+ _colors[i] = Color(ptr[3 * i + 0], ptr[3 * i + 1], ptr[3 * i + 2]);
+ }
+}
+
+Palette::Palette(const Palette & p) {
+ for(int i = 0; i < 256; i++) {
+ _colors[i] = p._colors[i];
+ }
+}
+
+const Color & Palette::operator[](int a) const {
+ assert(a >= 0 && a < 256);
+ return _colors[a];
+}
+
+Color & Palette::operator[](int a) {
+ assert(a >= 0 && a < 256);
+ return _colors[a];
+}
+
+Palette & Palette::operator=(const Palette & p) {
+ for(int i = 0; i < 256; i++) {
+ _colors[i] = p._colors[i];
+ }
+ return *this;
+}
diff --git a/scumm/smush/palette.h b/scumm/smush/palette.h
new file mode 100644
index 0000000000..4cc8491219
--- /dev/null
+++ b/scumm/smush/palette.h
@@ -0,0 +1,45 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2001/2002 The ScummVM project
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ *
+ */
+
+#ifndef __PALETTE_H_
+#define __PALETTE_H_
+
+#include "config.h"
+
+#include "color.h"
+
+/*! @brief simple class for handling a palette.
+
+ This small class is an helper for palettes.
+*/
+class Palette {
+private:
+ Color _colors[256];
+public:
+ Palette();
+ Palette(unsigned char *);
+ Palette(const Palette &);
+ const Color & operator[](int) const;
+ Color & operator[](int);
+ Palette & operator=(const Palette &);
+};
+
+#endif
diff --git a/scumm/smush/player.cpp b/scumm/smush/player.cpp
new file mode 100644
index 0000000000..5362f5be9a
--- /dev/null
+++ b/scumm/smush/player.cpp
@@ -0,0 +1,760 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2001/2002 The ScummVM project
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ *
+ */
+
+#include <stdafx.h>
+#include "player.h"
+
+#include "renderer.h"
+#include "channel.h"
+#include "chunck_type.h"
+#include "rect.h"
+#include "blitter.h"
+
+#include <assert.h>
+#include <stdlib.h> // for atoi
+#include <stdio.h> // for FILE, fopen, fclose, fread, fseek, ftell
+#include <string.h> // for strchr, strrchr
+#include <ctype.h> // for isdigit
+
+#ifndef max
+#define max(x, y) ((x) > (y) ? (x) : (y))
+#endif
+
+const int WAIT = 100;
+
+/*! @brief parser and map of string resources
+
+ This class implements a parser for the string resource format of SMUSH animations.
+ It then allows the player to get the string corresponding to a particular identifier.
+
+ @bug some of The Dig strings are not completely parsed (in titles)
+*/
+
+const int MAX_STRINGS = 200;
+
+class StringResource {
+private:
+ struct {
+ int id;
+ char * string;
+ } _strings[MAX_STRINGS];
+ int _nbStrings;
+ int _lastId;
+ char * _lastString;
+public:
+ StringResource() : _nbStrings(0), _lastId(-1) {};
+ ~StringResource() {
+ for(int i = 0; i < _nbStrings; i++) {
+ delete []_strings[i].string;
+ }
+ }
+ /*! @brief parse the given buffer
+
+ @param buffer the buffer that contain the resource (in lucasart format)
+ @param length the length of the buffer
+
+ @return \c true if the parsing went fine, \c false otherwise
+ */
+ bool init(char * buffer, int length) {
+ debug(9, "parsing string resources...");
+ char * def_start = strchr(buffer, '#');
+ while(def_start != NULL) {
+ char * def_end = strchr(def_start, '\n');
+ assert(def_end != NULL); // def_end is just before the start of the string [def_start,def_end] correspond to the definition text
+ char * id_end = def_end;
+ while(id_end >= def_start && !isdigit(*(id_end-1))) id_end--;
+ assert(id_end > def_start);
+ char * id_start = id_end;
+ while(isdigit(*(id_start - 1))) id_start--;
+ // [id_start-id_end] is the id number
+ char idstring[32];
+ memcpy(idstring, id_start, id_end - id_start);
+ idstring[id_end - id_start] = 0;
+ int id = atoi(idstring);
+ //~ assert(id != LONG_MIN && id != 0 && id != LONG_MAX);
+ char * data_start = def_end;
+ while(*data_start == '\n' || *data_start == '\r') data_start++;
+ char * data_end = data_start;
+ while(1) {
+ if(data_end[-2] == '\r' && data_end[1] == '\n' && data_end[-1] == '\n' && data_end[0] == '\r')
+ break;
+ data_end++;
+ if(data_end >= buffer + length) {
+ data_end = buffer + length;
+ break;
+ }
+ }
+ data_end -= 2;
+ assert(data_end > data_start);
+ char * value = new char[data_end - data_start + 1];
+ assert(value);
+ memcpy(value, data_start, data_end - data_start);
+ value[data_end - data_start] = 0;
+#ifdef DEBUG
+ debug(9, "Inserting (%s)%d == \"%s\"", idstring, id, value);
+#endif
+ _strings[_nbStrings].id = id;
+ _strings[_nbStrings].string = value;
+ _nbStrings ++;
+ def_start = strchr(data_end + 2, '#');
+ }
+ return true;
+ }
+ /*! @brief extract a string
+
+ @param id the resource identifier
+
+ @return the corresponding string.
+ */
+ const char * get(int id) {
+ if(id == _lastId) return _lastString;
+ for(int i = 0; i < _nbStrings; i++)
+ {
+ if(_strings[i].id == id) {
+ _lastId = id;
+ _lastString = _strings[i].string;
+ return _strings[i].string;
+ }
+ }
+ warning("invalid string id : %d", id);
+ _lastId = -1;
+ _lastString = "unknown string";
+ return _lastString;
+ }
+};
+
+void SmushPlayer::show(const char * p) {
+ if(strcmp(p, "subtitles") == 0)
+ _subtitles = true;
+ else if(strcmp(p, "bgmusic") == 0)
+ _bgmusic = true;
+ else if(strcmp(p, "voices") == 0)
+ _voices = true;
+ else {
+ int id = atoi(p);
+ if(id < 0 || id > 36) error("invalid parameter to show");
+ _skips[id] = true;
+ }
+}
+
+void SmushPlayer::hide(const char * p) {
+ if(strcmp(p, "subtitles") == 0)
+ _subtitles = false;
+ else if(strcmp(p, "bgmusic") == 0)
+ _bgmusic = false;
+ else if(strcmp(p, "voices") == 0)
+ _voices = false;
+ else {
+ int id = atoi(p);
+ if(id < 0 || id > 36) error("invalid parameter to hide");
+ _skips[id] = false;
+ }
+}
+
+SmushPlayer::SmushPlayer(Renderer * renderer, bool wait, bool sound) :
+ _version(-1),
+ _secondaryVersion(0),
+ _soundFrequency(0),
+ _nbframes(0),
+ _mixer(0),
+ _renderer(renderer),
+ _strings(0),
+ _frameSize(-1, -1),
+ _frame(0),
+ _outputSound(sound),
+ _wait(wait),
+ _alreadyInit(false),
+ _codec37Called(false),
+ _skipNext(false),
+ _subtitles(true),
+ _bgmusic(true),
+ _voices(true) {
+ _fr[0] = _fr[1] = _fr[2] = _fr[3] = 0;
+ assert(_renderer != 0);
+}
+
+SmushPlayer::~SmushPlayer() {
+ clean();
+ //~ if(_mixer) delete _mixer;
+}
+
+void SmushPlayer::updatePalette(void) {
+ _renderer->setPalette(_pal);
+}
+
+void SmushPlayer::clean() {
+ if(_strings)
+ delete _strings;
+ if(_fr[0]) delete _fr[0];
+ if(_fr[1]) delete _fr[1];
+ if(_fr[2]) delete _fr[2];
+ if(_fr[3]) delete _fr[3];
+}
+
+void SmushPlayer::checkBlock(const Chunck & b, Chunck::type type_expected, unsigned int min_size) {
+ if(type_expected != b.getType()) {
+ error("chunck type is different from expected : %d != %d", b.getType(), type_expected);
+ }
+ if(min_size > b.getSize()) {
+ error( "chunck size is inferior than minimum required size : %d < %d", b.getSize(), min_size);
+ }
+}
+
+void SmushPlayer::handleSoundBuffer(int track_id, int index, int max_frames, int flags, int vol, int bal, Chunck & b, int size) {
+ debug(6, "smush_player::handleSoundBuffer(%d)", track_id);
+ if(!_voices && (flags & 128) == 128) return;
+ if(!_bgmusic && (flags & 64) == 64) return;
+ _Channel * c = _mixer->findChannel(track_id);
+ if(c == 0) {
+ c = new SaudChannel(track_id, _soundFrequency);
+ _mixer->addChannel(c);
+ }
+ if(index == 0)
+ c->setParameters(max_frames, flags, vol, bal);
+ else
+ c->checkParameters(index, max_frames, flags, vol, bal);
+ c->appendData(b, size);
+}
+
+void SmushPlayer::handleSoundFrame(Chunck & b) {
+ checkBlock(b, TYPE_PSAD);
+ debug(6, "SmushPlayer::handleSoundFrame()");
+ if(!_outputSound) return;
+ int track_id = b.getWord();
+ int index = b.getWord();
+ int max_frames = b.getWord();
+ int flags = b.getWord();
+ int vol = b.getByte();
+ int bal = b.getChar();
+#ifdef DEBUG
+ if(index == 0) {
+ debug(5, "track_id == %d, max_frames == %d, %d, %d, %d", track_id, max_frames, flags, vol, bal);
+ }
+#endif
+ int size = b.getSize() - 10;
+ handleSoundBuffer(track_id, index, max_frames, flags, vol, bal, b, size);
+}
+
+void SmushPlayer::handleSkip(Chunck & b) {
+ checkBlock(b, TYPE_SKIP, 4);
+ int code = b.getDword();
+ debug(6, "SmushPlayer::handleSkip(%d)", code);
+ if(code >= 0 && code < 37)
+ _skipNext =_skips[code];
+ else
+ _skipNext =true;
+}
+
+void SmushPlayer::handleStore(Chunck & b) {
+ checkBlock(b, TYPE_STOR, 4);
+ debug(6, "SmushPlayer::handleStore()");
+}
+
+void SmushPlayer::handleFetch(Chunck & b) {
+ checkBlock(b, TYPE_FTCH, 6);
+ debug(6, "SmushPlayer::handleFetch()");
+}
+
+void SmushPlayer::handleImuseBuffer(int track_id, int index, int nbframes, int size, int unk1, int unk2, Chunck & b, int bsize) {
+ _Channel * c = _mixer->findChannel(track_id);
+ if(c == 0) {
+ c = new ImuseChannel(track_id, _soundFrequency);
+ _mixer->addChannel(c);
+ }
+ if(index == 0)
+ c->setParameters(nbframes, size, unk1, unk2);
+ else
+ c->checkParameters(index, nbframes, size, unk1, unk2);
+ c->appendData(b, bsize);
+}
+
+void SmushPlayer::handleImuseAction8(Chunck & b, int flags, int unknown, int track_id) {
+ assert(flags == 46 && unknown == 0);
+ int unknown2 = b.getWord();
+ track_id |= unknown2 << 16;
+ int index = b.getWord();
+ int nbframes = b.getWord();
+ int size = b.getDword();
+ int bsize = b.getSize() - 18;
+ handleImuseBuffer(track_id, index, nbframes, size, unknown, unknown2, b, bsize);
+}
+
+void SmushPlayer::handleImuseAction(Chunck & b) {
+ checkBlock(b, TYPE_IACT, 8);
+ debug(6, "SmushPlayer::handleImuseAction()");
+ if(!_outputSound) return;
+ int code = b.getWord();
+ int flags = b.getWord();
+ int unknown = b.getShort();
+ int track_id = b.getWord();
+#ifdef DEBUG
+ debug(5, "handleImuseAction(%d, %d, %d, %d)", code, flags, unknown, track_id);
+#endif
+ switch(code) {
+ case 8:
+ handleImuseAction8(b, flags, unknown, track_id);
+ break;
+#ifdef DEBUG
+ default: {
+ debug(9, "%5.5d %d %8.8d %4.4d", track_id, flags, unknown);
+ }
+#endif
+ }
+}
+
+void SmushPlayer::handleTextResource(Chunck & b) {
+ checkBlock(b, TYPE_TRES, 18);
+ int pos_x = b.getShort();
+ int pos_y = b.getShort();
+ int flags = b.getShort();
+ int left = b.getShort();
+ int top = b.getShort();
+ int width = b.getShort();
+ int height = b.getShort();
+ int unk2 = b.getWord();
+ int string_id = b.getWord();
+ debug(6, "SmushPlayer::handleTextResource(%d)", string_id);
+ if(!_strings) return;
+
+ // if subtitles disabled and bit 3 is set, then do not draw
+ if((!_subtitles) && ((flags & 8) == 8)) return;
+ const char * str = _strings->get(string_id);
+
+ FontRenderer * fr = _fr[0];
+ int color = 15;
+ while(*str == '/') str++; // For Full Throttle text resources
+ while(str[0] == '^') {
+ switch(str[1]) {
+ case 'f':
+ {
+#if 0
+ // This cause trouble if the next character is a digit.
+ int id = atoi(str+2);
+#else
+ // assume ASCII like character set...
+ int id = str[3] - '0';
+#endif
+ str += 4;
+ fr = _fr[id];
+ } break;
+ case 'c':
+ {
+ //~ int id = atoi(str+2);
+ color = str[4] - '0' + 10 *(str[3] - '0');
+ str += 5;
+ } break;
+ default:
+ error("invalid escape code in text string");
+ }
+ }
+ assert(fr != 0);
+ fr->setColor(color);
+ if(!_curBuffer) { _curBuffer = _renderer->lockFrame(_frame); }
+ if(flags == 0 || flags == 4) {
+ fr->drawStringAbsolute(str, _curBuffer, _frameSize, pos_x, pos_y);
+ } else {
+ fr->drawStringCentered(str, _curBuffer, _frameSize, max(pos_y, top), left, width, pos_x);
+ }
+}
+
+void SmushPlayer::readPalette(Palette & out, Chunck & in) {
+ unsigned char buffer[768];
+ in.read(buffer, 768);
+ out = Palette(buffer);
+}
+
+void SmushPlayer::handleDeltaPalette(Chunck & b) {
+ checkBlock(b, TYPE_XPAL);
+ debug(6, "SmushPlayer::handleDeltaPalette()");
+ if(b.getSize() == 768 * 3 + 4) {
+ int unk1, num;
+ unk1 = b.getWord();
+ num = b.getWord();
+ for(int i = 0; i < 768; i++) {
+ _deltaPal[i] = b.getWord();
+ }
+ readPalette(_pal, b);
+ updatePalette();
+ } else if(b.getSize() == 6) {
+ int unk1, num, unk2;
+ unk1 = b.getWord();
+ num = b.getWord();
+ unk2 = b.getWord();
+ for(int i = 0; i < 256; i++) {
+ _pal[i].delta(_deltaPal + 3 * i);
+ }
+ updatePalette();
+ } else {
+ error("wrong size for DeltaPalette");
+ }
+}
+
+void SmushPlayer::handleNewPalette(Chunck & b) {
+ checkBlock(b, TYPE_NPAL, 768);
+ debug(6, "SmushPlayer::handleNewPalette()");
+ readPalette(_pal, b);
+ updatePalette();
+}
+
+void SmushPlayer::decodeCodec(Chunck & b, const Rect & r, Decoder & codec) {
+ assert(_curBuffer);
+ Blitter blit(_curBuffer, _frameSize, r);
+ codec.decode(blit, b);
+}
+
+void SmushPlayer::initSize(const Rect & r, bool always, bool transparent) {
+ if(_codec37Called) _alreadyInit = true;
+
+ if(!_alreadyInit || _frameSize.getX() < r.right() || _frameSize.getY() < r.bottom() || always) {
+ if(_curBuffer) {
+ _renderer->unlockFrame();
+ _curBuffer = 0;
+ }
+ _frameSize = r.bottomRight();
+ _renderer->initFrame(_frameSize);
+ }
+
+ if(_curBuffer) {
+ _renderer->unlockFrame();
+ _curBuffer = 0;
+ }
+
+ _curBuffer = _renderer->lockFrame(_frame);
+ if(!_alreadyInit && transparent) {
+ memset(_curBuffer, 0, _frameSize.getX()*_frameSize.getY());
+ }
+
+ _codec1.initSize(_frameSize, r);
+ _codec37.initSize(_frameSize, r);
+ _codec44.initSize(_frameSize, r);
+ _codecd.initSize(_frameSize, r);
+ _alreadyInit = true;
+}
+
+void SmushPlayer::handleFrameObject(Chunck & b) {
+ checkBlock(b, TYPE_FOBJ, 14);
+ if(_skipNext) {
+ _skipNext = false;
+ return;
+ }
+ int codec = b.getWord();
+ debug(6, "SmushPlayer::handleFrameObject(%d)", codec);
+ unsigned short left = b.getWord();
+ unsigned short top = b.getWord();
+ unsigned short width = b.getWord();
+ unsigned short height = b.getWord();
+ Rect r(left, top, left + width, top + height);
+ unsigned short data[2];
+ data[1] = b.getWord();
+ data[0] = b.getWord();
+#ifdef DEBUG
+ debug(5, "Frame pos : %d, %d", left, top);
+ debug(5, "Frame size : %dx%d", width, height);
+ debug(5, "Codec : %d", codec);
+#endif
+ switch (codec) {
+ case 3:
+ case 1:
+ initSize(r, false, true);
+ decodeCodec(b, r, _codec1);
+ break;
+ case 37:
+ assert(left == 0 && top == 0);
+ initSize(r, true, false);
+ decodeCodec(b, r, _codec37);
+ _codec37Called = true;
+ break;
+ case 47:
+ initSize(r, false, true);
+ decodeCodec(b, r, _codecd);
+ break;
+ case 21:
+ case 44:
+ initSize(r, true, true);
+ decodeCodec(b, r, _codec44);
+ break;
+ default:
+ error("Invalid codec for frame object : %d", (int)codec);
+ }
+}
+
+void SmushPlayer::handleFrame(Chunck & b) {
+ checkBlock(b, TYPE_FRME);
+ debug(6, "SmushPlayer::handleFrame(%d)", _frame);
+ _alreadyInit = false;
+ _skipNext = false;
+
+ while(!b.eof()) {
+ Chunck * sub = b.subBlock();
+ if(sub->getSize() & 1) b.seek(1);
+ switch(sub->getType()) {
+ case TYPE_NPAL:
+ handleNewPalette(*sub);
+ break;
+ case TYPE_FOBJ:
+ handleFrameObject(*sub);
+ break;
+ case TYPE_PSAD:
+ handleSoundFrame(*sub);
+ break;
+ case TYPE_TRES:
+ handleTextResource(*sub);
+ break;
+ case TYPE_XPAL:
+ handleDeltaPalette(*sub);
+ break;
+ case TYPE_IACT:
+ handleImuseAction(*sub);
+ break;
+ case TYPE_STOR:
+ handleStore(*sub);
+ break;
+ case TYPE_FTCH:
+ handleFetch(*sub);
+ break;
+ case TYPE_SKIP:
+ handleSkip(*sub);
+ break;
+ default:
+ error("Unknown frame subchunck found : %s, %d", Chunck::ChunckString(sub->getType()), sub->getSize());
+ }
+ delete sub;
+ }
+ if(_curBuffer) {
+ _renderer->unlockFrame();
+ _curBuffer = 0;
+ }
+ if(_outputSound)
+ _mixer->handleFrame();
+#ifdef DEBUG
+ debug(5, "===================END OF FRAME========================");
+#endif
+ _renderer->flipFrame();
+ if(_wait)
+ _renderer->wait(WAIT);
+ _frame++;
+}
+
+void SmushPlayer::handleAnimHeader(Chunck & b) {
+ checkBlock(b, TYPE_AHDR, 774);
+ debug(6, "SmushPlayer::handleAnimHeader()");
+ _version = b.getWord();
+ _nbframes = b.getWord();
+ int unknown = b.getWord();
+#ifdef DEBUG
+ debug(5, "SMUSH HEADER : version == %d, nbframes == %d, unknown == %d", _version, _nbframes, unknown);
+#else
+ unknown = unknown;
+#endif
+ _renderer->startDecode(_fname, _version, _nbframes);
+ readPalette(_pal, b);
+ updatePalette();
+ if(_version == 1) {
+ _soundFrequency = 22050;
+ }
+ if(_version == 2) {
+ _secondaryVersion = b.getDword();
+ int unknown2 = b.getDword();
+ _soundFrequency = b.getDword();
+#ifdef DEBUG
+ debug(5, "SMUSH HEADER : secondary version == %d, unknown2 == %d, sound frequency == %d", _secondaryVersion, unknown2, _soundFrequency);
+ int i = 0, c;
+ while(!b.eof()) {
+ c = b.getByte();
+ if(c) debug(9, "SMUSH HEADER : remaining bytes : %d == %d", i, c);
+ i++;
+ }
+#else
+ unknown2 = unknown2;
+#endif
+ if(_secondaryVersion != 10 && _secondaryVersion != 0 && _secondaryVersion != 12 && _secondaryVersion != 15 && _secondaryVersion != 14)
+ error("Wrong secondary version number for SMUSH animation");
+ if(_soundFrequency != 0 && _soundFrequency != 11025 && _soundFrequency != 22050)
+ error("Wrong _sound_frequency number for SMUSH animation");
+ }else if(_version > 2) {
+ error("Wrong primary version number for SMUSH animation");
+ }
+ if(_outputSound && _soundFrequency) {
+ if(_soundFrequency != 22050) _soundFrequency = 22050;
+ _mixer = _renderer->getMixer();
+ if(_mixer) {
+ _mixer->init();
+ } else {
+ _outputSound = false;
+ }
+ }
+}
+
+static StringResource * getStrings(const char * file, bool is_encoded) {
+ debug(7, "trying to read text ressources from %s", file);
+ FILE * is;
+ is = fopen(file, "rb");
+ if(is == NULL) return 0;
+ fseek(is, 0, SEEK_END);
+ int length = ftell(is);
+ fseek(is, 0, SEEK_SET);
+ char * filebuffer = new char [length + 1];
+ assert(filebuffer);
+ fread (filebuffer, length, 1, is);
+ filebuffer[length] = 0;
+ fclose(is);
+ if(is_encoded) {
+ static const int ETRS_HEADER_LENGTH = 16;
+ assert(length > ETRS_HEADER_LENGTH);
+ Chunck::type type = READ_BE_UINT32(filebuffer);
+ if(type != TYPE_ETRS) error("invalid type for file"); // mem leak !!!
+ char * old = filebuffer;
+ filebuffer = new char[length - ETRS_HEADER_LENGTH];
+ for(int i = ETRS_HEADER_LENGTH; i < length; i++)
+ filebuffer[i - ETRS_HEADER_LENGTH] = old[i] ^ 0xCC;
+ delete []old;
+ length -= ETRS_HEADER_LENGTH;
+ }
+ StringResource * sr = new StringResource;
+ assert(sr);
+ sr->init(filebuffer, length);
+ delete []filebuffer;
+ return sr;
+}
+
+bool SmushPlayer::readString(const char * file, bool & ft) {
+ const char * i = strrchr(file, '.');
+ if(i == NULL) error("invalid filename : %s", file);
+ char fname[260];
+ memcpy(fname, file, i - file);
+ strcpy(fname + (i - file), ".trs");
+ if((_strings = getStrings(fname, false)) != 0) {
+ ft = true;
+ return true;
+ }
+ i = strrchr(file, '\\');
+ if(i == NULL) i = strrchr(file, '/');
+ else {
+ char * j = strrchr(file, '/');
+ if(j > i) i = j;
+ }
+ if(i == NULL) error("invalid filename : %s", file);
+
+ memcpy(fname, file, i - file + 1);
+ strcpy(fname + (i - file + 1), "digtxt.trs");
+ if((_strings = getStrings(fname, true)) != 0) {
+ ft = false;
+ return true;
+ }
+ return false;
+}
+
+static FontRenderer * loadFont(const char * file, bool original = false) {
+#ifdef DEBUG
+ debug(5, "loading font from \"%s\"", file);
+#endif
+ FontRenderer * fr = new FontRenderer(original);
+ SmushPlayer p(fr, false, false);
+ p.play(file);
+ return fr;
+}
+
+bool SmushPlayer::play(const char * file) {
+#ifdef DEBUG
+ debug(5, "start of animation : %s", file);
+#endif
+ char * i = strrchr(file, '\\');
+ if(i == NULL)
+ {
+ i = strrchr(file, '/');
+ } else {
+ char * j = strrchr(i, '/');
+ if(j != NULL)
+ i = j;
+ }
+ char directory[260];
+ if(i != NULL) {
+ strcpy(directory, file);
+ directory[i-file] = 0;
+ //! @todo remove this...
+ _fname = strdup(i);
+ } else {
+ directory[0] = 0;
+ _fname = strdup(file);
+ }
+ clean();
+
+ if(_wait) {
+ bool isFullthrottle;
+ if(!readString(file, isFullthrottle))
+ warning("unable to read text information for \"%s\"", file);
+ if(_strings) {
+ if(isFullthrottle) {
+ if(strcmp(directory, "") == 0) {
+ strcpy(directory, "../data/");
+ } else {
+ char * i = strrchr(directory, '\\');
+ char * j = strrchr(directory, '/');
+ if(j > i) i = j;
+ if(i == NULL) {
+ strcpy(directory, "data/");
+ } else {
+ *i = 0;
+ strcat(directory, "/data/");
+ }
+ }
+ char file[260];
+ strcpy(file, directory); strcat(file, "scummfnt.nut");
+ _fr[0] = loadFont(file, true);
+ strcpy(file, directory); strcat(file, "titlfnt.nut");
+ _fr[2] = loadFont(file, true);
+ } else {
+ for(int i = 0; i < 4; i++) {
+ char file[260];
+ sprintf(file, "%s/font%d.nut",directory, i);
+ _fr[i] = loadFont(file, i != 0);
+ }
+ }
+ }
+ }
+ FileChunck base = FileChunck(file);
+
+ checkBlock(base, TYPE_ANIM);
+
+ while(!base.eof()) {
+ Chunck * sub = base.subBlock();
+ switch(sub->getType()) {
+ case TYPE_AHDR:
+ handleAnimHeader(*sub);
+ break;
+ case TYPE_FRME:
+ handleFrame(*sub);
+ break;
+ default:
+ error("Unknown chunck found : %d, %d", sub->getType(), sub->getSize());
+ }
+ delete sub;
+ if(_renderer->prematureClose())
+ break;
+ }
+#ifdef DEBUG
+ debug(5, "end of animation");
+#endif
+ if(_outputSound) {
+ _mixer->stop();
+ }
+ return true;
+}
diff --git a/scumm/smush/player.h b/scumm/smush/player.h
new file mode 100644
index 0000000000..ceb58eaee2
--- /dev/null
+++ b/scumm/smush/player.h
@@ -0,0 +1,104 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2001/2002 The ScummVM project
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ *
+ */
+
+#ifndef __PLAYER_H_
+#define __PLAYER_H_
+
+#include "config.h"
+
+#include "rect.h"
+#include "mixer.h"
+#include "chunck.h"
+#include "palette.h"
+#include "codec1.h"
+#include "codec37.h"
+#include "codec44.h"
+#include "codec47.h"
+#include "frenderer.h"
+
+class Renderer;
+
+class StringResource;
+
+/*! @brief the SMUSH player class
+
+ This class is the player itself.
+*/
+class SmushPlayer {
+private:
+ char * _fname; //!< the name of the animation file being played
+ int _version; //!< the version of the animation file being played
+ int _secondaryVersion; //!< the secondary version number of the animation file being played
+ int _soundFrequency; //!< the sound frequency of the animation file being played
+ int _nbframes; //!< the number of frames in the animation file
+ Mixer * _mixer; //!< the sound mixer
+ Palette _pal; //!< the current palette
+ short _deltaPal[768]; //!< the delta palette information set by an xpal
+ Renderer * _renderer; //!< pointer to the ::renderer
+ StringResource * _strings; //!< pointer to the string resources associated with the animation
+ FontRenderer * _fr[4]; //!< pointers to the fonts for the animation
+ Codec1Decoder _codec1; //!< the ::decoder for codec 1 and 3
+ Codec37Decoder _codec37; //!< the ::decoder for codec 37
+ Codec44Decoder _codec44; //!< the ::decoder for codec 21 and 44
+ DumpDecoder _codecd; //!< the ::decoder for codec 21 and 44
+ Point _frameSize; //!< the current frame size of the animation
+ int _frame; //!< the current frame number of the animation
+ bool _outputSound; //!< should we handle sound ?
+ bool _wait; //!< should we synchronise the player ?
+ bool _alreadyInit; //!< has the player already been initialized for the current frame
+ bool _codec37Called; //!< has the codec 37 already been called once for this animation
+ bool _skipNext; //!< should the player skip the next frame object ?
+ bool _subtitles; //!< should the player handle subtitles ?
+ bool _bgmusic; //!< should the player output the background music ?
+ bool _voices; //!< should the player output the voice ?
+ bool _skips[37]; //!< mapping of frame object identifier to show or hide
+ char * _curBuffer; //!< pointer to the current frame
+public:
+ SmushPlayer(Renderer *, bool wait = true, bool output_sound = true);
+ virtual ~SmushPlayer();
+ bool play(const char *);
+ void updatePalette(void);
+ void show(const char *);
+ void hide(const char *);
+protected:
+ bool readString(const char * file, bool &);
+ void clean();
+ void checkBlock(const Chunck &, Chunck::type, unsigned int = 0);
+ void handleAnimHeader(Chunck &);
+ void handleFrame(Chunck &);
+ void handleNewPalette(Chunck &);
+ void handleFrameObject(Chunck &);
+ void handleSoundBuffer(int, int, int, int, int, int, Chunck &, int);
+ void handleImuseBuffer(int, int, int, int, int, int, Chunck &, int);
+ void handleSoundFrame(Chunck &);
+ void handleSkip(Chunck &);
+ void handleStore(Chunck &);
+ void handleFetch(Chunck &);
+ void handleImuseAction8(Chunck &, int flags, int unknown, int track_id);
+ void handleImuseAction(Chunck &);
+ void handleTextResource(Chunck &);
+ void handleDeltaPalette(Chunck &);
+ void decodeCodec(Chunck &, const Rect &, Decoder &);
+ void readPalette(Palette &, Chunck &);
+ void initSize(const Rect &, bool, bool);
+};
+
+#endif
diff --git a/scumm/smush/rect.cpp b/scumm/smush/rect.cpp
new file mode 100644
index 0000000000..deb1d5b35f
--- /dev/null
+++ b/scumm/smush/rect.cpp
@@ -0,0 +1,62 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2001/2002 The ScummVM project
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ *
+ */
+
+#include <stdafx.h>
+#include "rect.h"
+
+Rect::Rect() : _topLeft(0, 0), _bottomRight(0,0) {
+}
+
+Rect::Rect(int x, int y) : _topLeft(0, 0), _bottomRight(x, y) {
+ check();
+}
+
+Rect::Rect(int x1, int y1, int x2, int y2) : _topLeft(x1, y1), _bottomRight(x2, y2) {
+ check();
+}
+
+Rect::Rect(const Rect & r) : _topLeft(r._topLeft), _bottomRight(r._bottomRight) {
+}
+
+Rect & Rect::operator=(const Rect & r) {
+ _topLeft = r._topLeft;
+ _bottomRight = r._bottomRight;
+ return *this;
+}
+
+bool Rect::operator==(const Rect & r) const {
+ return _topLeft == r._topLeft && _bottomRight == r._bottomRight;
+}
+
+void Rect::check() {
+ if ((_topLeft.getX() < 0) || (_bottomRight.getX() < _topLeft.getX()) || (_topLeft.getY() < 0) || (_bottomRight.getY() < _topLeft.getY())) {
+ error("Invalid rect");
+ }
+}
+
+bool Rect::isInside(int x, int y) const {
+ return _topLeft.getX() >= x && _bottomRight.getX() < x && _topLeft.getY() >= y && _bottomRight.getY() < y;
+}
+
+bool Rect::isInside(const Point & p) const {
+ return (left() <= p.getX()) && (right() > p.getX()) && (top() <= p.getY()) && (bottom() > p.getY());
+}
+
diff --git a/scumm/smush/rect.h b/scumm/smush/rect.h
new file mode 100644
index 0000000000..c7483f54ef
--- /dev/null
+++ b/scumm/smush/rect.h
@@ -0,0 +1,101 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2001/2002 The ScummVM project
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ *
+ */
+
+#ifndef __RECT_H_
+#define __RECT_H_
+
+#include "config.h"
+
+/*! @brief simple class for handling both 2D position and size
+
+ This small class is an helper for position and size values.
+*/
+class Point {
+private:
+ int _x; //!< The horizontal part of the point
+ int _y; //!< The vertical part of the point
+public:
+ Point() : _x(0), _y(0) {};
+ Point(const Point & p) : _x(p.getX()), _y(p.getY()) {};
+ explicit Point(int x, int y) : _x(x), _y(y) {};
+ Point & operator=(const Point & p) { _x = p.getX(); _y = p.getY(); return *this; };
+ bool operator==(const Point & p) const { return _x == p.getX() && _y == p.getY(); };
+ const int & getX() const { return _x; };
+ const int & getY() const { return _y; };
+ int & getX() { return _x; };
+ int & getY() { return _y; };
+ Point operator+(const Point & p) const { return Point(_x + p.getX(), _y+p.getY()); };
+ Point operator-(const Point & p) const { return Point(_x - p.getX(), _y-p.getY()); };
+ Point & operator+=(const Point & p) { _x += p.getX(); _y += p.getY(); return *this; };
+ Point & operator-=(const Point & p) { _x -= p.getX(); _y -= p.getY(); return *this; };
+ bool isOrigin() const { return *this == Point(0, 0); };
+ void set(int x, int y) { _x = x; _y = y; }
+};
+
+/*! @brief simple class for handling a rectangular zone.
+
+ This small class is an helper for rectangles.
+ It is mostly used by the blitter class.
+*/
+class Rect {
+private:
+ Point _topLeft; //!< The point at the top left of the rectangle
+ Point _bottomRight; //!< The point at the bottom right of the rectangle
+protected:
+ void check();
+public:
+ Rect();
+ Rect(int x, int y);
+ explicit Rect(const Point & size);
+ Rect(int x1, int y1, int x2, int y2);
+ Rect(const Point & topleft, const Point & bottomright);
+ Rect(const Rect & r);
+ Rect & operator=(const Rect & r);
+ bool operator==(const Rect & r) const;
+ Point size() const { return (_bottomRight - _topLeft); };
+ int width() const { return size().getX(); }
+ int height() const { return size().getY(); }
+ int left() const { return _topLeft.getX(); }
+ int right() const { return _bottomRight.getX(); }
+ int top() const { return _topLeft.getY(); }
+ int bottom() const { return _bottomRight.getY(); }
+ const Point & topLeft() const { return _topLeft; }
+ const Point & bottomRight() const { return _bottomRight; }
+
+ /*! @brief check if given position is inside the rectangle
+
+ @param x the horizontal position to check
+ @param y the vertical position to check
+
+ @return true if the given position is inside the rectangle, false otherwise
+ */
+ bool isInside(int x, int y) const;
+ /*! @brief check if given point is inside the rectangle
+
+ @param p the point to check
+
+ @return true if the given point is inside the rectangle, false otherwise
+ */
+ bool isInside(const Point & p) const;
+ bool clip(Rect & r) const;
+};
+
+#endif
diff --git a/scumm/smush/renderer.h b/scumm/smush/renderer.h
new file mode 100644
index 0000000000..dde44a3afe
--- /dev/null
+++ b/scumm/smush/renderer.h
@@ -0,0 +1,123 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2001/2002 The ScummVM project
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ *
+ */
+
+#ifndef __RENDERER_H_
+#define __RENDERER_H_
+
+#include "config.h"
+
+#include "rect.h"
+
+class Palette;
+class Mixer;
+
+/*! @brief interface for general output (rendering)
+
+ This is the interface for frame output.
+ Several implementations of these interface exist, each having a particular
+ application.
+*/
+class Renderer {
+public:
+ virtual ~Renderer() {};
+ /*! @brief start of animation output
+
+ This is called by the animation player when output is going to start.
+
+ @param fname name of the animation being played.
+ @param version version number of the animation
+ @param nbframes total number of frames of the animation.
+
+ @return true if initialisation was ok, false otherwise
+ */
+ virtual bool startDecode(const char * fname, int version, int nbframes) = 0;
+ /*! @brief start of animation output
+
+ This is called by the animation player when the frame size is changing.
+
+ @param size new size of the frames.
+
+ @return true if everything went fine, false otherwise
+ */
+ virtual bool initFrame(const Point & size) = 0;
+ /*! @brief set a new palette
+
+ This is called by the animation player when the palette is changing.
+
+ @param pal new palette.
+
+ @return true if everything went fine, false otherwise
+ */
+ virtual bool setPalette(const Palette & pal) = 0;
+ /*! @brief lock a frame buffer
+
+ This is called by the animation player when a frame is going to be decoded.
+
+ @param frame the frame number.
+
+ @return a pointer to the frame buffer to output data to.
+ */
+ virtual char * lockFrame(int frame) = 0;
+ /*! @brief unlock a frame buffer
+
+ This is called by the animation player when a frame has been decoded.
+
+ @return true if everything went fine, false otherwise
+ */
+ virtual bool unlockFrame() = 0;
+ /*! @brief flip a frame buffer
+
+ This is called by the animation player when the current frame should be shown.
+
+ @return true if everything went fine, false otherwise
+ */
+ virtual bool flipFrame() = 0;
+ /*! @brief wait for some time
+
+ This is called by the animation player when the animation should stay idle.
+
+ @param ms number of millisecond to wait.
+
+ @return true if everything went fine, false otherwise
+ */
+ virtual bool wait(int ms) = 0;
+ /*! @brief does the renderer want a premature end of the animation ?
+
+ This is called by the animation player after each frame.
+
+ @return true if playing should be stopped, false otherwise.
+ */
+ virtual bool prematureClose() = 0;
+ /*! @brief request for a mixer
+
+ This is called by the animation player when sound output is required by the animation.
+
+ @return a valid pointer to an uninitialized mixer instance, or null if none is available.
+ */
+ virtual Mixer * getMixer() = 0;
+ /*! @brief debugging function : do not use
+
+ @return true if everything went fine, false otherwise
+ */
+ virtual bool saveCurrent() { return false; };
+};
+
+#endif
diff --git a/scumm/smush/saud_channel.cpp b/scumm/smush/saud_channel.cpp
new file mode 100644
index 0000000000..8fd584b659
--- /dev/null
+++ b/scumm/smush/saud_channel.cpp
@@ -0,0 +1,274 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2001/2002 The ScummVM project
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ *
+ */
+
+#include <stdafx.h>
+#include "channel.h"
+#include "chunck.h"
+#include "chunck_type.h"
+
+#include <assert.h>
+#include <string.h> // for memcpy.h
+#ifndef min
+#define min(x, y) ((x) > (y) ? (y) : (x))
+#endif
+
+void SaudChannel::handleStrk(Chunck & b) {
+ int size = b.getSize();
+ if(size != 14 && size != 10) {
+ error("STRK has a invalid size : %d", size);
+ }
+}
+
+void SaudChannel::handleSmrk(Chunck & b) {
+ _markReached = true;
+}
+
+void SaudChannel::handleShdr(Chunck & b) {
+ int size = b.getSize();
+ if(size != 4) warning("SMRK has a invalid size : %d", size);
+}
+
+bool SaudChannel::handleSubTags(int & offset) {
+ int available_size = _tbufferSize - offset;
+ if(available_size >= 8) {
+ Chunck::type type = READ_BE_UINT32(_tbuffer + offset);
+ unsigned int size = READ_BE_UINT32(_tbuffer + offset + 4);
+
+ switch(type) {
+ case TYPE_STRK:
+ _inData = false;
+ if(available_size >= (size + 8)) {
+ ContChunck c((char*)_tbuffer + offset);
+ handleStrk(c);
+ }
+ else
+ return false;
+ break;
+ case TYPE_SMRK:
+ _inData = false;
+ if(available_size >= (size + 8)) {
+ ContChunck c((char*)_tbuffer + offset);
+ handleSmrk(c);
+ }
+ else
+ return false;
+ break;
+ case TYPE_SHDR:
+ _inData = false;
+ if(available_size >= (size + 8)) {
+ ContChunck c((char*)_tbuffer + offset);
+ handleShdr(c);
+ }
+ else
+ return false;
+ break;
+ case TYPE_SDAT:
+ _inData = true;
+ _dataSize = size;
+ offset += 8;
+ return false;
+ default:
+ error("unknown chunck in SAUD track : %s ", Chunck::ChunckString(type));
+ }
+ offset += size + 8;
+ return true;
+ }
+ return false;
+}
+
+bool SaudChannel::processBuffer() {
+ // At the start of this function, we have _tbuffer[0.._tbuffersize] containing possible data...
+ // and _sbuffer is 0
+ // At the end we have :
+ // if(sound data) _sbuffer[0.._sbuffer_size] contains the sound data
+ // the unprocessed data is kept in _tbuffer[0.._tbuffersize] (which may have changed)
+ // if no unprocessed data, then _tbuffer is 0
+ assert(_tbuffer != 0);
+ assert(_tbufferSize != 0);
+ assert(_sbuffer == 0);
+ assert(_sbufferSize == 0);
+
+ if(_inData) {
+ if(_dataSize < _tbufferSize) {
+ // I can't assume that the channel is finished after data is received... (this assumption failed in realride.san)
+ int offset= _dataSize;
+ while(handleSubTags(offset));
+ _sbufferSize = _dataSize;
+ _sbuffer = _tbuffer;
+ if(offset < _tbufferSize) { // there is still some unprocessed data
+ int new_size = _tbufferSize - offset;
+ _tbuffer = new unsigned char[new_size];
+ if(!_tbuffer) error("SaudChannel failed to allocate memory");
+ memcpy(_tbuffer, _sbuffer + offset, new_size);
+ _tbufferSize = new_size;
+ } else {
+ _tbuffer = 0;
+ _tbufferSize = 0;
+ }
+ if(_sbufferSize == 0) {
+ // this never happened yet, but who knows
+ delete []_sbuffer;
+ _sbuffer = 0;
+ }
+ } else {
+ // easy, swap the buffer
+ _sbufferSize = _tbufferSize;
+ _sbuffer = _tbuffer;
+ _tbufferSize = 0;
+ _tbuffer = 0;
+ }
+ } else {
+ int offset = 0;
+ while(handleSubTags(offset));
+ if(_inData) {
+ _sbufferSize = _tbufferSize - offset;
+ assert(_sbufferSize);
+ _sbuffer = new unsigned char[_sbufferSize];
+ if(!_sbuffer) error("saud_channel failed to allocate memory");
+ memcpy(_sbuffer, _tbuffer + offset, _sbufferSize);
+ delete []_tbuffer;
+ _tbuffer = 0;
+ _tbufferSize = 0;
+ } else {
+ if(offset) { // maybe I should assert() this to avoid a lock...
+ unsigned char * old = _tbuffer;
+ int new_size = _tbufferSize - offset;
+ _tbuffer = new unsigned char[new_size];
+ if(!_tbuffer) error("SaudChannel failed to allocate memory");
+ memcpy(_tbuffer, old + offset, new_size);
+ _tbufferSize = new_size;
+ delete []old;
+ }
+ }
+ }
+ return true;
+}
+
+SaudChannel::SaudChannel(int track, int freq) :
+ _track(track),
+ _nbframes(0),
+ _dataSize(-1),
+ _tbuffer(0),
+ _sbuffer(0),
+ _frequency(freq),
+ _tbufferSize(0),
+ _sbufferSize(0),
+ _inData(false),
+ _markReached(false)
+ {
+}
+
+SaudChannel::~SaudChannel() {
+ if(_tbuffer) delete []_tbuffer;
+ if(_sbuffer) {
+ warning("this should never happen !!!! (_sbuffer not NULL here)");
+ delete []_sbuffer;
+ }
+}
+
+bool SaudChannel::isTerminated() const {
+ return (_markReached && _dataSize == 0 && _sbuffer == 0);
+}
+
+void SaudChannel::recalcVolumeTable() {
+ const int MAX_BALANCE = 100;
+ int volume_left, volume_right;
+ if(_balance < -MAX_BALANCE || _balance > MAX_BALANCE) {
+ error("balance is out of range ! : %d", _balance);
+ }
+ int left_multiplier = MAX_BALANCE - _balance;
+ int right_multiplier = MAX_BALANCE + _balance;
+ volume_left = _volume * left_multiplier / (MAX_BALANCE * 2);
+ volume_right = _volume * right_multiplier / (MAX_BALANCE * 2);
+ if(volume_left < 0) volume_left = 0;
+ if(volume_left > 128) volume_left = 128;
+ if(volume_right < 0) volume_right = 0;
+ if(volume_right > 128) volume_right = 128;
+ for(int i = 0; i < 256; i++) {
+ int value = volume_left * (signed char)i;
+ _voltable[0][i] = TO_BE_16(value);
+ value = volume_right * (signed char)i;
+ _voltable[1][i] = TO_BE_16(value);
+ }
+}
+
+bool SaudChannel::setParameters(int nb, int flags, int volume, int balance) {
+ _nbframes = nb;
+ _flags = flags; // bit 7 == IS_VOICE, bit 6 == IS_BACKGROUND_MUSIC, other ??
+ _volume = volume;
+ _balance = balance;
+ _index = 0;
+ recalcVolumeTable();
+ return true;
+}
+
+bool SaudChannel::checkParameters(int index, int nb, int flags, int volume, int balance) {
+ if(++_index != index) error("invalid index in SaudChannel::checkParameters()");
+ if(_nbframes != nb) error("invalid duration in SaudChannel::checkParameters()");
+ if(_flags != flags) error("invalid flags in SaudChannel::checkParameters()");
+ if(_volume != volume || _balance != balance) {
+ _volume = volume;
+ _balance = balance;
+ recalcVolumeTable();
+ }
+ return true;
+}
+
+bool SaudChannel::appendData(Chunck & b, int size) {
+ if(_dataSize == -1) { // First call
+ assert(size > 8);
+ Chunck::type saud_type = b.getDword(); saud_type = TO_BE_32(saud_type);
+ unsigned int saud_size = b.getDword(); saud_size = TO_BE_32(saud_size);
+ if(saud_type != TYPE_SAUD) error("Invalid CHUNCK for SaudChannel : %X", saud_type);
+ size -= 8;
+ _dataSize = -2; // We don't get here again...
+ }
+ if(_tbuffer) {
+ unsigned char * old = _tbuffer;
+ _tbuffer = new unsigned char[_tbufferSize + size];
+ if(!_tbuffer) error("saud_channel failed to allocate memory");
+ memcpy(_tbuffer, old, _tbufferSize);
+ delete []old;
+ b.read(_tbuffer + _tbufferSize, size);
+ _tbufferSize += size;
+ } else {
+ _tbufferSize = size;
+ _tbuffer = new unsigned char[_tbufferSize];
+ if(!_tbuffer) error("saud_channel failed to allocate memory");
+ b.read(_tbuffer, _tbufferSize);
+ }
+ return processBuffer();
+}
+
+int SaudChannel::availableSoundData(void) const {
+ return _sbufferSize;
+}
+
+void SaudChannel::getSoundData(short * snd, int size) {
+ for(int i = 0; i < size; i++) {
+ snd[2 * i] = _voltable[0][_sbuffer[i] ^ 0x80];
+ snd[2 * i + 1] = _voltable[1][_sbuffer[i] ^ 0x80];
+ }
+ _dataSize -= size;
+ delete []_sbuffer;
+ _sbuffer = 0;
+ _sbufferSize = 0;
+}
diff --git a/scumm/smush/scumm_renderer.cpp b/scumm/smush/scumm_renderer.cpp
new file mode 100644
index 0000000000..bfce102ae5
--- /dev/null
+++ b/scumm/smush/scumm_renderer.cpp
@@ -0,0 +1,266 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2001/2002 The ScummVM project
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ *
+ */
+
+#include <stdafx.h>
+#include "scumm_renderer.h"
+#include "channel.h"
+
+class scumm_mixer : public Mixer {
+private:
+ SoundMixer * _mixer; //!< pointer to the SoundMixer instance
+ struct {
+ int id;
+ _Channel * chan;
+ bool first;
+ int mixer_index;
+ } _channels[SoundMixer::NUM_CHANNELS]; //!< The map of track and channels
+ int _nextIndex;
+public:
+ scumm_mixer(SoundMixer *);
+ virtual ~scumm_mixer();
+ bool init();
+ _Channel * findChannel(int track);
+ bool addChannel(_Channel * c);
+ bool handleFrame();
+ bool stop();
+ bool update();
+};
+
+scumm_mixer::scumm_mixer(SoundMixer * m) : _mixer(m), _nextIndex(0) {
+ for(int i = 0; i < SoundMixer::NUM_CHANNELS; i++) {
+ _channels[i].id = -1;
+ _channels[i].chan = 0;
+ _channels[i].first = true;
+ }
+}
+
+scumm_mixer::~scumm_mixer() {
+}
+
+bool scumm_mixer::init() {
+ debug(9, "scumm_mixer::init()");
+ return true;
+}
+
+_Channel * scumm_mixer::findChannel(int track) {
+ debug(9, "scumm_mixer::findChannel(%d)", track);
+ for(int i = 0; i < SoundMixer::NUM_CHANNELS; i++) {
+ if(_channels[i].id == track)
+ return _channels[i].chan;
+ }
+ return 0;
+}
+
+bool scumm_mixer::addChannel(_Channel * c) {
+ int track = c->getTrackIdentifier();
+ int i;
+
+ debug(9, "scumm_mixer::addChannel(%d)", track);
+
+ for(i = 0; i < SoundMixer::NUM_CHANNELS; i++) {
+ if(_channels[i].id == track)
+ warning("mixer::addChannel(%d) : channel already exist !", track);
+ }
+ if(_nextIndex >= SoundMixer::NUM_CHANNELS) _nextIndex = 0;
+
+ for(i = _nextIndex; i < SoundMixer::NUM_CHANNELS; i++) {
+ if(_channels[i].chan == 0 || _channels[i].id == -1) {
+ _channels[i].chan = c;
+ _channels[i].id = track;
+ _channels[i].first = true;
+ _nextIndex = i + 1;
+ return true;
+ }
+ }
+
+ for(i = 0; i < _nextIndex; i++) {
+ if(_channels[i].chan == 0 || _channels[i].id == -1) {
+ _channels[i].chan = c;
+ _channels[i].id = track;
+ _channels[i].first = true;
+ _nextIndex = i + 1;
+ return true;
+ }
+ }
+
+ fprintf(stderr, "_nextIndex == %d\n", _nextIndex);
+
+ for(i = 0; i < SoundMixer::NUM_CHANNELS; i++) {
+ fprintf(stderr, "channel %d : %p(%d, %d) %d %d\n", i, _channels[i].chan,
+ _channels[i].chan ? _channels[i].chan->getTrackIdentifier() : -1,
+ _channels[i].chan ? _channels[i].chan->isTerminated() : 1,
+ _channels[i].first, _channels[i].mixer_index);
+ }
+
+ error("mixer::add_channel() : no more channel available");
+ return false;
+}
+
+bool scumm_mixer::handleFrame() {
+ debug(9, "scumm_mixer::handleFrame()");
+ for(int i = 0; i < SoundMixer::NUM_CHANNELS; i++) {
+ if(_channels[i].id != -1) {
+ debug(9, "updating channel %d (%p)", _channels[i].id, _channels[i].chan);
+ if(_channels[i].chan->isTerminated()) {
+ debug(9, "channel %d has terminated (%p)", _channels[i].id, _channels[i].chan);
+ delete _channels[i].chan;
+ _channels[i].id = -1;
+ _channels[i].chan = 0;
+ } else {
+ int rate;
+ bool stereo, is_short;
+
+ _channels[i].chan->getParameters(rate, stereo, is_short);
+ int size = _channels[i].chan->availableSoundData();
+ debug(9, "channel %d : %d, %s, %d bits, %d", _channels[i].id, rate, stereo ? "stereo" : "mono", is_short ? 16 : 8, size);
+ int flags = stereo ? SoundMixer::FLAG_STEREO : 0;
+
+ if(is_short) {
+ // FIXME this is one more data copy... we could get rid of it...
+ short * data = new short[size * (stereo ? 2 : 1)];
+ _channels[i].chan->getSoundData(data, size);
+ size *= stereo ? 4 : 2;
+
+ // append to _sound
+ if(_channels[i].first) {
+ _channels[i].mixer_index = _mixer->playStream(NULL, -1, data, size, rate, flags | SoundMixer::FLAG_16BITS);
+ debug(5, "channel %d bound to mixer_index %d", _channels[i].id, _channels[i].mixer_index);
+ _channels[i].first = false;
+ } else {
+ _mixer->append(_channels[i].mixer_index, data, size, rate, flags | SoundMixer::FLAG_16BITS);
+ }
+
+ delete []data;
+ } else {
+ char * data = new char[size*(stereo ? 2 : 1)];
+ _channels[i].chan->getSoundData(data, size);
+ size *= stereo ? 2 : 1;
+
+ // append to _sound
+ if(_channels[i].first) {
+ _channels[i].mixer_index = _mixer->playStream(NULL, -1, data, size, rate, flags | SoundMixer::FLAG_UNSIGNED);
+ _channels[i].first = false;
+ } else {
+ _mixer->append(_channels[i].mixer_index, data, size, rate, flags | SoundMixer::FLAG_UNSIGNED);
+ }
+
+ delete []data;
+ }
+ }
+ }
+ }
+ return true;
+}
+
+bool scumm_mixer::stop() {
+ debug(9, "scumm_mixer::stop()");
+ for(int i = 0; i < SoundMixer::NUM_CHANNELS; i++) {
+ if(_channels[i].id != -1) {
+ delete _channels[i].chan;
+ _channels[i].id = -1;
+ _channels[i].chan = 0;
+ }
+ }
+ //~ _mixer->stopAll();
+ return true;
+}
+
+ScummRenderer::ScummRenderer(Scumm * scumm) : _scumm(scumm), _smixer(0) {
+}
+
+static ScummRenderer * s_renderer;
+
+static void smush_handler(Scumm * scumm) {
+ s_renderer->update();
+}
+
+Mixer * ScummRenderer::getMixer() {
+ if(_smixer == 0) {
+ _scumm->_sound->pauseBundleMusic(true);
+ _smixer = new scumm_mixer(_scumm->_mixer);
+ if(!_smixer) error("unable to allocate a smush mixer");
+ s_renderer = this;
+ _scumm->_timer->installProcedure(&smush_handler, 75);
+ }
+ return _smixer;
+}
+
+ScummRenderer::~ScummRenderer() {
+ _scumm->_insaneState = 0;
+ _scumm->exitCutscene();
+ if(_smixer) {
+ _scumm->_timer->releaseProcedure(&smush_handler);
+ delete _smixer;
+ _smixer = 0;
+ }
+ _scumm->_sound->pauseBundleMusic(false);
+}
+
+bool ScummRenderer::wait(int ms) {
+ while(_wait) {
+ _scumm->waitForTimer(1);
+ }
+ return true;
+}
+
+bool ScummRenderer::startDecode(const char * fname, int version, int nbframes) {
+ _scumm->_sound->pauseBundleMusic(true);
+ _scumm->videoFinished = 0;
+ _scumm->_insaneState = 1;
+ return true;
+}
+
+bool ScummRenderer::setPalette(const Palette & pal) {
+ int i;
+ byte palette_colors[1024];
+ byte *p = palette_colors;
+
+ for (i = 0; i < 256; i++, p += 4) {
+ p[0] = pal[i].red();
+ p[1] = pal[i].green();
+ p[2] = pal[i].blue();
+ p[3] = 0;
+ }
+
+ _scumm->_system->set_palette(palette_colors, 0, 256);
+ _scumm->setDirtyColors(0, 255);
+ return BaseRenderer::setPalette(pal); // For compatibility with possible subclass...
+}
+
+void ScummRenderer::save(int frame) {
+ int width = min(getWidth(), _scumm->_realWidth);
+ int height = min(getHeight(), _scumm->_realHeight);
+
+ _scumm->_system->copy_rect((const byte *)data(), getWidth(), 0, 0, width, height);
+ _scumm->_system->update_screen();
+ _scumm->processKbd();
+ _wait = true;
+}
+
+bool ScummRenderer::prematureClose() {
+ return _scumm->videoFinished;
+}
+
+bool ScummRenderer::update() {
+ _wait = false;
+ return true;
+}
+
diff --git a/scumm/smush/scumm_renderer.h b/scumm/smush/scumm_renderer.h
new file mode 100644
index 0000000000..097c657c17
--- /dev/null
+++ b/scumm/smush/scumm_renderer.h
@@ -0,0 +1,66 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2001/2002 The ScummVM project
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Header$
+ *
+ */
+
+#ifndef __SCUMM_RENDERER_H_
+#define __SCUMM_RENDERER_H_
+
+#include "config.h"
+
+#ifdef DEBUG
+# ifndef NO_DEBUG_SCUMM_RENDERER
+# define DEBUG_SCUMM_RENDERER
+# endif
+#else
+# ifdef DEBUG_SCUMM_RENDERER
+# error DEBUG_SCUMM_RENDERER defined without DEBUG
+# endif
+#endif
+
+#include "brenderer.h"
+#include "mixer.h"
+#include "rect.h"
+#include "blitter.h"
+
+#ifndef min
+#define min(x, y) ((x) > (y) ? (y) : (x))
+#endif
+
+class scumm_mixer;
+
+class ScummRenderer : public BaseRenderer {
+private:
+ Scumm * _scumm;
+ scumm_mixer * _smixer;
+ volatile bool _wait;
+public:
+ ScummRenderer(Scumm * scumm);
+ virtual ~ScummRenderer();
+ virtual bool wait(int ms);
+ bool update();
+protected:
+ virtual bool startDecode(const char * fname, int version, int nbframes);
+ virtual bool setPalette(const Palette & pal);
+ virtual void save(int frame = -1);
+ virtual Mixer * getMixer();
+ virtual bool prematureClose();
+};
+
+#endif
diff --git a/simon/simon.cpp b/simon/simon.cpp
index 358cc42e98..2e24facc48 100644
--- a/simon/simon.cpp
+++ b/simon/simon.cpp
@@ -128,7 +128,7 @@ SimonState::SimonState(GameDetector *detector, OSystem *syst)
_game = detector->_gameId;
/* Setup mixer */
- if (!_mixer->bind_to_system(syst))
+ if (!_mixer->bindToSystem(syst))
warning("Sound initialization failed. "
"Features of the game that depend on sound synchronization will most likely break");
set_volume(detector->_sfx_volume);
@@ -3296,7 +3296,7 @@ void SimonState::readSfxFile(const char *filename)
fseek(in, 0, SEEK_SET);
/* stop all sounds */
- _mixer->stop_all();
+ _mixer->stopAll();
if (_sfx_heap)
free(_sfx_heap);
@@ -4038,12 +4038,11 @@ void SimonState::read_vga_from_datfile_1(uint vga_id)
FILE *in;
char buf[50];
uint32 size;
-
- // FIXME - weird hack to make the beard show up when wearing it (see bug #590800)
- if (vga_id == 328)
- sprintf(buf, "0119.VGA");
- else
- sprintf(buf, "%.3d%d.VGA", vga_id >> 1, (vga_id & 1) + 1);
+ // FIXME - weird hack to make the beard show up when wearing it (see bug #590800)
+ if (vga_id == 328)
+ sprintf(buf, "0119.VGA");
+ else
+ sprintf(buf, "%.3d%d.VGA", vga_id >> 1, (vga_id & 1) + 1);
in = fopen_maybe_lowercase(buf);
if (in == NULL) {
@@ -4798,7 +4797,7 @@ void SimonState::playVoice(uint voice)
byte *buffer = (byte *)malloc(data[1]);
fread(buffer, data[1], 1, _voice_file);
- _mixer->play_raw(&_voice_sound, buffer, data[1], READ_LE_UINT32(&wave_hdr.samples_per_sec),
+ _mixer->playRaw(&_voice_sound, buffer, data[1], READ_LE_UINT32(&wave_hdr.samples_per_sec),
SoundMixer::FLAG_UNSIGNED);
} else { /* VOC audio */
VocHeader voc_hdr;
@@ -4821,7 +4820,7 @@ void SimonState::playVoice(uint voice)
byte *buffer = (byte *)malloc(size);
fread(buffer, size, 1, _voice_file);
- _mixer->play_raw(&_voice_sound, buffer, size, samples_per_sec, SoundMixer::FLAG_UNSIGNED);
+ _mixer->playRaw(&_voice_sound, buffer, size, samples_per_sec, SoundMixer::FLAG_UNSIGNED);
}
}
@@ -4854,7 +4853,7 @@ void SimonState::playSound(uint sound)
byte *buffer = (byte *)malloc(size);
fread(buffer, size, 1, _effects_file);
- _mixer->play_raw(&_effects_sound, buffer, size, samples_per_sec, SoundMixer::FLAG_UNSIGNED);
+ _mixer->playRaw(&_effects_sound, buffer, size, samples_per_sec, SoundMixer::FLAG_UNSIGNED);
} else {
byte *p;
@@ -4880,7 +4879,7 @@ void SimonState::playSound(uint sound)
p++;
}
- _mixer->play_raw(&_playing_sound, p + 8, READ_LE_UINT32(p + 4), 22050,
+ _mixer->playRaw(&_playing_sound, p + 8, READ_LE_UINT32(p + 4), 22050,
SoundMixer::FLAG_UNSIGNED);
}
} else {
@@ -4938,7 +4937,7 @@ void SimonState::dx_unlock_attached()
void SimonState::set_volume(byte volume)
{
- _mixer->set_volume(volume);
+ _mixer->setVolume(volume);
}
diff --git a/simon/vga.cpp b/simon/vga.cpp
index 39d56d0c85..bbffb53611 100644
--- a/simon/vga.cpp
+++ b/simon/vga.cpp
@@ -1367,7 +1367,7 @@ void SimonState::vc_28()
void SimonState::vc_29_stop_all_sounds()
{
- _mixer->stop_all();
+ _mixer->stopAll();
}
void SimonState::vc_30_set_base_delay()
diff --git a/sound/mididrv.cpp b/sound/mididrv.cpp
index c7825673a5..b1a0cf163d 100644
--- a/sound/mididrv.cpp
+++ b/sound/mididrv.cpp
@@ -1075,7 +1075,7 @@ MidiDriver_MIDIEMU::MidiDriver_MIDIEMU()
int MidiDriver_MIDIEMU::open(int mode)
{
_opl = OPLCreate(OPL_TYPE_YM3812, 3579545, g_system->property(OSystem::PROP_GET_SAMPLE_RATE, 0));
- g_mixer->setup_premix((void *)this, premix_proc);
+ g_mixer->setupPremix((void *)this, premix_proc);
if (_stream_proc)
g_system->create_thread(midiemu_callback_thread, this);
return 0;
diff --git a/sound/mixer.cpp b/sound/mixer.cpp
index 38f25ed6e4..21a606448d 100644
--- a/sound/mixer.cpp
+++ b/sound/mixer.cpp
@@ -23,19 +23,15 @@
#include "stdafx.h"
#include "scumm.h"
-SoundMixer::SoundMixer()
-{
- _volume_table = (int16 *)calloc(256 * sizeof(int16), 1);
+SoundMixer::SoundMixer() {
+ _volumeTable = (int16 *)calloc(256 * sizeof(int16), 1);
}
-SoundMixer::~SoundMixer()
-{
- free(_volume_table);
+SoundMixer::~SoundMixer() {
+ free(_volumeTable);
}
-void SoundMixer::uninsert(Channel * chan)
-{
-
+void SoundMixer::unInsert(Channel * chan) {
for (int i = 0; i != NUM_CHANNELS; i++) {
if (_channels[i] == chan) {
if (_handles[i]) {
@@ -49,14 +45,13 @@ void SoundMixer::uninsert(Channel * chan)
error("SoundMixer::channel_deleted chan not found");
}
-int SoundMixer::append(int index, void *sound, uint32 size, uint rate, byte flags)
-{
+int SoundMixer::append(int index, void * sound, uint32 size, uint rate, byte flags) {
_syst->lock_mutex(_mutex);
- Channel *chan = _channels[index];
+ Channel * chan = _channels[index];
if (!chan) {
- warning("Trying to stream to an unexistant streamer ");
- play_stream(NULL, index, sound, size, rate, flags);
+ warning("Trying to stream to an unexistant streamer : %d", index);
+ playStream(NULL, index, sound, size, rate, flags);
chan = _channels[index];
} else {
chan->append(sound, size);
@@ -68,8 +63,15 @@ int SoundMixer::append(int index, void *sound, uint32 size, uint rate, byte flag
return 1;
}
-int SoundMixer::insert_at(PlayingSoundHandle *handle, int index, Channel * chan)
-{
+int SoundMixer::insertAt(PlayingSoundHandle * handle, int index, Channel * chan) {
+ if(index == -1) {
+ for (int i = 0; i != NUM_CHANNELS; i++)
+ if (_channels[i] == NULL) { index = i; break; }
+ if(index == -1) {
+ warning("SoundMixer::out of mixer slots");
+ return -1;
+ }
+ }
if (_channels[index] != NULL) {
error("Trying to put a mixer where it cannot go ");
}
@@ -80,12 +82,11 @@ int SoundMixer::insert_at(PlayingSoundHandle *handle, int index, Channel * chan)
return index;
}
-int SoundMixer::play_raw(PlayingSoundHandle *handle, void *sound, uint32 size, uint rate,
- byte flags)
-{
+int SoundMixer::playRaw(PlayingSoundHandle * handle, void * sound, uint32 size, uint rate,
+ byte flags) {
for (int i = 0; i != NUM_CHANNELS; i++) {
if (_channels[i] == NULL) {
- return insert_at(handle, i, new Channel_RAW(this, sound, size, rate, flags));
+ return insertAt(handle, i, new ChannelRaw(this, sound, size, rate, flags));
}
}
@@ -93,30 +94,27 @@ int SoundMixer::play_raw(PlayingSoundHandle *handle, void *sound, uint32 size, u
return -1;
}
-int SoundMixer::play_stream(PlayingSoundHandle *handle, int idx, void *sound, uint32 size,
- uint rate, byte flags)
-{
- return insert_at(handle, idx, new Channel_STREAM(this, sound, size, rate, flags));
+int SoundMixer::playStream(PlayingSoundHandle * handle, int idx, void * sound, uint32 size,
+ uint rate, byte flags) {
+ return insertAt(handle, idx, new ChannelStream(this, sound, size, rate, flags));
}
#ifdef COMPRESSED_SOUND_FILE
-int SoundMixer::play_mp3(PlayingSoundHandle *handle, void *sound, uint32 size, byte flags)
-{
+int SoundMixer::playMP3(PlayingSoundHandle * handle, void *sound, uint32 size, byte flags) {
for (int i = 0; i != NUM_CHANNELS; i++) {
if (_channels[i] == NULL) {
- return insert_at(handle, i, new Channel_MP3(this, sound, size, flags));
+ return insertAt(handle, i, new ChannelMP3(this, sound, size, flags));
}
}
warning("SoundMixer::out of mixer slots");
return -1;
}
-int SoundMixer::play_mp3_cdtrack(PlayingSoundHandle *handle, FILE * file, mad_timer_t duration)
-{
+int SoundMixer::playMP3CDTrack(PlayingSoundHandle * handle, FILE * file, mad_timer_t duration) {
/* Stop the previously playing CD track (if any) */
for (int i = 0; i != NUM_CHANNELS; i++) {
if (_channels[i] == NULL) {
- return insert_at(handle, i, new Channel_MP3_CDMUSIC(this, file, duration));
+ return insertAt(handle, i, new ChannelMP3CDMusic(this, file, duration));
}
}
@@ -125,16 +123,15 @@ int SoundMixer::play_mp3_cdtrack(PlayingSoundHandle *handle, FILE * file, mad_ti
}
#endif
-void SoundMixer::mix(int16 *buf, uint len)
-{
+void SoundMixer::mix(int16 *buf, uint len) {
if (_paused) {
memset(buf, 0, 2 * len * sizeof(int16));
return;
}
- if (_premix_proc) {
+ if (_premixProc) {
int i;
- _premix_proc(_premix_param, buf, len);
+ _premixProc(_premixParam, buf, len);
for (i = (len - 1); i >= 0; i--) {
buf[2 * i] = buf[2 * i + 1] = buf[i];
}
@@ -151,16 +148,14 @@ void SoundMixer::mix(int16 *buf, uint len)
_syst->unlock_mutex(_mutex);
}
-void SoundMixer::on_generate_samples(void *s, byte *samples, int len)
-{
+void SoundMixer::onGenerateSamples(void * s, byte * samples, int len) {
((SoundMixer *)s)->mix((int16 *)samples, len >> 2);
}
-bool SoundMixer::bind_to_system(OSystem *syst)
-{
+bool SoundMixer::bindToSystem(OSystem * syst) {
uint rate = (uint) syst->property(OSystem::PROP_GET_SAMPLE_RATE, 0);
- _output_rate = rate;
+ _outputRate = rate;
_syst = syst;
_mutex = _syst->create_mutex();
@@ -168,49 +163,42 @@ bool SoundMixer::bind_to_system(OSystem *syst)
if (rate == 0)
error("OSystem returned invalid sample rate");
- return syst->set_sound_proc(this, on_generate_samples, OSystem::SOUND_16BIT);
+ return syst->set_sound_proc(this, onGenerateSamples, OSystem::SOUND_16BIT);
}
-void SoundMixer::stop_all()
-{
+void SoundMixer::stopAll() {
for (int i = 0; i != NUM_CHANNELS; i++)
if (_channels[i])
_channels[i]->destroy();
}
-void SoundMixer::stop(PlayingSoundHandle psh)
-{
+void SoundMixer::stop(PlayingSoundHandle psh) {
if (psh && _channels[psh - 1])
_channels[psh - 1]->destroy();
}
-void SoundMixer::stop(int index)
-{
+void SoundMixer::stop(int index) {
if (_channels[index])
_channels[index]->destroy();
}
-void SoundMixer::pause(bool paused)
-{
+void SoundMixer::pause(bool paused) {
_paused = paused;
}
-bool SoundMixer::has_active_channel()
-{
+bool SoundMixer::hasActiveChannel() {
for (int i = 0; i != NUM_CHANNELS; i++)
if (_channels[i])
return true;
return false;
}
-void SoundMixer::setup_premix(void *param, PremixProc *proc)
-{
- _premix_param = param;
- _premix_proc = proc;
+void SoundMixer::setupPremix(void * param, PremixProc * proc) {
+ _premixParam = param;
+ _premixProc = proc;
}
-void SoundMixer::set_volume(int volume)
-{
+void SoundMixer::setVolume(int volume) {
int i;
// Check range
@@ -221,55 +209,51 @@ void SoundMixer::set_volume(int volume)
// The volume table takes 8 bit unsigned data as index and returns 16 bit signed
for (i = 0; i < 128; i++)
- _volume_table[i] = i * volume;
+ _volumeTable[i] = i * volume;
for (i = -128; i < 0; i++)
- _volume_table[i+256] = i * volume;
+ _volumeTable[i + 256] = i * volume;
}
-void SoundMixer::set_music_volume(int volume)
-{
+void SoundMixer::setMusicVolume(int volume) {
// Check range
if (volume > 256)
volume = 256;
else if (volume < 0)
volume = 0;
- _music_volume = volume;
+ _musicVolume = volume;
}
#ifdef COMPRESSED_SOUND_FILE
-bool SoundMixer::Channel::sound_finished()
-{
+bool SoundMixer::Channel::soundFinished() {
warning("sound_finished should never be called on a non-MP3 mixer ");
return false;
}
#endif
-void SoundMixer::Channel::append(void *sound, uint32 size)
-{
+void SoundMixer::Channel::append(void * sound, uint32 size) {
error("append method should never be called on something else than a _STREAM mixer ");
}
/* RAW mixer */
-SoundMixer::Channel_RAW::Channel_RAW(SoundMixer *mixer, void *sound, uint32 size, uint rate,
- byte flags)
-{
+SoundMixer::ChannelRaw::ChannelRaw(SoundMixer * mixer, void * sound, uint32 size, uint rate,
+ byte flags) {
_mixer = mixer;
_flags = flags;
_ptr = sound;
_pos = 0;
- _fp_pos = 0;
- _fp_speed = (1 << 16) * rate / mixer->_output_rate;
- _to_be_destroyed = false;
- _realsize = size;
+ _fpPos = 0;
+ _fpSpeed = (1 << 16) * rate / mixer->_outputRate;
+ _toBeDestroyed = false;
+ _realSize = size;
// adjust the magnitude to prevent division error
while (size & 0xFFFF0000)
size >>= 1, rate = (rate >> 1) + 1;
_rate = rate;
- _size = size * mixer->_output_rate / rate;
+ _size = size * mixer->_outputRate / rate;
if (_flags & FLAG_16BITS)
_size = _size >> 1;
if (_flags & FLAG_STEREO)
@@ -288,7 +272,7 @@ protected:
int a, b, c, d;
public:
- CubicInterpolator(int a, int b, int c) : x0(2*a-b), x1(a), x2(b), x3(c)
+ CubicInterpolator(int a, int b, int c) : x0(2 * a - b), x1(a), x2(b), x3(c)
{
// We use a simple linear interpolation for x0
updateCoefficients();
@@ -299,7 +283,7 @@ public:
x0 = x1;
x1 = x2;
x2 = x3;
- x3 = 2*x2-x1; // Simple linear interpolation
+ x3 = 2 * x2 - x1; // Simple linear interpolation
updateCoefficients();
}
@@ -313,14 +297,14 @@ public:
}
/* t must be a 16.16 fixed point number between 0 and 1 */
- inline int interpolate(uint32 fp_pos)
+ inline int interpolate(uint32 fpPos)
{
int result = 0;
- int t = fp_pos >> 8;
- result = (a*t + b) >> 8;
+ int t = fpPos >> 8;
+ result = (a * t + b) >> 8;
result = (result * t + c) >> 8;
result = (result * t + d) >> 8;
- result = (result/3 + 1) >> 1;
+ result = (result / 3 + 1) >> 1;
return result;
}
@@ -328,15 +312,14 @@ public:
protected:
inline void updateCoefficients()
{
- a = ((-x0*2)+(x1*5)-(x2*4)+x3);
- b = ((x0+x2-(2*x1))*6) << 8;
- c = ((-4*x0)+x1+(x2*4)-x3) << 8;
- d = (x1*6) << 8;
+ a = ((-x0 * 2) + (x1 * 5) - (x2 * 4) + x3);
+ b = ((x0 + x2 - (2 * x1)) * 6) << 8;
+ c = ((-4 * x0) + x1 + (x2 * 4) - x3) << 8;
+ d = (x1 * 6) << 8;
}
};
-static inline int clamped_add_16(int a, int b)
-{
+static inline int clamped_add_16(int a, int b) {
int val = a + b;
if (val > 32767) {
@@ -347,15 +330,14 @@ static inline int clamped_add_16(int a, int b)
return val;
}
-static int16 *mix_signed_mono_8(int16 *data, uint * len_ptr, byte **s_ptr, uint32 *fp_pos_ptr,
- int fp_speed, const int16 *vol_tab, byte *s_end)
-{
+static int16 * mix_signed_mono_8(int16 * data, uint * len_ptr, byte ** s_ptr, uint32 * fp_pos_ptr,
+ int fp_speed, const int16 * vol_tab, byte * s_end) {
uint32 fp_pos = *fp_pos_ptr;
byte *s = *s_ptr;
uint len = *len_ptr;
int inc = 1, result;
- CubicInterpolator interp(vol_tab[*s], vol_tab[*(s+1)], vol_tab[*(s+2)]);
+ CubicInterpolator interp(vol_tab[*s], vol_tab[*(s + 1)], vol_tab[*(s + 2)]);
do {
do {
@@ -373,8 +355,8 @@ static int16 *mix_signed_mono_8(int16 *data, uint * len_ptr, byte **s_ptr, uint3
fp_pos &= 0x0000FFFF;
} while (!inc && len && (s < s_end));
- if (s+2 < s_end)
- interp.feedData(vol_tab[*(s+2)]);
+ if (s + 2 < s_end)
+ interp.feedData(vol_tab[*(s + 2)]);
else
interp.feedData();
@@ -386,15 +368,15 @@ static int16 *mix_signed_mono_8(int16 *data, uint * len_ptr, byte **s_ptr, uint3
return data;
}
-static int16 *mix_unsigned_mono_8(int16 *data, uint * len_ptr, byte **s_ptr, uint32 *fp_pos_ptr,
- int fp_speed, const int16 *vol_tab, byte *s_end)
-{
+
+static int16 * mix_unsigned_mono_8(int16 * data, uint * len_ptr, byte ** s_ptr, uint32 * fp_pos_ptr,
+ int fp_speed, const int16 * vol_tab, byte * s_end) {
uint32 fp_pos = *fp_pos_ptr;
byte *s = *s_ptr;
uint len = *len_ptr;
int inc = 1, result;
- CubicInterpolator interp(vol_tab[*s ^ 0x80], vol_tab[*(s+1) ^ 0x80], vol_tab[*(s+2) ^ 0x80]);
+ CubicInterpolator interp(vol_tab[*s ^ 0x80], vol_tab[*(s + 1) ^ 0x80], vol_tab[*(s + 2) ^ 0x80]);
do {
do {
@@ -412,8 +394,8 @@ static int16 *mix_unsigned_mono_8(int16 *data, uint * len_ptr, byte **s_ptr, uin
fp_pos &= 0x0000FFFF;
} while (!inc && len && (s < s_end));
- if (s+2 < s_end)
- interp.feedData(vol_tab[*(s+2) ^ 0x80]);
+ if (s + 2 < s_end)
+ interp.feedData(vol_tab[*(s + 2) ^ 0x80]);
else
interp.feedData();
@@ -425,23 +407,22 @@ static int16 *mix_unsigned_mono_8(int16 *data, uint * len_ptr, byte **s_ptr, uin
return data;
}
-static int16 *mix_signed_stereo_8(int16 *data, uint * len_ptr, byte **s_ptr, uint32 *fp_pos_ptr,
- int fp_speed, const int16 *vol_tab, byte *s_end)
-{
+
+static int16 * mix_signed_stereo_8(int16 * data, uint * len_ptr, byte ** s_ptr, uint32 * fp_pos_ptr,
+ int fp_speed, const int16 * vol_tab, byte *s_end) {
warning("Mixing stereo signed 8 bit is not supported yet ");
return data;
}
-static int16 *mix_unsigned_stereo_8(int16 *data, uint * len_ptr, byte **s_ptr, uint32 *fp_pos_ptr,
- int fp_speed, const int16 *vol_tab, byte *s_end)
-{
+static int16 * mix_unsigned_stereo_8(int16 * data, uint * len_ptr, byte ** s_ptr, uint32 * fp_pos_ptr,
+ int fp_speed, const int16 * vol_tab, byte * s_end) {
uint32 fp_pos = *fp_pos_ptr;
byte *s = *s_ptr;
uint len = *len_ptr;
int inc = 1;
- CubicInterpolator left(vol_tab[*s ^ 0x80], vol_tab[*(s+2) ^ 0x80], vol_tab[*(s+4) ^ 0x80]);
- CubicInterpolator right(vol_tab[*(s+1) ^ 0x80], vol_tab[*(s+3) ^ 0x80], vol_tab[*(s+5) ^ 0x80]);
+ CubicInterpolator left(vol_tab[*s ^ 0x80], vol_tab[*(s + 2) ^ 0x80], vol_tab[*(s + 4) ^ 0x80]);
+ CubicInterpolator right(vol_tab[*(s + 1) ^ 0x80], vol_tab[*(s + 3) ^ 0x80], vol_tab[*(s + 5) ^ 0x80]);
do {
do {
@@ -457,9 +438,9 @@ static int16 *mix_unsigned_stereo_8(int16 *data, uint * len_ptr, byte **s_ptr, u
fp_pos &= 0x0000FFFF;
} while (!inc && len && (s < s_end));
- if (s+5 < s_end) {
- left.feedData(vol_tab[*(s+4) ^ 0x80]);
- right.feedData(vol_tab[*(s+5) ^ 0x80]);
+ if (s + 5 < s_end) {
+ left.feedData(vol_tab[*(s + 4) ^ 0x80]);
+ right.feedData(vol_tab[*(s + 5) ^ 0x80]);
} else {
left.feedData();
right.feedData();
@@ -473,9 +454,8 @@ static int16 *mix_unsigned_stereo_8(int16 *data, uint * len_ptr, byte **s_ptr, u
return data;
}
-static int16 *mix_signed_mono_16(int16 *data, uint * len_ptr, byte **s_ptr, uint32 *fp_pos_ptr,
- int fp_speed, const int16 *vol_tab, byte *s_end)
-{
+static int16 * mix_signed_mono_16(int16 * data, uint * len_ptr, byte ** s_ptr, uint32 * fp_pos_ptr,
+ int fp_speed, const int16 * vol_tab, byte * s_end) {
uint32 fp_pos = *fp_pos_ptr;
unsigned char volume = ((int)vol_tab[1]) / 8;
byte *s = *s_ptr;
@@ -499,16 +479,14 @@ static int16 *mix_signed_mono_16(int16 *data, uint * len_ptr, byte **s_ptr, uint
return data;
}
-static int16 *mix_unsigned_mono_16(int16 *data, uint * len_ptr, byte **s_ptr, uint32 *fp_pos_ptr,
- int fp_speed, const int16 *vol_tab, byte *s_end)
-{
+static int16 *mix_unsigned_mono_16(int16 *data, uint * len_ptr, byte ** s_ptr, uint32 * fp_pos_ptr,
+ int fp_speed, const int16 * vol_tab, byte * s_end) {
warning("Mixing mono unsigned 16 bit is not supported yet ");
return data;
}
-static int16 *mix_signed_stereo_16(int16 *data, uint * len_ptr, byte **s_ptr, uint32 *fp_pos_ptr,
- int fp_speed, const int16 *vol_tab, byte *s_end)
-{
+static int16 *mix_signed_stereo_16(int16 * data, uint * len_ptr, byte ** s_ptr, uint32 * fp_pos_ptr,
+ int fp_speed, const int16 * vol_tab, byte * s_end) {
uint32 fp_pos = *fp_pos_ptr;
unsigned char volume = ((int)vol_tab[1]) / 8;
byte *s = *s_ptr;
@@ -531,28 +509,29 @@ static int16 *mix_signed_stereo_16(int16 *data, uint * len_ptr, byte **s_ptr, ui
return data;
}
-static int16 *mix_unsigned_stereo_16(int16 *data, uint * len_ptr, byte **s_ptr, uint32 *fp_pos_ptr,
- int fp_speed, const int16 *vol_tab, byte *s_end)
-{
+static int16 * mix_unsigned_stereo_16(int16 * data, uint * len_ptr, byte ** s_ptr, uint32 * fp_pos_ptr,
+ int fp_speed, const int16 * vol_tab, byte * s_end) {
warning("Mixing stereo unsigned 16 bit is not supported yet ");
return data;
}
-static int16 *(*mixer_helper_table[8]) (int16 *data, uint * len_ptr, byte **s_ptr,
- uint32 *fp_pos_ptr, int fp_speed, const int16 *vol_tab,
- byte *s_end) = {
-mix_signed_mono_8, mix_unsigned_mono_8, mix_signed_stereo_8, mix_unsigned_stereo_8,
- mix_signed_mono_16, mix_unsigned_mono_16, mix_signed_stereo_16, mix_unsigned_stereo_16};
+static int16 * (*mixer_helper_table[8]) (int16 * data, uint * len_ptr, byte ** s_ptr,
+ uint32 * fp_pos_ptr, int fp_speed, const int16 * vol_tab,
+ byte * s_end) = {
+ mix_signed_mono_8, mix_unsigned_mono_8,
+ mix_signed_stereo_8, mix_unsigned_stereo_8,
+ mix_signed_mono_16, mix_unsigned_mono_16,
+ mix_signed_stereo_16, mix_unsigned_stereo_16
+};
-void SoundMixer::Channel_RAW::mix(int16 *data, uint len)
-{
+void SoundMixer::ChannelRaw::mix(int16 * data, uint len) {
byte *s, *s_org = NULL;
uint32 fp_pos;
byte *end;
- if (_to_be_destroyed) {
- real_destroy();
+ if (_toBeDestroyed) {
+ realDestroy();
return;
}
@@ -565,11 +544,11 @@ void SoundMixer::Channel_RAW::mix(int16 *data, uint len)
*/
if (_flags & FLAG_FILE) {
/* determine how many samples to read from the file */
- uint num = len * _fp_speed >> 16;
+ uint num = len * _fpSpeed >> 16;
s_org = (byte *)malloc(num);
if (s_org == NULL)
- error("Channel_RAW::mix out of memory");
+ error("ChannelRaw::mix out of memory");
uint num_read = fread(s_org, 1, num, (FILE *) _ptr);
if (num - num_read != 0)
@@ -580,141 +559,116 @@ void SoundMixer::Channel_RAW::mix(int16 *data, uint len)
end = s_org + num;
} else {
s = (byte *)_ptr + _pos;
- fp_pos = _fp_pos;
- end = (byte *)_ptr + _realsize;
+ fp_pos = _fpPos;
+ end = (byte *)_ptr + _realSize;
}
- const uint32 fp_speed = _fp_speed;
- const int16 *vol_tab = _mixer->_volume_table;
+ const uint32 fp_speed = _fpSpeed;
+ const int16 *vol_tab = _mixer->_volumeTable;
mixer_helper_table[_flags & 0x07] (data, &len, &s, &fp_pos, fp_speed, vol_tab, end);
_pos = s - (byte *)_ptr;
- _fp_pos = fp_pos;
+ _fpPos = fp_pos;
if (_flags & FLAG_FILE) {
free(s_org);
}
if (_size < 1)
- real_destroy();
+ realDestroy();
}
-void SoundMixer::Channel_RAW::real_destroy()
-{
+void SoundMixer::ChannelRaw::realDestroy() {
if (_flags & FLAG_AUTOFREE)
free(_ptr);
- _mixer->uninsert(this);
+ _mixer->unInsert(this);
delete this;
}
-/* STREAM mixer */
-SoundMixer::Channel_STREAM::Channel_STREAM(SoundMixer *mixer, void *sound, uint32 size, uint rate,
- byte flags)
-{
+SoundMixer::ChannelStream::ChannelStream(SoundMixer * mixer, void * sound, uint32 size, uint rate,
+ byte flags) {
_mixer = mixer;
_flags = flags;
- _buffer_size = 1024 * size;
- _ptr = (byte *)malloc(_buffer_size);
+ _bufferSize = 1024 * size;
+ _ptr = (byte *)malloc(_bufferSize);
memcpy(_ptr, sound, size);
- _end_of_data = _ptr + size;
+ _endOfData = _ptr + size;
if (_flags & FLAG_AUTOFREE)
free(sound);
_pos = _ptr;
- _fp_pos = 0;
- _fp_speed = (1 << 16) * rate / mixer->_output_rate;
- _to_be_destroyed = false;
+ _fpPos = 0;
+ _fpSpeed = (1 << 16) * rate / mixer->_outputRate;
+ _toBeDestroyed = false;
/* adjust the magnitute to prevent division error */
while (size & 0xFFFF0000)
size >>= 1, rate = (rate >> 1) + 1;
-
_rate = rate;
}
-void SoundMixer::Channel_STREAM::append(void *data, uint32 len)
-{
- byte *new_end = _end_of_data + len;
+void SoundMixer::ChannelStream::append(void * data, uint32 len) {
+ byte *new_end = _endOfData + len;
byte *cur_pos = _pos; /* This is just to prevent the variable to move during the tests :-) */
- if (new_end > (_ptr + _buffer_size)) {
+ if (new_end > (_ptr + _bufferSize)) {
/* Wrap-around case */
- new_end = _ptr + len - ((_ptr + _buffer_size) - _end_of_data);
- if ((_end_of_data < cur_pos) || (new_end >= cur_pos)) {
+ new_end = _ptr + len - ((_ptr + _bufferSize) - _endOfData);
+ if ((_endOfData < cur_pos) || (new_end >= cur_pos)) {
warning("Mixer full... Trying to not break too much ");
return;
}
- memcpy(_end_of_data, data, (_ptr + _buffer_size) - _end_of_data);
- memcpy(_ptr, (byte *)data + ((_ptr + _buffer_size) - _end_of_data),
- len - ((_ptr + _buffer_size) - _end_of_data));
+ memcpy(_endOfData, data, (_ptr + _bufferSize) - _endOfData);
+ memcpy(_ptr, (byte *)data + ((_ptr + _bufferSize) - _endOfData),
+ len - ((_ptr + _bufferSize) - _endOfData));
} else {
- if ((_end_of_data < cur_pos) && (new_end >= cur_pos)) {
+ if ((_endOfData < cur_pos) && (new_end >= cur_pos)) {
warning("Mixer full... Trying to not break too much ");
return;
}
- memcpy(_end_of_data, data, len);
+ memcpy(_endOfData, data, len);
}
- _end_of_data = new_end;
+ _endOfData = new_end;
}
-void SoundMixer::Channel_STREAM::mix(int16 *data, uint len)
-{
+void SoundMixer::ChannelStream::mix(int16 * data, uint len) {
uint32 fp_pos;
- const uint32 fp_speed = _fp_speed;
- const int16 *vol_tab = _mixer->_volume_table;
- byte *end_of_data = _end_of_data;
+ const uint32 fp_speed = _fpSpeed;
+ const int16 * vol_tab = _mixer->_volumeTable;
+ byte * end_of_data = _endOfData;
- if (_to_be_destroyed) {
- real_destroy();
+ if (_toBeDestroyed) {
+ realDestroy();
return;
}
- fp_pos = _fp_pos;
+ fp_pos = _fpPos;
if (_pos < end_of_data) {
mixer_helper_table[_flags & 0x07] (data, &len, &_pos, &fp_pos, fp_speed, vol_tab, end_of_data);
} else {
-// mixer_helper_table[_flags & 0x07] (data, &len, &_pos, &fp_pos, fp_speed, vol_tab,
-// _ptr + _buffer_size);
-// if (len != 0) {
-// _pos = _ptr;
-// mixer_helper_table[_flags & 0x07] (data, &len, &_pos, &fp_pos, fp_speed, vol_tab,
-// end_of_data);
-// } else
- _to_be_destroyed = true;
+ _toBeDestroyed = true;
}
- if (len != 0) {
- // FIXME: BBrox, what does this mean? :)
- // Commented by Ender to remove non-existant
- // streamer bug in Dig smush movies.
- //warning("Streaming underflow of %d bytes", len);
- //real_destroy();
- //return;
- }
- _fp_pos = fp_pos;
+
+ _fpPos = fp_pos;
}
-void SoundMixer::Channel_STREAM::real_destroy()
-{
+void SoundMixer::ChannelStream::realDestroy() {
free(_ptr);
- _mixer->uninsert(this);
+ _mixer->unInsert(this);
delete this;
}
-
-
-/* MP3 mixer goes here */
#ifdef COMPRESSED_SOUND_FILE
-SoundMixer::Channel_MP3::Channel_MP3(SoundMixer *mixer, void *sound, uint size, byte flags)
-{
+SoundMixer::ChannelMP3::ChannelMP3(SoundMixer * mixer, void * sound, uint size, byte flags) {
_mixer = mixer;
_flags = flags;
- _pos_in_frame = 0xFFFFFFFF;
+ _posInFrame = 0xFFFFFFFF;
_position = 0;
_size = size;
_ptr = sound;
- _to_be_destroyed = false;
+ _toBeDestroyed = false;
mad_stream_init(&_stream);
#ifdef _WIN32_WCE
@@ -735,11 +689,10 @@ SoundMixer::Channel_MP3::Channel_MP3(SoundMixer *mixer, void *sound, uint size,
When using Lame, it seems that the sound starts to have some volume about 50 ms
from the start of the sound => we skip about 2 frames (at 22.05 khz).
*/
- _silence_cut = 576 * 2;
+ _silenceCut = 576 * 2;
}
-static inline int scale_sample(mad_fixed_t sample)
-{
+static inline int scale_sample(mad_fixed_t sample) {
/* round */
sample += (1L << (MAD_F_FRACBITS - 16));
@@ -753,44 +706,43 @@ static inline int scale_sample(mad_fixed_t sample)
return sample >> (MAD_F_FRACBITS + 2 - 16);
}
-void SoundMixer::Channel_MP3::mix(int16 *data, uint len)
-{
- mad_fixed_t const *ch;
- const int16 *vol_tab = _mixer->_volume_table;
+void SoundMixer::ChannelMP3::mix(int16 * data, uint len) {
+ mad_fixed_t const * ch;
+ const int16 * vol_tab = _mixer->_volumeTable;
unsigned char volume = ((int)vol_tab[1]) / 8;
- if (_to_be_destroyed) {
- real_destroy();
+ if (_toBeDestroyed) {
+ realDestroy();
return;
}
while (1) {
- ch = _synth.pcm.samples[0] + _pos_in_frame;
+ ch = _synth.pcm.samples[0] + _posInFrame;
/* Skip _silence_cut a the start */
- if ((_pos_in_frame < _synth.pcm.length) && (_silence_cut > 0)) {
- uint32 diff = _synth.pcm.length - _pos_in_frame;
+ if ((_posInFrame < _synth.pcm.length) && (_silenceCut > 0)) {
+ uint32 diff = _synth.pcm.length - _posInFrame;
- if (diff > _silence_cut)
- diff = _silence_cut;
- _silence_cut -= diff;
+ if (diff > _silenceCut)
+ diff = _silenceCut;
+ _silenceCut -= diff;
ch += diff;
- _pos_in_frame += diff;
+ _posInFrame += diff;
}
- while ((_pos_in_frame < _synth.pcm.length) && (len > 0)) {
+ while ((_posInFrame < _synth.pcm.length) && (len > 0)) {
int16 sample = (int16)((scale_sample(*ch) * volume) / 32);
*data++ += sample;
*data++ += sample;
len--;
ch++;
- _pos_in_frame++;
+ _posInFrame++;
}
if (len == 0)
return;
if (_position >= _size) {
- real_destroy();
+ realDestroy();
return;
}
@@ -800,23 +752,22 @@ void SoundMixer::Channel_MP3::mix(int16 *data, uint len)
if (mad_frame_decode(&_frame, &_stream) == -1) {
/* End of audio... */
if (_stream.error == MAD_ERROR_BUFLEN) {
- real_destroy();
+ realDestroy();
return;
} else if (!MAD_RECOVERABLE(_stream.error)) {
error("MAD frame decode error !");
}
}
mad_synth_frame(&_synth, &_frame);
- _pos_in_frame = 0;
+ _posInFrame = 0;
_position = (unsigned char *)_stream.next_frame - (unsigned char *)_ptr;
}
}
-void SoundMixer::Channel_MP3::real_destroy()
-{
+void SoundMixer::ChannelMP3::realDestroy() {
if (_flags & FLAG_AUTOFREE)
free(_ptr);
- _mixer->uninsert(this);
+ _mixer->unInsert(this);
mad_synth_finish(&_synth);
mad_frame_finish(&_frame);
mad_stream_finish(&_stream);
@@ -824,19 +775,17 @@ void SoundMixer::Channel_MP3::real_destroy()
delete this;
}
-/* MP3 CD music */
#define MP3CD_BUFFERING_SIZE 131072
-SoundMixer::Channel_MP3_CDMUSIC::Channel_MP3_CDMUSIC(SoundMixer *mixer, FILE * file,
- mad_timer_t duration)
-{
+SoundMixer::ChannelMP3CDMusic::ChannelMP3CDMusic(SoundMixer * mixer, FILE * file,
+ mad_timer_t duration){
_mixer = mixer;
_file = file;
_duration = duration;
_initialized = false;
- _buffer_size = MP3CD_BUFFERING_SIZE;
+ _bufferSize = MP3CD_BUFFERING_SIZE;
_ptr = malloc(MP3CD_BUFFERING_SIZE);
- _to_be_destroyed = false;
+ _toBeDestroyed = false;
mad_stream_init(&_stream);
#ifdef _WIN32_WCE
@@ -847,24 +796,23 @@ SoundMixer::Channel_MP3_CDMUSIC::Channel_MP3_CDMUSIC(SoundMixer *mixer, FILE * f
mad_synth_init(&_synth);
}
-void SoundMixer::Channel_MP3_CDMUSIC::mix(int16 *data, uint len)
-{
+void SoundMixer::ChannelMP3CDMusic::mix(int16 * data, uint len) {
mad_fixed_t const *ch;
mad_timer_t frame_duration;
- unsigned char volume = _mixer->_music_volume / 8;
+ unsigned char volume = _mixer->_musicVolume / 8;
- if (_to_be_destroyed) {
- real_destroy();
+ if (_toBeDestroyed) {
+ realDestroy();
return;
}
if (!_initialized) {
int skip_loop;
// just skipped
- memset(_ptr, 0, _buffer_size);
- _size = fread(_ptr, 1, _buffer_size, _file);
+ memset(_ptr, 0, _bufferSize);
+ _size = fread(_ptr, 1, _bufferSize, _file);
if (!_size) {
- real_destroy();
+ realDestroy();
return;
}
// Resync
@@ -880,7 +828,7 @@ void SoundMixer::Channel_MP3_CDMUSIC::mix(int16 *data, uint len)
} else {
if (!MAD_RECOVERABLE(_stream.error)) {
debug(1, "Unrecoverable error while skipping !");
- real_destroy();
+ realDestroy();
return;
}
}
@@ -890,24 +838,24 @@ void SoundMixer::Channel_MP3_CDMUSIC::mix(int16 *data, uint len)
mad_synth_mute(&_synth);
// Resume decoding
if (mad_frame_decode(&_frame, &_stream) == 0) {
- _pos_in_frame = 0;
+ _posInFrame = 0;
_initialized = true;
} else {
debug(1, "Cannot resume decoding");
- real_destroy();
+ realDestroy();
return;
}
}
while (1) {
// Get samples, play samples ...
- ch = _synth.pcm.samples[0] + _pos_in_frame;
- while ((_pos_in_frame < _synth.pcm.length) && (len > 0)) {
+ ch = _synth.pcm.samples[0] + _posInFrame;
+ while ((_posInFrame < _synth.pcm.length) && (len > 0)) {
int16 sample = (int16)((scale_sample(*ch++) * volume) / 32);
*data++ += sample;
*data++ += sample;
len--;
- _pos_in_frame++;
+ _posInFrame++;
}
if (len == 0) {
return;
@@ -923,13 +871,13 @@ void SoundMixer::Channel_MP3_CDMUSIC::mix(int16 *data, uint len)
int not_decoded;
if (!_stream.next_frame) {
- memset(_ptr, 0, _buffer_size + MAD_BUFFER_GUARD);
- _size = fread(_ptr, 1, _buffer_size, _file);
+ memset(_ptr, 0, _bufferSize + MAD_BUFFER_GUARD);
+ _size = fread(_ptr, 1, _bufferSize, _file);
not_decoded = 0;
} else {
not_decoded = _stream.bufend - _stream.next_frame;
memcpy(_ptr, _stream.next_frame, not_decoded);
- _size = fread((unsigned char *)_ptr + not_decoded, 1, _buffer_size - not_decoded, _file);
+ _size = fread((unsigned char *)_ptr + not_decoded, 1, _bufferSize - not_decoded, _file);
}
_stream.error = (enum mad_error)0;
// Restream
@@ -942,19 +890,17 @@ void SoundMixer::Channel_MP3_CDMUSIC::mix(int16 *data, uint len)
}
}
mad_synth_frame(&_synth, &_frame);
- _pos_in_frame = 0;
+ _posInFrame = 0;
}
}
-bool SoundMixer::Channel_MP3_CDMUSIC::sound_finished()
-{
+bool SoundMixer::ChannelMP3CDMusic::soundFinished() {
return mad_timer_compare(_duration, mad_timer_zero) <= 0;
}
-void SoundMixer::Channel_MP3_CDMUSIC::real_destroy()
-{
+void SoundMixer::ChannelMP3CDMusic::realDestroy() {
free(_ptr);
- _mixer->uninsert(this);
+ _mixer->unInsert(this);
mad_synth_finish(&_synth);
mad_frame_finish(&_frame);
mad_stream_finish(&_stream);
@@ -962,5 +908,4 @@ void SoundMixer::Channel_MP3_CDMUSIC::real_destroy()
delete this;
}
-
#endif
diff --git a/sound/mixer.h b/sound/mixer.h
index 9ce371acd7..19c0414fcd 100644
--- a/sound/mixer.h
+++ b/sound/mixer.h
@@ -30,110 +30,112 @@
#endif
typedef uint32 PlayingSoundHandle;
+
class SoundMixer {
private:
class Channel {
public:
- bool _to_be_destroyed;
+ bool _toBeDestroyed;
virtual void mix(int16 *data, uint len) = 0;
void destroy() {
- _to_be_destroyed = true;
- } virtual void real_destroy() = 0;
+ _toBeDestroyed = true;
+ }
+ virtual void realDestroy() = 0;
virtual void append(void *sound, uint32 size);
#ifdef COMPRESSED_SOUND_FILE
- virtual bool sound_finished();
+ virtual bool soundFinished();
#endif
};
- class Channel_RAW:public Channel {
- SoundMixer *_mixer;
- void *_ptr;
+ class ChannelRaw : public Channel {
+ SoundMixer * _mixer;
+ void * _ptr;
uint32 _pos;
uint32 _size;
- uint32 _fp_speed;
- uint32 _fp_pos;
- uint32 _realsize, _rate;
+ uint32 _fpSpeed;
+ uint32 _fpPos;
+ uint32 _realSize, _rate;
byte _flags;
-
public:
- void mix(int16 *data, uint len);
- Channel_RAW(SoundMixer *mixer, void *sound, uint32 size, uint rate, byte flags);
- void real_destroy();
+ ChannelRaw(SoundMixer * mixer, void * sound, uint32 size, uint rate, byte flags);
+ void mix(int16 * data, uint len);
+ void realDestroy();
};
- class Channel_STREAM:public Channel {
- SoundMixer *_mixer;
- byte *_ptr;
- byte *_end_of_data;
- byte *_pos;
- uint32 _fp_speed;
- uint32 _fp_pos;
- uint32 _buffer_size;
+ class ChannelStream : public Channel {
+ SoundMixer * _mixer;
+ byte * _ptr;
+ byte * _endOfData;
+ byte * _pos;
+ uint32 _fpSpeed;
+ uint32 _fpPos;
+ uint32 _bufferSize;
uint32 _rate;
byte _flags;
public:
- void append(void *sound, uint32 size);
- void mix(int16 *data, uint len);
- Channel_STREAM(SoundMixer *mixer, void *sound, uint32 size, uint rate, byte flags);
- void real_destroy();
+ ChannelStream(SoundMixer * mixer, void * sound, uint32 size, uint rate, byte flags);
+ void append(void * sound, uint32 size);
+ void mix(int16 * data, uint len);
+ void realDestroy();
};
#ifdef COMPRESSED_SOUND_FILE
- class Channel_MP3:public Channel {
- SoundMixer *_mixer;
+ class ChannelMP3 : public Channel {
+ SoundMixer * _mixer;
void *_ptr;
struct mad_stream _stream;
struct mad_frame _frame;
struct mad_synth _synth;
- uint32 _silence_cut;
- uint32 _pos_in_frame;
+ uint32 _silenceCut;
+ uint32 _posInFrame;
uint32 _position;
uint32 _size;
byte _flags;
public:
- void mix(int16 *data, uint len);
- Channel_MP3(SoundMixer *mixer, void *sound, uint size, byte flags);
- void real_destroy();
+ ChannelMP3(SoundMixer * mixer, void *sound, uint size, byte flags);
+ void mix(int16 * data, uint len);
+ void realDestroy();
};
- class Channel_MP3_CDMUSIC:public Channel {
- SoundMixer *_mixer;
- void *_ptr;
+ class ChannelMP3CDMusic:public Channel {
+ SoundMixer * _mixer;
+ void * _ptr;
struct mad_stream _stream;
struct mad_frame _frame;
struct mad_synth _synth;
- uint32 _pos_in_frame;
+ uint32 _posInFrame;
uint32 _size;
- uint32 _buffer_size;
+ uint32 _bufferSize;
mad_timer_t _duration;
- FILE *_file;
+ FILE * _file;
bool _initialized;
+
public:
- void mix(int16 *data, uint len);
- Channel_MP3_CDMUSIC(SoundMixer *mixer, FILE * file, mad_timer_t duration);
- void real_destroy();
- bool sound_finished();
+ ChannelMP3CDMusic(SoundMixer * mixer, FILE * file, mad_timer_t duration);
+ void mix(int16 * data, uint len);
+ void realDestroy();
+ bool soundFinished();
};
#endif
- static void on_generate_samples(void *s, byte *samples, int len);
+ static void onGenerateSamples(void * s, byte * samples, int len);
public:
- typedef void PremixProc (void *param, int16 *data, uint len);
+ typedef void PremixProc (void * param, int16 * data, uint len);
- OSystem *_syst;
- void *_mutex;
+ OSystem * _syst;
+ void * _mutex;
- uint _output_rate;
+ uint _outputRate;
- int16 *_volume_table;
- int _music_volume;
+ int16 * _volumeTable;
+ int _musicVolume;
bool _paused;
@@ -141,18 +143,18 @@ public:
NUM_CHANNELS = 16,
};
- void *_premix_param;
- PremixProc *_premix_proc;
+ void * _premixParam;
+ PremixProc * _premixProc;
- Channel *_channels[NUM_CHANNELS];
- PlayingSoundHandle *_handles[NUM_CHANNELS];
+ Channel * _channels[NUM_CHANNELS];
+ PlayingSoundHandle * _handles[NUM_CHANNELS];
SoundMixer();
~SoundMixer();
- int insert_at(PlayingSoundHandle *handle, int index, Channel * chan);
- void append(void *data, uint32 len);
- void uninsert(Channel * chan);
+ int insertAt(PlayingSoundHandle * handle, int index, Channel * chan);
+ void append(void * data, uint32 len);
+ void unInsert(Channel * chan);
/* start playing a raw sound */
enum {
@@ -163,41 +165,41 @@ public:
FLAG_AUTOFREE = 8, /* sound buffer is freed automagically at the end of playing */
FLAG_FILE = 16, /* sound is a FILE * that's read from */
};
- int play_raw(PlayingSoundHandle *handle, void *sound, uint32 size, uint rate, byte flags);
- int play_stream(PlayingSoundHandle *handle, int index, void *sound, uint32 size, uint rate,
+ int playRaw(PlayingSoundHandle * handle, void * sound, uint32 size, uint rate, byte flags);
+ int playStream(PlayingSoundHandle * handle, int index, void * sound, uint32 size, uint rate,
byte flags);
#ifdef COMPRESSED_SOUND_FILE
- int play_mp3(PlayingSoundHandle *handle, void *sound, uint32 size, byte flags);
- int play_mp3_cdtrack(PlayingSoundHandle *handle, FILE * file, mad_timer_t duration);
+ int playMP3(PlayingSoundHandle * handle, void * sound, uint32 size, byte flags);
+ int playMP3CDTrack(PlayingSoundHandle * handle, FILE * file, mad_timer_t duration);
#endif
/* Premix procedure, useful when using fmopl adlib */
- void setup_premix(void *param, PremixProc *proc);
+ void setupPremix(void * param, PremixProc * proc);
/* mix */
- void mix(int16 *buf, uint len);
+ void mix(int16 * buf, uint len);
/* stop all currently playing sounds */
- void stop_all();
+ void stopAll();
/* stop playing a specific sound */
void stop(PlayingSoundHandle psh);
void stop(int index);
/* append to existing sound */
- int append(int index, void *sound, uint32 size, uint rate, byte flags);
+ int append(int index, void * sound, uint32 size, uint rate, byte flags);
/* is any channel active? */
- bool has_active_channel();
+ bool hasActiveChannel();
/* bind to the OSystem object => mixer will be
* invoked automatically when samples need
* to be generated */
- bool bind_to_system(OSystem *syst);
+ bool bindToSystem(OSystem *syst);
/* set the volume, 0-256 */
- void set_volume(int volume);
- void set_music_volume(int volume);
+ void setVolume(int volume);
+ void setMusicVolume(int volume);
/* pause - unpause */
void pause(bool paused);
diff --git a/sound/sound.cpp b/sound/sound.cpp
index a096774842..8015ef9ba6 100644
--- a/sound/sound.cpp
+++ b/sound/sound.cpp
@@ -137,19 +137,19 @@ void Sound::processSoundQues() {
byte * buffer = (byte*)malloc (size);
memcpy(buffer, ptr, size);
if (chan == 1) {
- _scumm->_mixer->play_raw(NULL, buffer, size, rate, SoundMixer::FLAG_AUTOFREE | SoundMixer::FLAG_UNSIGNED);
+ _scumm->_mixer->playRaw(NULL, buffer, size, rate, SoundMixer::FLAG_AUTOFREE | SoundMixer::FLAG_UNSIGNED);
}
else if (chan == 2) {
- _scumm->_mixer->play_raw(NULL, buffer, size, rate, SoundMixer::FLAG_AUTOFREE | SoundMixer::FLAG_UNSIGNED | SoundMixer::FLAG_STEREO);
+ _scumm->_mixer->playRaw(NULL, buffer, size, rate, SoundMixer::FLAG_AUTOFREE | SoundMixer::FLAG_UNSIGNED | SoundMixer::FLAG_STEREO);
}
} else if (bits == 12) {
byte * buffer = NULL;
uint32 final_size = decode12BitsSample(ptr, &buffer, size);
if (chan == 1) {
- _scumm->_mixer->play_raw(NULL, buffer, final_size, rate, SoundMixer::FLAG_AUTOFREE | SoundMixer::FLAG_16BITS);
+ _scumm->_mixer->playRaw(NULL, buffer, final_size, rate, SoundMixer::FLAG_AUTOFREE | SoundMixer::FLAG_16BITS);
}
else if (chan == 2) {
- _scumm->_mixer->play_raw(NULL, buffer, final_size, rate, SoundMixer::FLAG_AUTOFREE | SoundMixer::FLAG_16BITS | SoundMixer::FLAG_STEREO);
+ _scumm->_mixer->playRaw(NULL, buffer, final_size, rate, SoundMixer::FLAG_AUTOFREE | SoundMixer::FLAG_16BITS | SoundMixer::FLAG_STEREO);
}
}
}
@@ -249,7 +249,7 @@ void Sound::playSound(int sound) {
// Allocate a sound buffer, copy the data into it, and play
char *sound = (char*)malloc(size);
memcpy(sound, ptr, size);
- _scumm->_mixer->play_raw(NULL, sound, size, rate, SoundMixer::FLAG_UNSIGNED | SoundMixer::FLAG_AUTOFREE);
+ _scumm->_mixer->playRaw(NULL, sound, size, rate, SoundMixer::FLAG_UNSIGNED | SoundMixer::FLAG_AUTOFREE);
return;
}
// Support for Putt-Putt sounds - very hackish, too 8-)
@@ -265,15 +265,15 @@ void Sound::playSound(int sound) {
// Allocate a sound buffer, copy the data into it, and play
char *sound = (char*)malloc(size);
- memcpy(sound, ptr+8, size);
- _scumm->_mixer->play_raw(NULL, sound, size, rate, SoundMixer::FLAG_UNSIGNED | SoundMixer::FLAG_AUTOFREE);
+ memcpy(sound, ptr + 8, size);
+ _scumm->_mixer->playRaw(NULL, sound, size, rate, SoundMixer::FLAG_UNSIGNED | SoundMixer::FLAG_AUTOFREE);
return;
}
else if (ptr != NULL && READ_UINT32_UNALIGNED(ptr) == MKID('Crea')) {
int size, rate;
char * sound = read_creative_voc_file(ptr, size, rate);
if(sound != NULL) {
- _scumm->_mixer->play_raw(NULL, sound, size, rate, SoundMixer::FLAG_UNSIGNED | SoundMixer::FLAG_AUTOFREE);
+ _scumm->_mixer->playRaw(NULL, sound, size, rate, SoundMixer::FLAG_UNSIGNED | SoundMixer::FLAG_AUTOFREE);
}
return;
}
@@ -310,7 +310,7 @@ void Sound::playSound(int sound) {
// Allocate a sound buffer, copy the data into it, and play
char *sound = (char*)malloc(size);
memcpy(sound, ptr + 33, size);
- _scumm->_mixer->play_raw(NULL, sound, size, rate, SoundMixer::FLAG_UNSIGNED | SoundMixer::FLAG_AUTOFREE);
+ _scumm->_mixer->playRaw(NULL, sound, size, rate, SoundMixer::FLAG_UNSIGNED | SoundMixer::FLAG_AUTOFREE);
return;
}
@@ -386,7 +386,7 @@ void Sound::playSound(int sound) {
// FIXME: Something in the header signifies looping. Need to track it down and add a
// mixer flag or something.
- _scumm->_mixer->play_raw(NULL, sound, size, 11000, SoundMixer::FLAG_UNSIGNED | SoundMixer::FLAG_AUTOFREE);
+ _scumm->_mixer->playRaw(NULL, sound, size, 11000, SoundMixer::FLAG_UNSIGNED | SoundMixer::FLAG_AUTOFREE);
return;
}
@@ -676,8 +676,8 @@ void Sound::setupSound() {
_scumm->_imuse->set_master_volume(_sound_volume_master);
_scumm->_imuse->set_music_volume(_sound_volume_music);
- _scumm->_mixer->set_volume(_sound_volume_sfx);
- _scumm->_mixer->set_music_volume(_sound_volume_music);
+ _scumm->_mixer->setVolume(_sound_volume_sfx);
+ _scumm->_mixer->setMusicVolume(_sound_volume_music);
}
_sfxFile = openSfxFile();
}
@@ -833,12 +833,12 @@ void * Sound::openSfxFile() {
}
void Sound::stopSfxSound() {
- _scumm->_mixer->stop_all();
+ _scumm->_mixer->stopAll();
}
bool Sound::isSfxFinished() {
- return !_scumm->_mixer->has_active_channel();
+ return !_scumm->_mixer->hasActiveChannel();
}
uint32 Sound::decode12BitsSample(byte * src, byte ** dst, uint32 size) {
@@ -985,7 +985,7 @@ void Sound::bundleMusicHandler(Scumm * scumm) {
byte * buffer = NULL;
uint32 final_size = decode12BitsSample(ptr, &buffer, size);
- _scumm->_mixer->play_raw(NULL, buffer, final_size, rate, SoundMixer::FLAG_AUTOFREE | SoundMixer::FLAG_16BITS | SoundMixer::FLAG_STEREO);
+ _scumm->_mixer->playRaw(NULL, buffer, final_size, rate, SoundMixer::FLAG_AUTOFREE | SoundMixer::FLAG_16BITS | SoundMixer::FLAG_STEREO);
}
void Sound::playBundleSound(char *sound) {
@@ -1042,7 +1042,7 @@ void Sound::playBundleSound(char *sound) {
byte * final = (byte *)malloc(size);
memcpy(final, ptr, size);
- _scumm->_mixer->play_raw(NULL, final, size, rate, SoundMixer::FLAG_UNSIGNED | SoundMixer::FLAG_AUTOFREE);
+ _scumm->_mixer->playRaw(NULL, final, size, rate, SoundMixer::FLAG_UNSIGNED | SoundMixer::FLAG_AUTOFREE);
}
int Sound::playSfxSound(void *sound, uint32 size, uint rate, bool isUnsigned) {
@@ -1051,14 +1051,14 @@ int Sound::playSfxSound(void *sound, uint32 size, uint rate, bool isUnsigned) {
byte flags = SoundMixer::FLAG_AUTOFREE;
if (isUnsigned)
flags |= SoundMixer::FLAG_UNSIGNED;
- return _scumm->_mixer->play_raw(NULL, sound, size, rate, flags);
+ return _scumm->_mixer->playRaw(NULL, sound, size, rate, flags);
}
int Sound::playSfxSound_MP3(void *sound, uint32 size) {
#ifdef COMPRESSED_SOUND_FILE
if (_soundsPaused)
return -1;
- return _scumm->_mixer->play_mp3(NULL, sound, size, SoundMixer::FLAG_AUTOFREE);
+ return _scumm->_mixer->playMP3(NULL, sound, size, SoundMixer::FLAG_AUTOFREE);
#endif
return -1;
}
@@ -1200,7 +1200,7 @@ int Sound::playMP3CDTrack(int track, int num_loops, int start, int delay) {
if (_mp3_cd_playing == true)
_scumm->_mixer->stop(_mp3_index);
- _mp3_index = _scumm->_mixer->play_mp3_cdtrack(NULL, _mp3_tracks[index], duration);
+ _mp3_index = _scumm->_mixer->playMP3CDTrack(NULL, _mp3_tracks[index], duration);
_mp3_cd_playing = true;
return 0;
}
@@ -1229,7 +1229,7 @@ int Sound::updateMP3CD() {
return -1;
}
- if (_scumm->_mixer->_channels[_mp3_index]->sound_finished())
+ if (_scumm->_mixer->_channels[_mp3_index]->soundFinished())
stopMP3CD();
return 0;
}