aboutsummaryrefslogtreecommitdiff
path: root/engines/gob
diff options
context:
space:
mode:
Diffstat (limited to 'engines/gob')
-rw-r--r--engines/gob/cdrom.cpp6
-rw-r--r--engines/gob/game.cpp4
-rw-r--r--engines/gob/game.h5
-rw-r--r--engines/gob/gob.cpp11
-rw-r--r--engines/gob/gob.h2
-rw-r--r--engines/gob/goblin.cpp164
-rw-r--r--engines/gob/goblin.h4
-rw-r--r--engines/gob/goblin_v2.cpp164
-rw-r--r--engines/gob/inter.h3
-rw-r--r--engines/gob/inter_v2.cpp244
-rw-r--r--engines/gob/mult_v2.cpp15
-rw-r--r--engines/gob/music.cpp212
-rw-r--r--engines/gob/music.h131
-rw-r--r--engines/gob/sound.cpp14
14 files changed, 495 insertions, 484 deletions
diff --git a/engines/gob/cdrom.cpp b/engines/gob/cdrom.cpp
index 8661d3515a..75e9d7bd66 100644
--- a/engines/gob/cdrom.cpp
+++ b/engines/gob/cdrom.cpp
@@ -158,7 +158,7 @@ void CDROM::startTrack(const char *trackname) {
if (!_LICbuffer)
return;
- debugC(1, kDebugMusic, "startTrack(%s)", trackname);
+ debugC(1, kDebugMusic, "CDROM::startTrack(%s)", trackname);
matchPtr = 0;
curPtr = _LICbuffer;
@@ -200,7 +200,7 @@ void CDROM::play(uint32 from, uint32 to) {
// HSG encodes frame information into a double word:
// minute multiplied by 4500, plus second multiplied by 75,
// plus frame, minus 150
- debugC(1, kDebugMusic, "play(%d, %d)", from, to);
+ debugC(1, kDebugMusic, "CDROM::play(%d, %d)", from, to);
AudioCD.play(1, 1, from, to - from + 1);
_cdPlaying = true;
@@ -226,7 +226,7 @@ void CDROM::stopPlaying(void) {
}
void CDROM::stop(void) {
- debugC(1, kDebugMusic, "stop()");
+ debugC(1, kDebugMusic, "CDROM::stop()");
AudioCD.stop();
_cdPlaying = false;
diff --git a/engines/gob/game.cpp b/engines/gob/game.cpp
index 2ddec2fa56..f96c2e8a45 100644
--- a/engines/gob/game.cpp
+++ b/engines/gob/game.cpp
@@ -72,6 +72,8 @@ Game::Game(GobEngine *vm) : _vm(vm) {
_soundFromExt[i] = 0;
_soundADL[i] = false;
}
+ _infIns = 0;
+ _infogrames = 0;
_curTotFile[0] = 0;
_curExtFile[0] = 0;
@@ -148,6 +150,8 @@ Game::~Game() {
delete[] _imdVidBuffer;
if (_word_2FC80)
delete[] _word_2FC80;
+ if (_infIns)
+ delete _infIns;
}
char *Game::loadExtData(int16 itemId, int16 *pResWidth, int16 *pResHeight, uint32 *dataSize) {
diff --git a/engines/gob/game.h b/engines/gob/game.h
index 9bdd15049f..1b7ba19834 100644
--- a/engines/gob/game.h
+++ b/engines/gob/game.h
@@ -24,6 +24,7 @@
#define GOB_GAME_H
#include "gob/sound.h"
+#include "gob/music.h"
#include "gob/video.h"
namespace Gob {
@@ -151,6 +152,10 @@ public:
char _soundFromExt[60];
bool _soundADL[60];
+ Infogrames::Instruments *_infIns;
+ Infogrames *_infogrames;
+ Audio::SoundHandle _infHandle;
+
char _totToLoad[20];
int32 _startTimeKey;
diff --git a/engines/gob/gob.cpp b/engines/gob/gob.cpp
index c4d6242d7f..122fc4ecfa 100644
--- a/engines/gob/gob.cpp
+++ b/engines/gob/gob.cpp
@@ -226,10 +226,6 @@ GobEngine::~GobEngine() {
delete _util;
if (_adlib)
delete _adlib;
- if (_infogrames) {
- _infogrames->unload(true);
- delete _infogrames;
- }
delete _video;
delete[] _startTot;
delete[] _startTot0;
@@ -687,7 +683,6 @@ uint32 GobEngine::readDataEndian(Common::InSaveFile &in, char *varBuf, byte *siz
}
int GobEngine::init() {
- _infogrames = 0;
_adlib = 0;
_snd = new Snd(this);
_global = new Global(this);
@@ -724,9 +719,11 @@ int GobEngine::init() {
}
else
error("GobEngine::init(): Unknown version of game engine");
+ _noMusic = MidiDriver::parseMusicDriver(ConfMan.get("music_driver")) == MD_NULL;
if (!(_features & Gob::GF_AMIGA) &&
- ((_features & Gob::GF_MAC) || (_features & Gob::GF_GOB1) || (_features & Gob::GF_GOB2))) {
- if (MidiDriver::parseMusicDriver(ConfMan.get("music_driver")) == MD_NULL)
+ (((_features & Gob::GF_MAC) && (_features & Gob::GF_GOB1)) ||
+ (_features & Gob::GF_GOB2))) {
+ if (_noMusic)
_adlib = new Adlib_Dummy(this);
else
_adlib = new Adlib(this);
diff --git a/engines/gob/gob.h b/engines/gob/gob.h
index 3c79908971..aa248febe2 100644
--- a/engines/gob/gob.h
+++ b/engines/gob/gob.h
@@ -146,6 +146,7 @@ public:
char *_startTot;
char *_startTot0;
bool _copyProtection;
+ bool _noMusic;
bool _quitRequested;
Game *_game;
@@ -168,7 +169,6 @@ public:
Util *_util;
Inter *_inter;
Adlib *_adlib;
- Infogrames *_infogrames;
GobEngine *_vm;
void writeVarDebug(uint32 offs, uint32 v);
diff --git a/engines/gob/goblin.cpp b/engines/gob/goblin.cpp
index 7ed4f0b8d4..223835049d 100644
--- a/engines/gob/goblin.cpp
+++ b/engines/gob/goblin.cpp
@@ -1793,170 +1793,6 @@ void Goblin::playSounds(Mult::Mult_Object *obj) {
}
-void Goblin::sub_19BD3(void) {
- Mult::Mult_Object *obj0;
- Mult::Mult_Object *obj1;
- Mult::Mult_AnimData *anim0;
- Mult::Mult_AnimData *anim1;
- int16 pass;
- int16 gob1X;
- int16 gob2X;
- int16 gob1Y;
- int16 gob2Y;
- int16 var_A;
- int16 var_C;
- int16 di;
- int16 si;
-
- obj0 = &_vm->_mult->_objects[0];
- obj1 = &_vm->_mult->_objects[1];
- anim0 = obj0->pAnimData;
- anim1 = obj1->pAnimData;
-
- si = anim0->state;
- di = anim1->state;
-
- if (anim0->isBusy == 0) {
- if ((_word_2F9BC == 0) && (anim0->isStatic == 0)) {
- if ((VAR(_dword_2F9B6) == 0) && (si == 28)) {
- si = _vm->_util->getRandom(3) + 24;
- sub_195C7(0, si);
- WRITE_VAR(_dword_2F9B6, 100);
- } else
- WRITE_VAR(_dword_2F9B6, VAR(_dword_2F9B6) - 1);
- }
- if ((si == 8) || (si == 9) || (si == 29))
- anim0->curLookDir = 6;
- }
- if (anim1->isBusy == 0) {
- if ((_word_2F9BA == 0) && (anim1->isStatic == 0)) {
- if ((VAR(_dword_2F9B2) == 0) && (di == 28)) {
- di = _vm->_util->getRandom(3) + 24;
- sub_195C7(1, di);
- WRITE_VAR(_dword_2F9B2, 100);
- } else
- WRITE_VAR(_dword_2F9B2, VAR(_dword_2F9B2) - 1);
- }
- if ((di == 8) || (di == 9) || (di == 29))
- anim1->curLookDir = 6;
- }
-
- if ((anim0->isBusy == 1) && (anim0->isStatic == 0) &&
- ((anim0->state == 28) || (anim0->state == 29)))
- anim0->curLookDir = 0;
- if ((anim1->isBusy == 1) && (anim1->isStatic == 0) &&
- ((anim1->state == 28) || (anim1->state == 29)))
- anim1->curLookDir = 0;
-
- if (VAR(18) != ((uint32) -1)) {
- if (anim0->layer == 44)
- anim0->curLookDir = 4;
- else if (anim0->layer == 45)
- anim0->curLookDir = 0;
- if (anim0->isBusy == 0)
- anim0->curLookDir = 6;
- }
- if (VAR(19) != ((uint32) -1)) {
- if (anim1->layer == 48)
- anim1->curLookDir = 4;
- else if (anim1->layer == 49)
- anim1->curLookDir = 0;
- if (anim1->isBusy == 0)
- anim1->curLookDir = 6;
- }
-
- if ((anim0->layer == 45) && (anim0->curLookDir == 4) && (anim0->pathExistence == 5) &&
- (VAR(18) == ((uint32) -1)) && (_word_2F9C0 == 0)) {
- sub_195C7(0, 19);
- }
- if ((anim0->layer == 44) && (anim0->curLookDir == 0) && (anim0->pathExistence == 5) &&
- (VAR(18) == ((uint32) -1)) && (_word_2F9C0 == 0)) {
- sub_195C7(0, 16);
- }
- if ((anim1->layer == 49) && (anim1->curLookDir == 4) && (anim1->pathExistence == 5) &&
- (VAR(19) == ((uint32) -1)) && (_word_2F9BE == 0)) {
- sub_195C7(1, 19);
- }
- if ((anim1->layer == 48) && (anim1->curLookDir == 0) && (anim1->pathExistence == 5) &&
- (VAR(19) == ((uint32) -1)) && (_word_2F9BE == 0)) {
- sub_195C7(1, 16);
- }
-
- gob1X = obj0->goblinX;
- gob2X = obj1->goblinX;
- gob1Y = obj0->goblinY;
- gob2Y = obj1->goblinY;
- di = anim0->field_13;
- si = anim0->field_14;
- var_A = anim1->field_13;
- var_C = anim1->field_14;
-
- pass = _vm->_map->getPass(gob1X, gob1Y);
- if ((pass > 17) && (pass < 21))
- sub_19AB7(anim0);
- pass = _vm->_map->getPass(gob2X, gob2Y);
- if ((pass > 17) && (pass < 21))
- sub_19B45(anim1);
-
- if ((di < 0) || (di > 39) || (si < 0) || (si > 39))
- return;
-
- if (gob1Y > si) {
- if (_vm->_map->getPass(di, si) > 17) {
- do {
- si--;
- } while (_vm->_map->getPass(di, si) > 17);
- si++;
- if (_vm->_map->getPass(di - 1, si) == 0) {
- if (_vm->_map->getPass(di + 1, si) != 0)
- di++;
- } else
- di--;
- sub_197A6(di, si, 0);
- }
- } else {
- if (_vm->_map->getPass(di, si) > 17) {
- do {
- si++;
- } while (_vm->_map->getPass(di, si) > 17);
- si--;
- if (_vm->_map->getPass(di - 1, si) == 0) {
- if (_vm->_map->getPass(di + 1, si) != 0)
- di++;
- } else
- di--;
- sub_197A6(di, si, 0);
- }
- }
- if (gob2Y > var_C) {
- if (_vm->_map->getPass(var_A, var_C) > 17) {
- do {
- var_C--;
- } while (_vm->_map->getPass(var_A, var_C) > 17);
- var_C++;
- if (_vm->_map->getPass(var_A - 1, var_C) == 0) {
- if (_vm->_map->getPass(var_A + 1, var_C) != 0)
- var_A++;
- } else
- var_A--;
- sub_197A6(var_A, var_C, 1);
- }
- } else {
- if (_vm->_map->getPass(var_A, var_C) > 17) {
- do {
- var_C++;
- } while (_vm->_map->getPass(var_A, var_C) > 17);
- var_C--;
- if (_vm->_map->getPass(var_A - 1, var_C) == 0) {
- if (_vm->_map->getPass(var_A + 1, var_C) != 0)
- var_A++;
- } else
- var_A--;
- sub_197A6(var_A, var_C, 1);
- }
- }
-}
-
void Goblin::sub_195C7(int16 index, int16 state) {
Mult::Mult_Object *obj;
Mult::Mult_AnimData *animData;
diff --git a/engines/gob/goblin.h b/engines/gob/goblin.h
index 7e823bdae8..0050c5744e 100644
--- a/engines/gob/goblin.h
+++ b/engines/gob/goblin.h
@@ -217,13 +217,13 @@ public:
int16 treatItem(int16 action);
int16 doMove(Gob_Object *gobDesc, int16 cont, int16 action);
- void sub_19BD3(void);
void sub_195C7(int16 index, int16 state);
void sub_11984(Mult::Mult_Object *obj);
void sub_197A6(int16 destX, int16 destY, int16 objIndex);
void sub_19AB7(Mult::Mult_AnimData *animData);
void sub_19B45(Mult::Mult_AnimData *animData);
+ virtual void handleGoblins(void) = 0;
virtual void placeObject(Gob_Object * objDesc, char animated,
int16 index, int16 x, int16 y, int16 state) = 0;
virtual void freeObjects(void) = 0;
@@ -257,6 +257,7 @@ protected:
class Goblin_v1 : public Goblin {
public:
+ virtual void handleGoblins(void) {}
virtual void placeObject(Gob_Object * objDesc, char animated,
int16 index, int16 x, int16 y, int16 state);
virtual void freeObjects(void);
@@ -273,6 +274,7 @@ protected:
class Goblin_v2 : public Goblin_v1 {
public:
+ virtual void handleGoblins(void);
virtual void placeObject(Gob_Object * objDesc, char animated,
int16 index, int16 x, int16 y, int16 state);
virtual void freeObjects(void);
diff --git a/engines/gob/goblin_v2.cpp b/engines/gob/goblin_v2.cpp
index 44d26c6bc9..35114f4ed9 100644
--- a/engines/gob/goblin_v2.cpp
+++ b/engines/gob/goblin_v2.cpp
@@ -523,4 +523,168 @@ void Goblin_v2::moveAdvance(Mult::Mult_Object *obj, Gob_Object *gobDesc,
}
}
+void Goblin_v2::handleGoblins(void) {
+ Mult::Mult_Object *obj0;
+ Mult::Mult_Object *obj1;
+ Mult::Mult_AnimData *anim0;
+ Mult::Mult_AnimData *anim1;
+ int16 pass;
+ int16 gob1X;
+ int16 gob2X;
+ int16 gob1Y;
+ int16 gob2Y;
+ int16 var_A;
+ int16 var_C;
+ int16 di;
+ int16 si;
+
+ obj0 = &_vm->_mult->_objects[0];
+ obj1 = &_vm->_mult->_objects[1];
+ anim0 = obj0->pAnimData;
+ anim1 = obj1->pAnimData;
+
+ si = anim0->state;
+ di = anim1->state;
+
+ if (anim0->isBusy == 0) {
+ if ((_word_2F9BC == 0) && (anim0->isStatic == 0)) {
+ if ((VAR(_dword_2F9B6) == 0) && (si == 28)) {
+ si = _vm->_util->getRandom(3) + 24;
+ sub_195C7(0, si);
+ WRITE_VAR(_dword_2F9B6, 100);
+ } else
+ WRITE_VAR(_dword_2F9B6, VAR(_dword_2F9B6) - 1);
+ }
+ if ((si == 8) || (si == 9) || (si == 29))
+ anim0->curLookDir = 6;
+ }
+ if (anim1->isBusy == 0) {
+ if ((_word_2F9BA == 0) && (anim1->isStatic == 0)) {
+ if ((VAR(_dword_2F9B2) == 0) && (di == 28)) {
+ di = _vm->_util->getRandom(3) + 24;
+ sub_195C7(1, di);
+ WRITE_VAR(_dword_2F9B2, 100);
+ } else
+ WRITE_VAR(_dword_2F9B2, VAR(_dword_2F9B2) - 1);
+ }
+ if ((di == 8) || (di == 9) || (di == 29))
+ anim1->curLookDir = 6;
+ }
+
+ if ((anim0->isBusy == 1) && (anim0->isStatic == 0) &&
+ ((anim0->state == 28) || (anim0->state == 29)))
+ anim0->curLookDir = 0;
+ if ((anim1->isBusy == 1) && (anim1->isStatic == 0) &&
+ ((anim1->state == 28) || (anim1->state == 29)))
+ anim1->curLookDir = 0;
+
+ if (VAR(18) != ((uint32) -1)) {
+ if (anim0->layer == 44)
+ anim0->curLookDir = 4;
+ else if (anim0->layer == 45)
+ anim0->curLookDir = 0;
+ if (anim0->isBusy == 0)
+ anim0->curLookDir = 6;
+ }
+ if (VAR(19) != ((uint32) -1)) {
+ if (anim1->layer == 48)
+ anim1->curLookDir = 4;
+ else if (anim1->layer == 49)
+ anim1->curLookDir = 0;
+ if (anim1->isBusy == 0)
+ anim1->curLookDir = 6;
+ }
+
+ if ((anim0->layer == 45) && (anim0->curLookDir == 4) && (anim0->pathExistence == 5) &&
+ (VAR(18) == ((uint32) -1)) && (_word_2F9C0 == 0)) {
+ sub_195C7(0, 19);
+ }
+ if ((anim0->layer == 44) && (anim0->curLookDir == 0) && (anim0->pathExistence == 5) &&
+ (VAR(18) == ((uint32) -1)) && (_word_2F9C0 == 0)) {
+ sub_195C7(0, 16);
+ }
+ if ((anim1->layer == 49) && (anim1->curLookDir == 4) && (anim1->pathExistence == 5) &&
+ (VAR(19) == ((uint32) -1)) && (_word_2F9BE == 0)) {
+ sub_195C7(1, 19);
+ }
+ if ((anim1->layer == 48) && (anim1->curLookDir == 0) && (anim1->pathExistence == 5) &&
+ (VAR(19) == ((uint32) -1)) && (_word_2F9BE == 0)) {
+ sub_195C7(1, 16);
+ }
+
+ gob1X = obj0->goblinX;
+ gob2X = obj1->goblinX;
+ gob1Y = obj0->goblinY;
+ gob2Y = obj1->goblinY;
+ di = anim0->field_13;
+ si = anim0->field_14;
+ var_A = anim1->field_13;
+ var_C = anim1->field_14;
+
+ pass = _vm->_map->getPass(gob1X, gob1Y);
+ if ((pass > 17) && (pass < 21))
+ sub_19AB7(anim0);
+ pass = _vm->_map->getPass(gob2X, gob2Y);
+ if ((pass > 17) && (pass < 21))
+ sub_19B45(anim1);
+
+ if ((di < 0) || (di > 39) || (si < 0) || (si > 39))
+ return;
+
+ if (gob1Y > si) {
+ if (_vm->_map->getPass(di, si) > 17) {
+ do {
+ si--;
+ } while (_vm->_map->getPass(di, si) > 17);
+ si++;
+ if (_vm->_map->getPass(di - 1, si) == 0) {
+ if (_vm->_map->getPass(di + 1, si) != 0)
+ di++;
+ } else
+ di--;
+ sub_197A6(di, si, 0);
+ }
+ } else {
+ if (_vm->_map->getPass(di, si) > 17) {
+ do {
+ si++;
+ } while (_vm->_map->getPass(di, si) > 17);
+ si--;
+ if (_vm->_map->getPass(di - 1, si) == 0) {
+ if (_vm->_map->getPass(di + 1, si) != 0)
+ di++;
+ } else
+ di--;
+ sub_197A6(di, si, 0);
+ }
+ }
+ if (gob2Y > var_C) {
+ if (_vm->_map->getPass(var_A, var_C) > 17) {
+ do {
+ var_C--;
+ } while (_vm->_map->getPass(var_A, var_C) > 17);
+ var_C++;
+ if (_vm->_map->getPass(var_A - 1, var_C) == 0) {
+ if (_vm->_map->getPass(var_A + 1, var_C) != 0)
+ var_A++;
+ } else
+ var_A--;
+ sub_197A6(var_A, var_C, 1);
+ }
+ } else {
+ if (_vm->_map->getPass(var_A, var_C) > 17) {
+ do {
+ var_C++;
+ } while (_vm->_map->getPass(var_A, var_C) > 17);
+ var_C--;
+ if (_vm->_map->getPass(var_A - 1, var_C) == 0) {
+ if (_vm->_map->getPass(var_A + 1, var_C) != 0)
+ var_A++;
+ } else
+ var_A--;
+ sub_197A6(var_A, var_C, 1);
+ }
+ }
+}
+
} // End of namespace Gob
diff --git a/engines/gob/inter.h b/engines/gob/inter.h
index 18f501c262..4fcddb04a3 100644
--- a/engines/gob/inter.h
+++ b/engines/gob/inter.h
@@ -362,7 +362,8 @@ protected:
void o2_playMult(void);
void o2_initCursor(void);
void o2_playImd(void);
- void o2_setPickable(int16 &extraData, int32 *retVarPtr, Goblin::Gob_Object *objDesc);
+ void o2_handleGoblins(int16 &extraData, int32 *retVarPtr, Goblin::Gob_Object *objDesc);
+ void o2_playInfogrames(int16 &extraData, int32 *retVarPtr, Goblin::Gob_Object *objDesc);
};
} // End of namespace Gob
diff --git a/engines/gob/inter_v2.cpp b/engines/gob/inter_v2.cpp
index f0389dc201..181289621e 100644
--- a/engines/gob/inter_v2.cpp
+++ b/engines/gob/inter_v2.cpp
@@ -84,7 +84,7 @@ const int Inter_v2::_goblinFuncLookUp[][2] = {
{50, 36},
{52, 37},
{53, 38},
- {150, 39},
+ {100, 39},
{152, 40},
{200, 41},
{201, 42},
@@ -551,94 +551,94 @@ void Inter_v2::setupOpcodes(void) {
static const OpcodeGoblinEntryV2 opcodesGoblin[71] = {
/* 00 */
- OPCODE(o1_setState),
- OPCODE(o1_setCurFrame),
- OPCODE(o1_setNextState),
- OPCODE(o1_setMultState),
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
/* 04 */
- OPCODE(o1_setOrder),
- OPCODE(o1_setActionStartState),
- OPCODE(o1_setCurLookDir),
- OPCODE(o1_setType),
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
/* 08 */
- OPCODE(o1_setNoTick),
- OPCODE(o2_setPickable),
- OPCODE(o1_setXPos),
- OPCODE(o1_setYPos),
+ {NULL, ""},
+ OPCODE(o2_playInfogrames),
+ {NULL, ""},
+ {NULL, ""},
/* 0C */
- OPCODE(o1_setDoAnim),
- OPCODE(o1_setRelaxTime),
- OPCODE(o1_setMaxTick),
- OPCODE(o1_getState),
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
/* 10 */
- OPCODE(o1_getCurFrame),
- OPCODE(o1_getNextState),
- OPCODE(o1_getMultState),
- OPCODE(o1_getOrder),
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
/* 14 */
- OPCODE(o1_getActionStartState),
- OPCODE(o1_getCurLookDir),
- OPCODE(o1_getType),
- OPCODE(o1_getNoTick),
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
/* 18 */
- OPCODE(o1_getPickable),
- OPCODE(o1_getObjMaxFrame),
- OPCODE(o1_getXPos),
- OPCODE(o1_getYPos),
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
/* 1C */
- OPCODE(o1_getDoAnim),
- OPCODE(o1_getRelaxTime),
- OPCODE(o1_getMaxTick),
- OPCODE(o1_manipulateMap),
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
/* 20 */
- OPCODE(o1_getItem),
- OPCODE(o1_manipulateMapIndirect),
- OPCODE(o1_getItemIndirect),
- OPCODE(o1_setPassMap),
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
/* 24 */
- OPCODE(o1_setGoblinPosH),
- OPCODE(o1_getGoblinPosXH),
- OPCODE(o1_getGoblinPosYH),
- OPCODE(o1_setGoblinMultState),
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ OPCODE(o2_handleGoblins),
/* 28 */
- OPCODE(o1_setGoblinUnk14),
- OPCODE(o1_setItemIdInPocket),
- OPCODE(o1_setItemIndInPocket),
- OPCODE(o1_getItemIdInPocket),
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
/* 2C */
- OPCODE(o1_getItemIndInPocket),
- OPCODE(o1_setItemPos),
- OPCODE(o1_setGoblinPos),
- OPCODE(o1_setGoblinState),
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
/* 30 */
- OPCODE(o1_setGoblinStateRedraw),
- OPCODE(o1_decRelaxTime),
- OPCODE(o1_getGoblinPosX),
- OPCODE(o1_getGoblinPosY),
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
/* 34 */
- OPCODE(o1_clearPathExistence),
- OPCODE(o1_setGoblinVisible),
- OPCODE(o1_setGoblinInvisible),
- OPCODE(o1_getObjectIntersect),
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
/* 38 */
- OPCODE(o1_getGoblinIntersect),
- OPCODE(o1_setItemPos),
- OPCODE(o1_loadObjects),
- OPCODE(o1_freeObjects),
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
/* 3C */
- OPCODE(o1_animateObjects),
- OPCODE(o1_drawObjects),
- OPCODE(o1_loadMap),
- OPCODE(o1_moveGoblin),
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
/* 40 */
- OPCODE(o1_switchGoblin),
- OPCODE(o1_loadGoblin),
- OPCODE(o1_writeTreatItem),
- OPCODE(o1_moveGoblin0),
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
/* 44 */
- OPCODE(o1_setGoblinTarget),
- OPCODE(o1_setGoblinObjectsPos),
- OPCODE(o1_initGoblin)
+ {NULL, ""},
+ {NULL, ""},
+ {NULL, ""},
};
_opcodesDrawV2 = opcodesDraw;
@@ -687,9 +687,11 @@ void Inter_v2::executeGoblinOpcode(int i, int16 &extraData, int32 *retVarPtr, Go
}
if (op == NULL) {
- warning("unimplemented opcodeGoblin: %d", i);
+ int16 val;
+
_vm->_global->_inter_execPtr -= 2;
- _vm->_global->_inter_execPtr += load16() * 2;
+ val = load16();
+ _vm->_global->_inter_execPtr += val << 1;
}
else
(this->*op) (extraData, retVarPtr, objDesc);
@@ -1613,52 +1615,13 @@ bool Inter_v2::o2_playSound(char &cmdCount, int16 &counter, int16 &retFlag) {
bool Inter_v2::o2_goblinFunc(char &cmdCount, int16 &counter, int16 &retFlag) {
int16 cmd;
- char fileName[20];
+ int16 extraData;
cmd = load16();
_vm->_global->_inter_execPtr += 2;
- switch (cmd) {
- case 0:
- case 1:
- case 2:
- case 3:
- case 11:
- case 13:
- load16();
- break;
-
- case 10:
- strcpy(fileName, GET_VAR_STR(load16()));
- strcat(fileName, ".DUM");
- if (!_vm->_infogrames) {
- _vm->_infogrames = new Infogrames(_vm, true);
- _vm->_infogrames->loadInstruments("i1.ins");
- }
- _vm->_infogrames->load(fileName);
- _vm->_infogrames->startPlay();
- break;
-
- case 100:
- _vm->_goblin->_word_2F9C0 = VAR(load16());
- _vm->_goblin->_word_2F9BE = VAR(load16());
- _vm->_goblin->_dword_2F9B6 = load16();
- _vm->_goblin->_dword_2F9B2 = load16();
- _vm->_goblin->_word_2F9BC = VAR(load16());
- _vm->_goblin->_word_2F9BA = VAR(load16());
- _vm->_goblin->sub_19BD3();
- break;
-
- case 101:
- break;
-
- default:
- _vm->_global->_inter_execPtr -= 2;
- cmd = load16();
- _vm->_global->_inter_execPtr += cmd << 1;
- break;
- }
-
+ if (cmd != 101)
+ executeGoblinOpcode(cmd, extraData, NULL, NULL);
return false;
}
@@ -2346,6 +2309,51 @@ void Inter_v2::o2_switchTotSub(void) {
_vm->_game->switchTotSub(index, skipPlay);
}
+void Inter_v2::o2_handleGoblins(int16 &extraData, int32 *retVarPtr, Goblin::Gob_Object *objDesc) {
+ _vm->_goblin->_word_2F9C0 = VAR(load16());
+ _vm->_goblin->_word_2F9BE = VAR(load16());
+ _vm->_goblin->_dword_2F9B6 = load16();
+ _vm->_goblin->_dword_2F9B2 = load16();
+ _vm->_goblin->_word_2F9BC = VAR(load16());
+ _vm->_goblin->_word_2F9BA = VAR(load16());
+ _vm->_goblin->handleGoblins();
+}
+
+void Inter_v2::o2_playInfogrames(int16 &extraData, int32 *retVarPtr, Goblin::Gob_Object *objDesc) {
+ int16 varName;
+ char fileName[20];
+
+ varName = load16();
+
+ if (_vm->_noMusic)
+ return;
+
+ strcpy(fileName, GET_VAR_STR(varName));
+ strcat(fileName, ".DUM");
+ debugC(1, kDebugMusic, "Playing Infogrames music file \"%s\"", fileName);
+ if (!_vm->_game->_infIns) {
+ _vm->_game->_infIns = new Infogrames::Instruments;
+ if (!_vm->_game->_infIns->load("i1.ins")) {
+ warning("Couldn't load instruments file");
+ delete _vm->_game->_infIns;
+ _vm->_game->_infIns = 0;
+ }
+ }
+ if (_vm->_game->_infIns) {
+ _vm->_mixer->stopHandle(_vm->_game->_infHandle);
+ _vm->_game->_infogrames =
+ new Infogrames(*_vm->_game->_infIns, true,
+ _vm->_mixer->getOutputRate());
+ if (!_vm->_game->_infogrames->load(fileName)) {
+ warning("Couldn't load infogrames music");
+ delete _vm->_game->_infogrames;
+ _vm->_game->_infogrames = 0;
+ } else
+ _vm->_mixer->playInputStream(Audio::Mixer::kMusicSoundType,
+ &_vm->_game->_infHandle, _vm->_game->_infogrames);
+ }
+}
+
void Inter_v2::storeKey(int16 key) {
WRITE_VAR(12, _vm->_util->getTimeKey() - _vm->_game->_startTimeKey);
@@ -2388,10 +2396,6 @@ void Inter_v2::storeMouse(void) {
WRITE_VAR(4, _vm->_game->_mouseButtons);
}
-void Inter_v2::o2_setPickable(int16 &extraData, int32 *retVarPtr, Goblin::Gob_Object *objDesc) {
- warning("GOB2 Stub! o2_setPickable");
-}
-
void Inter_v2::animPalette(void) {
int16 i;
int16 j;
diff --git a/engines/gob/mult_v2.cpp b/engines/gob/mult_v2.cpp
index c582957e12..70ccb1ffd5 100644
--- a/engines/gob/mult_v2.cpp
+++ b/engines/gob/mult_v2.cpp
@@ -516,7 +516,6 @@ void Mult_v2::playMult(int16 startFrame, int16 endFrame, char checkEscape,
}
do {
- _vm->_snd->loopSounds();
stop = 1;
if (VAR(58) == 0) {
@@ -540,6 +539,7 @@ void Mult_v2::playMult(int16 startFrame, int16 endFrame, char checkEscape,
stop = doFadeAnim(stop);
stop = doSoundAnim(stop, _frame);
+ _vm->_snd->loopSounds();
if (_frame >= endFrame)
stopNoClear = 1;
@@ -1318,18 +1318,7 @@ void Mult_v2::animate(void) {
void Mult_v2::playSound(Snd::SoundDesc * soundDesc, int16 repCount, int16 freq,
int16 channel) {
-// warning("playSound, %d, %d, %d", repCount, freq, channel);
- if (soundDesc->frequency >= 0) {
- if (soundDesc->frequency == freq)
- _vm->_snd->playSample(soundDesc, repCount, -channel);
- else
- _vm->_snd->playSample(soundDesc, repCount, freq);
- } else {
- if (soundDesc->frequency == -freq)
- _vm->_snd->playSample(soundDesc, repCount, -channel);
- else
- _vm->_snd->playSample(soundDesc, repCount, freq);
- }
+ _vm->_snd->playSample(soundDesc, repCount, freq);
}
void Mult_v2::freeMult(void) {
diff --git a/engines/gob/music.cpp b/engines/gob/music.cpp
index 0411f82761..7c18d57a23 100644
--- a/engines/gob/music.cpp
+++ b/engines/gob/music.cpp
@@ -32,19 +32,15 @@
namespace Gob {
-Paula::Paula(GobEngine *vm, bool stereo, int intFreq) : _vm(vm) {
+Paula::Paula(bool stereo, int rate, int interruptFreq) :
+ _stereo(stereo), _rate(rate), _intFreq(interruptFreq) {
_playing = false;
- _stereo = stereo;
- _rate = _vm->_mixer->getOutputRate();
- _vm->_mixer->setupPremix(this, Audio::Mixer::kMusicSoundType);
- _intFreq = intFreq;
-
clearVoices();
- _voice[0].panning = 0;
- _voice[1].panning = 1;
- _voice[2].panning = 1;
- _voice[3].panning = 0;
+ _voice[0].panning = 63;
+ _voice[1].panning = 191;
+ _voice[2].panning = 191;
+ _voice[3].panning = 63;
if (_intFreq <= 0)
_intFreq = _rate;
@@ -54,10 +50,12 @@ Paula::Paula(GobEngine *vm, bool stereo, int intFreq) : _vm(vm) {
}
Paula::~Paula() {
- _vm->_mixer->setupPremix(0);
}
-void Paula::clearVoice(int voice) {
+void Paula::clearVoice(byte voice) {
+ if (voice >= 4)
+ return;
+
_voice[voice].data = 0;
_voice[voice].dataRepeat = 0;
_voice[voice].length = 0;
@@ -78,9 +76,14 @@ int Paula::readBuffer(int16 *buffer, const int numSamples) {
int16 *p;
int8 *data;
+ _mutex.lock();
+
memset(buffer, 0, numSamples * 2);
if (!_playing)
+ {
+ _mutex.unlock();
return numSamples;
+ }
samples = _stereo ? numSamples / 2 : numSamples;
while (samples > 0) {
@@ -101,7 +104,8 @@ int Paula::readBuffer(int16 *buffer, const int numSamples) {
p = buffer;
_voice[voice].volume &= 0x3F;
- if ((_voice[voice].lengthRepeat > 2) && ((int)(offset + nSamples * rate) >= sLen)) {
+ if ((_voice[voice].lengthRepeat > 2) &&
+ ((int)(offset + nSamples * rate) >= sLen)) {
int neededSamples = nSamples;
int end = (int)((sLen - offset) / rate);
@@ -122,7 +126,8 @@ int Paula::readBuffer(int16 *buffer, const int numSamples) {
mix(p, data[(int)(offset + rate * i)], voice);
_voice[voice].data = data = _voice[voice].dataRepeat;
- _voice[voice].length = sLen = _voice[voice].lengthRepeat;
+ _voice[voice].length = sLen =
+ _voice[voice].lengthRepeat;
_voice[voice].offset = offset = 0;
neededSamples -= end;
@@ -132,7 +137,8 @@ int Paula::readBuffer(int16 *buffer, const int numSamples) {
_voice[voice].offset += rate * neededSamples;
if (ceil(_voice[voice].offset) >= sLen) {
_voice[voice].data = data = _voice[voice].dataRepeat;
- _voice[voice].length = sLen = _voice[voice].lengthRepeat;
+ _voice[voice].length = sLen =
+ _voice[voice].lengthRepeat;
_voice[voice].offset = offset = 0;
}
neededSamples = 0;
@@ -148,7 +154,8 @@ int Paula::readBuffer(int16 *buffer, const int numSamples) {
mix(p, data[(int)(offset + rate * i)], voice);
_voice[voice].offset = sLen;
} else {
- // The requested number of samples is the limiting factor, not the sample
+ // The requested number of samples is the limiting
+ // factor, not the sample
for (int i = 0; i < nSamples; i++)
mix(p, data[(int)(offset + rate * i)], voice);
@@ -161,10 +168,20 @@ int Paula::readBuffer(int16 *buffer, const int numSamples) {
_curInt += nSamples;
samples -= nSamples;
}
+ _mutex.unlock();
return numSamples;
}
Infogrames::Instruments::Instruments() {
+ init();
+}
+
+Infogrames::Instruments::~Instruments() {
+ if (_sampleData)
+ delete[] _sampleData;
+}
+
+void Infogrames::Instruments::init() {
int i;
for (i = 0; i < 32; i++) {
@@ -177,11 +194,6 @@ Infogrames::Instruments::Instruments() {
_sampleData = 0;
}
-Infogrames::Instruments::~Instruments() {
- if (_sampleData)
- delete[] _sampleData;
-}
-
bool Infogrames::Instruments::load(Common::SeekableReadStream &ins) {
int i;
uint32 fsize;
@@ -189,13 +201,16 @@ bool Infogrames::Instruments::load(Common::SeekableReadStream &ins) {
uint32 offsetRepeat[32];
uint32 dataOffset;
+ unload();
+
fsize = ins.readUint32BE();
dataOffset = fsize;
for (i = 0; (i < 32) && !ins.eos(); i++) {
offset[i] = ins.readUint32BE();
offsetRepeat[i] = ins.readUint32BE();
if ((offset[i] > fsize) || (offsetRepeat[i] > fsize) ||
- (offset[i] < (ins.pos() + 4)) || (offsetRepeat[i] < (ins.pos() + 4))) {
+ (offset[i] < (ins.pos() + 4)) ||
+ (offsetRepeat[i] < (ins.pos() + 4))) {
// Definitely no real entry anymore
ins.seek(-8, SEEK_CUR);
break;
@@ -223,29 +238,38 @@ bool Infogrames::Instruments::load(Common::SeekableReadStream &ins) {
return true;
}
+void Infogrames::Instruments::unload(void) {
+ if (_sampleData)
+ delete[] _sampleData;
+ init();
+}
+
+const uint8 Infogrames::tickCount[] =
+ {2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96};
const uint16 Infogrames::periods[] =
{0x6ACC, 0x64CC, 0x5F25, 0x59CE, 0x54C3, 0x5003, 0x4B86, 0x4747, 0x4346,
- 0x3F8B, 0x3BF3, 0x3892, 0x3568, 0x3269, 0x2F93, 0x2CEA, 0x2A66, 0x2801,
- 0x2566, 0x23A5, 0x21AF, 0x1FC4, 0x1DFE, 0x1C4E, 0x1ABC, 0x1936, 0x17CC,
- 0x1676, 0x1533, 0x1401, 0x12E4, 0x11D5, 0x10D4, 0xFE3, 0xEFE, 0xE26,
- 0xD5B, 0xC9B, 0xBE5, 0xB3B, 0xA9B, 0xA02, 0x972, 0x8E9, 0x869, 0x7F1,
- 0x77F, 0x713, 0x6AD, 0x64D, 0x5F2, 0x59D, 0x54D, 0x500, 0x4B8, 0x475,
- 0x435, 0x3F8, 0x3BF, 0x38A, 0x356, 0x326, 0x2F9, 0x2CF, 0x2A6, 0x280,
- 0x25C, 0x23A, 0x21A, 0x1FC, 0x1E0, 0x1C5, 0x1AB, 0x193, 0x17D, 0x167,
- 0x153, 0x140, 0x12E, 0x11D, 0x10D, 0xFE, 0xF0, 0xE2, 0xD6, 0xCA, 0xBE,
- 0xB4, 0xAA, 0xA0, 0x97, 0x8F, 0x87, 0x7F, 0x78, 0x70, 0x60, 0x50, 0x40,
- 0x30, 0x20, 0x10, 0, 0, 0x20, 0x2020, 0x2020, 0x2020, 0x2020, 0x3030,
- 0x3030, 0x3020, 0x2020, 0x2020, 0x2020, 0x2020, 0x2020, 0x2020, 0x2020,
- 0x2020, 0x2090, 0x4040, 0x4040, 0x4040, 0x4040, 0x4040, 0x4040, 0x4040,
- 0x400C, 0xC0C, 0xC0C, 0xC0C, 0xC0C, 0xC40, 0x4040, 0x4040, 0x4040, 0x909,
- 0x909, 0x909, 0x101, 0x101, 0x101, 0x101, 0x101, 0x101, 0x101, 0x101, 0x101,
- 0x101, 0x4040, 0x4040, 0x4040, 0xA0A, 0xA0A, 0xA0A, 0x202, 0x202, 0x202,
- 0x202, 0x202, 0x202, 0x202, 0x202, 0x202, 0x202, 0x4040, 0x4040, 0x2000};
-const uint8 Infogrames::tickCount[] = {2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96};
-
-Infogrames::Infogrames(GobEngine *vm, bool stereo) :
- Paula(vm, stereo, vm->_mixer->getOutputRate()/80) {
- _instruments = 0;
+ 0x3F8B, 0x3BF3, 0x3892, 0x3568, 0x3269, 0x2F93, 0x2CEA, 0x2A66, 0x2801,
+ 0x2566, 0x23A5, 0x21AF, 0x1FC4, 0x1DFE, 0x1C4E, 0x1ABC, 0x1936, 0x17CC,
+ 0x1676, 0x1533, 0x1401, 0x12E4, 0x11D5, 0x10D4, 0x0FE3, 0x0EFE, 0x0E26,
+ 0x0D5B, 0x0C9B, 0x0BE5, 0x0B3B, 0x0A9B, 0x0A02, 0x0972, 0x08E9, 0x0869,
+ 0x07F1, 0x077F, 0x0713, 0x06AD, 0x064D, 0x05F2, 0x059D, 0x054D, 0x0500,
+ 0x04B8, 0x0475, 0x0435, 0x03F8, 0x03BF, 0x038A, 0x0356, 0x0326, 0x02F9,
+ 0x02CF, 0x02A6, 0x0280, 0x025C, 0x023A, 0x021A, 0x01FC, 0x01E0, 0x01C5,
+ 0x01AB, 0x0193, 0x017D, 0x0167, 0x0153, 0x0140, 0x012E, 0x011D, 0x010D,
+ 0x00FE, 0x00F0, 0x00E2, 0x00D6, 0x00CA, 0x00BE, 0x00B4, 0x00AA, 0x00A0,
+ 0x0097, 0x008F, 0x0087, 0x007F, 0x0078, 0x0070, 0x0060, 0x0050, 0x0040,
+ 0x0030, 0x0020, 0x0010, 0x0000, 0x0000, 0x0020, 0x2020, 0x2020, 0x2020,
+ 0x2020, 0x3030, 0x3030, 0x3020, 0x2020, 0x2020, 0x2020, 0x2020, 0x2020,
+ 0x2020, 0x2020, 0x2020, 0x2090, 0x4040, 0x4040, 0x4040, 0x4040, 0x4040,
+ 0x4040, 0x4040, 0x400C, 0x0C0C, 0x0C0C, 0x0C0C, 0x0C0C, 0x0C40, 0x4040,
+ 0x4040, 0x4040, 0x0909, 0x0909, 0x0909, 0x0101, 0x0101, 0x0101, 0x0101,
+ 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x4040, 0x4040, 0x4040,
+ 0x0A0A, 0x0A0A, 0x0A0A, 0x0202, 0x0202, 0x0202, 0x0202, 0x0202, 0x0202,
+ 0x0202, 0x0202, 0x0202, 0x0202, 0x4040, 0x4040, 0x2000};
+
+Infogrames::Infogrames(Instruments &ins, bool stereo, int rate) :
+ Paula(stereo, rate, rate/80) {
+ _instruments = &ins;
_data = 0;
_repCount = -1;
@@ -264,7 +288,6 @@ void Infogrames::init() {
_period = 0;
_sample = 0;
_speedCounter = _speed;
- _newVol = 0x3F;
for (i = 0; i < 4; i++) {
_chn[i].cmds = 0;
@@ -285,28 +308,20 @@ void Infogrames::init() {
_chn[i].periodSlide.flags = 0;
_chn[i].periodSlide.curDelay1 = 0;
_chn[i].periodSlide.curDelay2 = 0;
- _chn[i].curPeriod = 0;
_chn[i].period = 0;
- _chn[i].curCmdBlock = 0;
- _chn[i].flags = 0;
+ _chn[i].flags = 0x81;
_chn[i].ticks = 0;
_chn[i].tickCount = 0;
_chn[i].periodMod = 0;
- _chn[i].field_2B = 0;
- _chn[i].field_2C = 0;
- _chn[i].field_2F = 0;
}
- for (i = 0; i < 4; i++) {
- _chn[i].flags = 0x81;
- _chn[i].field_2B = 0x3F;
- _chn[i].field_2F = 0x3F;
- }
+ _end = _data == 0;
}
void Infogrames::reset() {
int i;
+ stopPlay();
init();
_volSlideBlocks = 0;
@@ -315,8 +330,6 @@ void Infogrames::reset() {
_cmdBlocks = 0;
_speedCounter = 0;
_speed = 0;
- _newVol = 0;
- _field_1E = 8;
for (i = 0; i < 4; i++)
_chn[i].cmdBlockIndices = 0;
@@ -350,11 +363,8 @@ bool Infogrames::load(Common::SeekableReadStream &dum) {
for (i = 0; i < 4; i++) {
_chn[i].cmdBlockIndices = _subSong + dataStr.readUint16BE();
_chn[i].flags = 0x81;
- _chn[i].field_2B = 0x3F;
- _chn[i].field_2F = 0x3F;
}
_cmdBlocks = _data + dataStr.pos() + 2;
- _newVol = 0x3F;
if ((_volSlideBlocks > (_data + size)) ||
(_periodSlideBlocks > (_data + size)) ||
@@ -366,10 +376,11 @@ bool Infogrames::load(Common::SeekableReadStream &dum) {
return false;
_end = false;
+ _playing = true;
return true;
}
-void Infogrames::unload(bool destroyInstruments) {
+void Infogrames::unload(void) {
stopPlay();
if (_data)
@@ -379,12 +390,6 @@ void Infogrames::unload(bool destroyInstruments) {
clearVoices();
reset();
- if (destroyInstruments) {
- if (_instruments)
- delete _instruments;
- _instruments = 0;
- }
-
_end = true;
}
@@ -397,28 +402,16 @@ void Infogrames::getNextSample(Channel &chn) {
if (chn.flags & 64)
return;
- if (chn.field_2B != chn.field_2F) {
- chn.field_2C++;
- if (chn.field_2C > _field_1E) {
- chn.field_2C = 0;
- if (chn.field_2F <= chn.field_2B)
- chn.field_2B--;
- else
- chn.field_2B++;
- }
- }
-
if (chn.flags & 1) {
chn.flags &= ~1;
chn.cmdBlocks = chn.cmdBlockIndices;
- chn.curCmdBlock = 0;
} else {
chn.flags &= ~1;
if (_speedCounter == 0)
chn.ticks--;
if (chn.ticks != 0) {
- _volume = MAX(0, tune(chn.volSlide, 0) - (0x3F - MAX(chn.field_2B, _newVol)));
- _period = tune(chn.periodSlide, chn.curPeriod);
+ _volume = MAX((int16) 0, tune(chn.volSlide, 0));
+ _period = tune(chn.periodSlide, chn.period);
return;
} else {
chn.ticks = chn.tickCount;
@@ -430,8 +423,8 @@ void Infogrames::getNextSample(Channel &chn) {
while (cont || ((cmdBlock = *chn.cmdBlocks) != 0xFF)) {
if (!cont) {
chn.cmdBlocks++;
- chn.curCmdBlock++;
- chn.cmds = _subSong + READ_BE_UINT16(_cmdBlocks + (cmdBlock * 2));
+ chn.cmds = _subSong +
+ READ_BE_UINT16(_cmdBlocks + (cmdBlock * 2));
} else
cont = false;
while ((cmd = *chn.cmds) != 0xFF) {
@@ -463,7 +456,8 @@ void Infogrames::getNextSample(Channel &chn) {
chn.periodMod = (int8) *chn.cmds++;
break;
case 1: // Set continuous period slide
- chn.periodSlide.data = _periodSlideBlocks + *chn.cmds++ * 13 + 1;
+ chn.periodSlide.data =
+ _periodSlideBlocks + *chn.cmds++ * 13 + 1;
chn.periodSlide.amount = 0;
chn.periodSlide.dataOffset = 0;
chn.periodSlide.finetunePos = 0;
@@ -473,7 +467,8 @@ void Infogrames::getNextSample(Channel &chn) {
chn.periodSlide.flags = 0x81;
break;
case 2: // Set non-continuous period slide
- chn.periodSlide.data = _periodSlideBlocks + *chn.cmds++ * 13 + 1;
+ chn.periodSlide.data =
+ _periodSlideBlocks + *chn.cmds++ * 13 + 1;
chn.periodSlide.amount = 0;
chn.periodSlide.dataOffset = 0;
chn.periodSlide.finetunePos = 0;
@@ -492,7 +487,6 @@ void Infogrames::getNextSample(Channel &chn) {
} else { // 0xxxxxxx - Set period
if (cmd != 0)
cmd += chn.periodMod;
- chn.curPeriod = periods[cmd];
chn.period = periods[cmd];
chn.volSlide.dataOffset = 0;
chn.volSlide.finetunePos = 0;
@@ -508,20 +502,18 @@ void Infogrames::getNextSample(Channel &chn) {
chn.periodSlide.curDelay2 = 0;
chn.periodSlide.flags |= 1;
chn.periodSlide.flags &= ~4;
- _volume = MAX(0, tune(chn.volSlide, 0) - (0x3F - MAX(chn.field_2B, _newVol)));
- _period = tune(chn.periodSlide, chn.curPeriod);
+ _volume = MAX((int16) 0, tune(chn.volSlide, 0));
+ _period = tune(chn.periodSlide, chn.period);
return;
}
}
}
- if (chn.flags & 32) {
- chn.cmdBlocks = chn.cmdBlockIndices;
- chn.curCmdBlock = 0;
- } else {
+ if (!(chn.flags & 32)) {
chn.flags |= 0x40;
_volume = 0;
return;
- }
+ } else
+ chn.cmdBlocks = chn.cmdBlockIndices;
}
}
@@ -586,7 +578,8 @@ void Infogrames::interrupt() {
_voice[chn].data = _instruments->_samples[_sample].data;
_voice[chn].length = _instruments->_samples[_sample].length;
_voice[chn].dataRepeat = _instruments->_samples[_sample].dataRepeat;
- _voice[chn].lengthRepeat = _instruments->_samples[_sample].lengthRepeat;
+ _voice[chn].lengthRepeat =
+ _instruments->_samples[_sample].lengthRepeat;
_voice[chn].offset = 0;
_sample = 0xFF;
}
@@ -600,10 +593,12 @@ void Infogrames::interrupt() {
if (_repCount > 0) {
_repCount--;
init();
- } else if (_repCount == -1)
- init();
- else
+ } else if (_repCount != -1) {
_end = true;
+ _playing = false;
+ }
+ else
+ init();
}
}
@@ -698,7 +693,8 @@ void Adlib::premixerCall(int16 *buf, uint len) {
uint datalen = len;
while (datalen && _playing) {
if (_samplesTillPoll) {
- render = (datalen > _samplesTillPoll) ? (_samplesTillPoll) : (datalen);
+ render = (datalen > _samplesTillPoll) ?
+ (_samplesTillPoll) : (datalen);
datalen -= render;
_samplesTillPoll -= render;
YM3812UpdateOne(_opl, data, render);
@@ -759,10 +755,10 @@ void Adlib::setFreqs(void) {
// Run through the 12 columns
for (col = 0; col < 12; col ++) {
if (!col)
- val = (((0x2710L + lin * 0x18) * 0xCB78 / 0x3D090) << 0xE) * 9 / 0x1B503;
+ val = (((0x2710L + lin * 0x18) * 0xCB78 / 0x3D090) << 0xE) *
+ 9 / 0x1B503;
_freqs[lin][col] = (short)((val + 4) >> 3);
val = val * 0x6A / 0x64;
- // val = val * 392 / 370;
}
}
}
@@ -810,7 +806,8 @@ void Adlib::setVoice(byte voice, byte instr, bool set) {
writeOPL(0x08, 0x00);
writeOPL(0x40 | channel, ((strct[0] & 3) << 6) | (strct[8] & 0x3F));
if (!i)
- writeOPL(0xC0 | voice , ((strct[2] & 7) << 1) | (1 - (strct[12] & 1)));
+ writeOPL(0xC0 | voice,
+ ((strct[2] & 7) << 1) | (1 - (strct[12] & 1)));
writeOPL(0x60 | channel, ((strct[3] & 0xF) << 4) | (strct[6] & 0xF));
writeOPL(0x80 | channel, ((strct[4] & 0xF) << 4) | (strct[7] & 0xF));
writeOPL(0x20 | channel, ((strct[9] & 1) << 7) |
@@ -971,14 +968,16 @@ void Adlib::pollMusic(void) {
_samplesTillPoll = 0;
return;
default:
- warning("Unknown special command in ADL, stopping playback: %X", instr & 0x0F);
+ warning("Unknown special command in ADL, stopping playback: %X",
+ instr & 0x0F);
_repCount = 0;
_ended = true;
break;
}
break;
default:
- warning("Unknown command in ADL, stopping playback: %X", instr & 0xF0);
+ warning("Unknown command in ADL, stopping playback: %X",
+ instr & 0xF0);
_repCount = 0;
_ended = true;
break;
@@ -1000,13 +999,6 @@ void Adlib::pollMusic(void) {
_samplesTillPoll = tempo * (_rate / 1000);
}
-void Adlib::startPlay(void) {
- if (!_data)
- return;
-
- _playing = true;
-}
-
void Adlib::playBgMusic(void) {
for (int i = 0; i < ARRAYSIZE(_tracks); i++)
if (!scumm_stricmp(_vm->_game->_curTotFile, _tracks[i][0])) {
diff --git a/engines/gob/music.h b/engines/gob/music.h
index 89d8e2933c..0ddcab79fd 100644
--- a/engines/gob/music.h
+++ b/engines/gob/music.h
@@ -36,15 +36,24 @@ namespace Gob {
class GobEngine;
-// Emulation of the "Paula" Amiga music chip
-class Paula: public Audio::AudioStream {
+/**
+ * Emulation of the "Paula" Amiga music chip
+ * The interrupt frequency specifies the number of mixed wavesamples between
+ * calls of the interrupt method
+ */
+class Paula : public Audio::AudioStream {
public:
- Paula(GobEngine *vm, bool stereo = false, int intFreq = 0);
+ Paula(bool stereo = false, int rate = 44100, int interruptFreq = 0);
~Paula();
bool playing() const { return _playing; }
void setInterruptFreq(int freq) { _intFreq = freq; }
- void clearVoice(int voice);
+ void setPanning(byte voice, byte panning)
+ {
+ if (voice < 4)
+ _voice[voice].panning = panning;
+ }
+ void clearVoice(byte voice);
void clearVoices() { int i; for (i = 0; i < 4; i++) clearVoice(i); }
virtual void startPlay(void) {}
virtual void stopPlay(void) {}
@@ -65,7 +74,7 @@ protected:
int16 period;
byte volume;
double offset;
- byte panning; // For stereo mixing; 0: left, 1: right
+ byte panning; // For stereo mixing: 0 = far left, 255 = far right
} _voice[4];
int _rate;
@@ -74,34 +83,31 @@ protected:
bool _stereo;
bool _end;
bool _playing;
-
- GobEngine *_vm;
+ Common::Mutex _mutex;
void mix(int16 *&buf, int8 data, int voice) {
if (_stereo) {
- *buf++ += _voice[voice].panning == 0 ? 2 * _voice[voice].volume * data : 0;
- *buf++ += _voice[voice].panning == 1 ? 2 * _voice[voice].volume * data : 0;
+ *buf++ += (((int32) data) * _voice[voice].volume *
+ (255 - _voice[voice].panning)) >> 7;
+ *buf++ += (((int32) data) * _voice[voice].volume *
+ (_voice[voice].panning)) >> 7;
} else
*buf++ += _voice[voice].volume * data;
}
virtual void interrupt(void) {};
};
+/** A player for the Infogrames/RobHubbard2 format */
class Infogrames : public Paula {
public:
class Instruments {
public:
- struct Sample {
- int8 *data;
- int8 *dataRepeat;
- uint32 length;
- uint32 lengthRepeat;
- } _samples[32];
-
- uint8 _count;
- int8 *_sampleData;
-
Instruments();
+ template<typename T> Instruments(T ins) {
+ init();
+ bool result = load(ins);
+ assert(result);
+ }
~Instruments();
bool load(Common::SeekableReadStream &ins);
@@ -112,17 +118,39 @@ public:
return load(f);
return false;
}
+ void unload(void);
+
+ uint8 getCount(void) const { return _count; }
+
+ protected:
+ struct Sample {
+ int8 *data;
+ int8 *dataRepeat;
+ uint32 length;
+ uint32 lengthRepeat;
+ } _samples[32];
+
+ uint8 _count;
+ int8 *_sampleData;
+
+ void init();
+
+ friend class Infogrames;
};
- Infogrames(GobEngine *vm, bool stereo = false);
+ Infogrames(Instruments &ins, bool stereo = false, int rate = 44100);
~Infogrames();
Instruments *getInstruments(void) const { return _instruments; }
bool getRepeating(void) const { return _repCount != 0; }
void setRepeating (int32 repCount) { _repCount = repCount; }
- void restart(void) { if (!_data || !_instruments) return; init(); _end = false; }
- virtual void startPlay(void) { if (_data && _instruments) { restart(); _playing = true; } }
- virtual void stopPlay(void) { _playing = false; }
+ virtual void startPlay(void) { _playing = true;}
+ virtual void stopPlay(void)
+ {
+ _mutex.lock();
+ _playing = false;
+ _mutex.unlock();
+ }
virtual void pausePlay(bool pause) { _playing = !pause; }
bool load(Common::SeekableReadStream &dum);
@@ -133,17 +161,8 @@ public:
return load(f);
return false;
}
- void unload(bool destroyInstruments = false);
- template<typename T> bool loadInstruments(T ins) {
- unload(true);
- _instruments = new Instruments();
- if (!_instruments->load(ins)) {
- delete _instruments;
- _instruments = 0;
- return false;
- }
- return true;
- }
+ void unload(void);
+ void restart(void) { if (_data) { stopPlay(); init(); startPlay(); } }
protected:
Instruments *_instruments;
@@ -153,44 +172,38 @@ protected:
byte *_data;
int32 _repCount;
- uint16 _volume;
- int16 _period;
- byte *_volSlideBlocks;
- byte *_periodSlideBlocks;
byte *_subSong;
byte *_cmdBlocks;
- uint8 _sample;
+ byte *_volSlideBlocks;
+ byte *_periodSlideBlocks;
uint8 _speedCounter;
uint8 _speed;
- uint8 _newVol;
- uint8 _field_1E;
+
+ uint16 _volume;
+ int16 _period;
+ uint8 _sample;
struct Slide {
- int16 finetuneNeg;
- int16 finetunePos;
byte *data;
int8 amount;
uint8 dataOffset;
- uint8 flags; // 0: Apply finetune modifier, 2: Don't slide, 7: Continuous
+ int16 finetuneNeg;
+ int16 finetunePos;
uint8 curDelay1;
uint8 curDelay2;
+ uint8 flags; // 0: Apply finetune modifier, 2: Don't slide, 7: Continuous
};
struct Channel {
byte *cmdBlockIndices;
- byte *cmds;
byte *cmdBlocks;
+ byte *cmds;
+ uint8 ticks;
+ uint8 tickCount;
Slide volSlide;
Slide periodSlide;
- int16 curPeriod;
int16 period;
- uint16 curCmdBlock;
- uint16 flags; // 0: Need init, 5: Loop cmdBlocks, 6: Ignore channel
- uint8 ticks;
- uint8 tickCount;
int8 periodMod;
- uint8 field_2B;
- uint8 field_2C;
- uint8 field_2F;
+ uint8 flags; // 0: Need init, 5: Loop cmdBlocks, 6: Ignore channel
} _chn[4];
void init(void);
@@ -211,8 +224,13 @@ public:
bool getRepeating(void) const { return _repCount != 0; }
void setRepeating (int32 repCount) { _repCount = repCount; }
int getIndex(void) const { return _index; }
- virtual void startPlay(void);
- virtual void stopPlay(void) { _mutex.lock(); _playing = false; _mutex.unlock(); }
+ virtual void startPlay(void) { if (_data) _playing = true; }
+ virtual void stopPlay(void)
+ {
+ _mutex.lock();
+ _playing = false;
+ _mutex.unlock();
+ }
virtual void playTrack(const char *trackname);
virtual void playBgMusic(void);
virtual bool load(const char *filename);
@@ -265,6 +283,9 @@ protected:
void pollMusic(void);
};
+/**
+ * A dummy class for the "null" sound driver
+ */
class Adlib_Dummy: public Adlib {
public:
Adlib_Dummy(GobEngine *vm) : Adlib(vm) {}
diff --git a/engines/gob/sound.cpp b/engines/gob/sound.cpp
index 0c1e612b9f..aa7724a294 100644
--- a/engines/gob/sound.cpp
+++ b/engines/gob/sound.cpp
@@ -95,18 +95,14 @@ void Snd::speakerOff(void) {
}
void Snd::playSample(Snd::SoundDesc *sndDesc, int16 repCount, int16 frequency) {
- if (frequency == 0)
+ if (frequency <= 0)
frequency = sndDesc->frequency;
- if (frequency <= 0) {
- warning("Attempted to play a sample with a frequency of %d (sndDesc->freq = %d)", frequency, sndDesc->frequency);
- return;
- }
-// assert(frequency > 0);
+ for (int i = 0; i < ARRAYSIZE(_loopingSounds); i++)
+ _loopingSounds[i] = 0;
+ _vm->_mixer->stopHandle(sndDesc->handle);
- if (!_vm->_mixer->isSoundHandleActive(sndDesc->handle)) {
- _vm->_mixer->playRaw(&sndDesc->handle, sndDesc->data, sndDesc->size, frequency, 0);
- }
+ _vm->_mixer->playRaw(&sndDesc->handle, sndDesc->data, sndDesc->size, frequency, 0);
sndDesc->repCount = repCount - 1;
sndDesc->frequency = frequency;