diff options
-rw-r--r-- | engines/gob/cdrom.cpp | 6 | ||||
-rw-r--r-- | engines/gob/game.cpp | 4 | ||||
-rw-r--r-- | engines/gob/game.h | 5 | ||||
-rw-r--r-- | engines/gob/gob.cpp | 11 | ||||
-rw-r--r-- | engines/gob/gob.h | 2 | ||||
-rw-r--r-- | engines/gob/goblin.cpp | 164 | ||||
-rw-r--r-- | engines/gob/goblin.h | 4 | ||||
-rw-r--r-- | engines/gob/goblin_v2.cpp | 164 | ||||
-rw-r--r-- | engines/gob/inter.h | 3 | ||||
-rw-r--r-- | engines/gob/inter_v2.cpp | 244 | ||||
-rw-r--r-- | engines/gob/mult_v2.cpp | 15 | ||||
-rw-r--r-- | engines/gob/music.cpp | 212 | ||||
-rw-r--r-- | engines/gob/music.h | 131 | ||||
-rw-r--r-- | engines/gob/sound.cpp | 14 |
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; |