aboutsummaryrefslogtreecommitdiff
path: root/engines/neverhood
diff options
context:
space:
mode:
authorjohndoe1232012-09-22 00:55:40 +0000
committerWillem Jan Palenstijn2013-05-08 20:43:42 +0200
commitfc0e40db304aa489d4117299fcce1f80ba0b6379 (patch)
treee8f25ec91d06c4150e17a661c2285c1f411b89eb /engines/neverhood
parent0bb70c39f084dc122d213b07b1ef2d946608fe88 (diff)
downloadscummvm-rg350-fc0e40db304aa489d4117299fcce1f80ba0b6379.tar.gz
scummvm-rg350-fc0e40db304aa489d4117299fcce1f80ba0b6379.tar.bz2
scummvm-rg350-fc0e40db304aa489d4117299fcce1f80ba0b6379.zip
NEVERHOOD: Implement the actual audio code
Sounds and music play now in some scenes (I didn't change the comments to code in all modules yet) - Fix calcHash to ignore non-alphanumeric characters, this fixes at least one animation glitch (when inserting tapes into the player) - Move SoundResource to sound.cpp
Diffstat (limited to 'engines/neverhood')
-rw-r--r--engines/neverhood/entity.h1
-rw-r--r--engines/neverhood/gamemodule.cpp6
-rw-r--r--engines/neverhood/klayman.cpp20
-rw-r--r--engines/neverhood/klayman.h2
-rw-r--r--engines/neverhood/module1000.cpp20
-rw-r--r--engines/neverhood/module1100.cpp45
-rw-r--r--engines/neverhood/module1200.cpp27
-rw-r--r--engines/neverhood/module1300.cpp42
-rw-r--r--engines/neverhood/module1400.cpp40
-rw-r--r--engines/neverhood/navigationscene.h2
-rw-r--r--engines/neverhood/neverhood.cpp4
-rw-r--r--engines/neverhood/neverhood.h2
-rw-r--r--engines/neverhood/resource.cpp44
-rw-r--r--engines/neverhood/resource.h16
-rw-r--r--engines/neverhood/resourceman.cpp2
-rw-r--r--engines/neverhood/scene.cpp16
-rw-r--r--engines/neverhood/sound.cpp463
-rw-r--r--engines/neverhood/sound.h120
18 files changed, 673 insertions, 199 deletions
diff --git a/engines/neverhood/entity.h b/engines/neverhood/entity.h
index 9256c13ba8..22eb780024 100644
--- a/engines/neverhood/entity.h
+++ b/engines/neverhood/entity.h
@@ -27,6 +27,7 @@
#include "neverhood/neverhood.h"
#include "neverhood/gamevars.h"
#include "neverhood/graphics.h"
+#include "neverhood/sound.h"
namespace Neverhood {
diff --git a/engines/neverhood/gamemodule.cpp b/engines/neverhood/gamemodule.cpp
index e2494af453..7841e278c3 100644
--- a/engines/neverhood/gamemodule.cpp
+++ b/engines/neverhood/gamemodule.cpp
@@ -298,9 +298,9 @@ uint32 GameModule::handleMessage(int messageNum, const MessageParam &param, Enti
void GameModule::startup() {
// TODO: Displaying of error text probably not needed in ScummVM
// createModule(1500, 0); // Logos and intro video //Real
-#if 0
+#if 1
_vm->gameState().sceneNum = 0;
- createModule(1200, -1);
+ createModule(1400, -1);
#endif
#if 0
_vm->gameState().sceneNum = 0;
@@ -339,7 +339,7 @@ void GameModule::startup() {
_vm->gameState().sceneNum = 8;
createModule(2600, -1);
#endif
-#if 1
+#if 0
_vm->gameState().which = 0;
_vm->gameState().sceneNum = 1;
createModule(2700, -1);
diff --git a/engines/neverhood/klayman.cpp b/engines/neverhood/klayman.cpp
index ca30e3bccb..00008830e7 100644
--- a/engines/neverhood/klayman.cpp
+++ b/engines/neverhood/klayman.cpp
@@ -60,7 +60,7 @@ static const KlaymanIdleTableItem klaymanTable4[] = {
Klayman::Klayman(NeverhoodEngine *vm, Entity *parentScene, int16 x, int16 y, int surfacePriority, int objectPriority, NRectArray *clipRects)
: AnimatedSprite(vm, objectPriority), _soundResource1(vm), _soundResource2(vm),
_counterMax(0), _counter(0), _isMoveObjectRequested(false), _counter3Max(0), _isWalkingOpenDoorNotified(false), _counter1(0),
- _counter2(0), /*_field118(0), */_status2(0), _acceptInput(true), _attachedSprite(NULL), _isWalking(false),
+ _tapesToInsert(0), /*_field118(0), */_status2(0), _acceptInput(true), _attachedSprite(NULL), _isWalking(false),
_status3(1), _parentScene(parentScene), _isSneaking(false), _isLargeStep(false), _flagF6(false), _isLeverDown(false),
_flagFA(false), _ladderStatus(0), _pathPoints(NULL), _resourceHandle(-1), _soundFlag(false) {
@@ -2119,16 +2119,16 @@ void Klayman::cbLeverReleasedEvent() {
void Klayman::stInsertDisk() {
if (!stStartActionFromIdle(AnimationCallback(&Klayman::stInsertDisk))) {
_status2 = 2;
- _counter2 = 0;
+ _tapesToInsert = 0;
for (uint32 i = 0; i < 20; i++) {
if (getSubVar(0x02038314, i)) {
setSubVar(0x02720344, i, 1);
setSubVar(0x02038314, i, 0);
- _counter2++;
+ _tapesToInsert++;
}
}
- if (_counter2 == 0) {
- gotoState(NULL);
+ if (_tapesToInsert == 0) {
+ GotoState(NULL);
gotoNextStateExt();
} else {
startAnimation(0xD8C8D100, 0, -1);
@@ -2136,7 +2136,7 @@ void Klayman::stInsertDisk() {
SetSpriteUpdate(&Klayman::spriteUpdate41F250);
SetMessageHandler(&Klayman::hmInsertDisk);
_acceptInput = false;
- _counter2--;
+ _tapesToInsert--;
}
}
}
@@ -2145,12 +2145,12 @@ uint32 Klayman::hmInsertDisk(int messageNum, const MessageParam &param, Entity *
switch (messageNum) {
case 0x100D:
if (param.asInteger() == 0x06040580) {
- if (_counter2 == 0) {
- // TODO: Calc calcHash value somewhere else
+ if (_tapesToInsert == 0) {
+ // TODO: Calc calcHash value somewhere else
nextAnimationByHash(0xD8C8D100, calcHash("GoToStartLoop/Finish"), 0);
}
- } else if (_counter2 != 0 && param.asInteger() == calcHash("GoToStartLoop/Finish")) {
- _counter2--;
+ } else if (_tapesToInsert != 0 && param.asInteger() == calcHash("GoToStartLoop/Finish")) {
+ _tapesToInsert--;
startAnimationByHash(0xD8C8D100, 0x01084280, 0);
} else if (param.asInteger() == 0x062A1510) {
_soundResource1.play(0x41688704);
diff --git a/engines/neverhood/klayman.h b/engines/neverhood/klayman.h
index b752b1ecdb..cbf17a01f8 100644
--- a/engines/neverhood/klayman.h
+++ b/engines/neverhood/klayman.h
@@ -185,7 +185,7 @@ protected:
int16 _counter, _counterMax;
int16 _counter3, _counter3Max;
int16 _counter1;
- int16 _counter2;
+ int16 _tapesToInsert;
bool _flagF6;
bool _isLeverDown;
bool _isWalkingOpenDoorNotified;
diff --git a/engines/neverhood/module1000.cpp b/engines/neverhood/module1000.cpp
index 1c30681401..2db598bb3e 100644
--- a/engines/neverhood/module1000.cpp
+++ b/engines/neverhood/module1000.cpp
@@ -31,8 +31,8 @@ Module1000::Module1000(NeverhoodEngine *vm, Module *parentModule, int which)
_musicFileHash = getGlobalVar(0xD0A14D10) ? 0x81106480 : 0x00103144;
- // TODO SoundMan_addMusic(0x03294419, 0x061880C6);
- // TODO SoundMan_addMusic(0x03294419, _musicFileHash);
+ _vm->_soundMan->addMusic(0x03294419, 0x061880C6);
+ _vm->_soundMan->addMusic(0x03294419, _musicFileHash);
if (which < 0) {
createScene(_vm->gameState().sceneNum, -1);
@@ -45,7 +45,7 @@ Module1000::Module1000(NeverhoodEngine *vm, Module *parentModule, int which)
}
Module1000::~Module1000() {
- // TODO SoundMan_deleteMusicGroup(0x03294419);
+ _vm->_soundMan->deleteMusicGroup(0x03294419);
}
void Module1000::createScene(int sceneNum, int which) {
@@ -53,24 +53,24 @@ void Module1000::createScene(int sceneNum, int which) {
_vm->gameState().sceneNum = sceneNum;
switch (_vm->gameState().sceneNum) {
case 0:
- // TODO SoundMan_startMusic(0x061880C6, 0, 0, 1);
+ _vm->_soundMan->startMusic(0x061880C6, 0, 0);
_childObject = new Scene1001(_vm, this, which);
break;
case 1:
- // TODO SoundMan_startMusic(0x061880C6, 0, 0, 1);
+ _vm->_soundMan->startMusic(0x061880C6, 0, 0);
_childObject = new Scene1002(_vm, this, which);
break;
case 2:
- // TODO SoundMan_startMusic(0x061880C6, 0, 0);
+ _vm->_soundMan->startMusic(0x061880C6, 0, 0);
_childObject = new Class152(_vm, this, 0xC084110C, 0x41108C00);
break;
case 3:
- // TODO SoundMan_stopMusic(0x061880C6, 0, 2);
+ _vm->_soundMan->stopMusic(0x061880C6, 0, 2);
_childObject = new Scene1004(_vm, this, which);
break;
case 4:
- // TODO SoundMan_stopMusic(0x061880C6, 0, 0);
- // TODO SoundMan_startMusic(_musicFileHash, 0, 0, 1);
+ _vm->_soundMan->stopMusic(0x061880C6, 0, 0);
+ _vm->_soundMan->startMusic(_musicFileHash, 0, 0);
_childObject = new Scene1005(_vm, this, which);
break;
}
@@ -105,7 +105,7 @@ void Module1000::updateScene() {
createScene(1, 2);
break;
case 4:
- // TODO SoundMan_stopMusic(_musicFileHash, 0, 1);
+ _vm->_soundMan->stopMusic(_musicFileHash, 0, 1);
createScene(3, 1);
break;
}
diff --git a/engines/neverhood/module1100.cpp b/engines/neverhood/module1100.cpp
index 8b73598e03..e948c2b045 100644
--- a/engines/neverhood/module1100.cpp
+++ b/engines/neverhood/module1100.cpp
@@ -22,6 +22,7 @@
#include "neverhood/module1100.h"
#include "neverhood/gamemodule.h"
+#include "neverhood/navigationscene.h"
namespace Neverhood {
@@ -36,16 +37,16 @@ Module1100::Module1100(NeverhoodEngine *vm, Module *parentModule, int which)
createScene(9, 3);
}
- // TODO SoundMan_addSoundList(0x2C818, dword_4B85B0, true);
+ // TODO SoundMan_addSoundList(0x0002C818, dword_4B85B0, true);
// TODO SoundMan_setSoundListParams(dword_4B85B0, true, 50, 600, 20, 250);
- // TODO SoundMan_setSoundParams(0x74E01054, false, 100, 200, 10, 20);
- // TODO SoundMan_setSoundVolume(0x74E01054, 60);
- // TODO SoundMan_playTwoSounds(0x2C818, 0x41861371, 0x43A2507F);
+ _vm->_soundMan->setSoundParams(0x74E01054, false, 100, 200, 10, 20);
+ _vm->_soundMan->setSoundVolume(0x74E01054, 60);
+ _vm->_soundMan->playTwoSounds(0x0002C818, 0x41861371, 0x43A2507F, 0);
}
Module1100::~Module1100() {
- // TODO SoundMan_deleteGroup(0x2C818);
+ _vm->_soundMan->deleteGroup(0x0002C818);
}
void Module1100::createScene(int sceneNum, int which) {
@@ -86,11 +87,11 @@ void Module1100::createScene(int sceneNum, int which) {
createSmackerScene(0x04180007, true, false, false);
break;
case 6:
- // TODO SoundMan_deleteSoundGroup(0x2C818);
+ _vm->_soundMan->deleteSoundGroup(0x0002C818);
createSmackerScene(kSmackerFileHashList06, true, true, false);
break;
case 7:
- // TODO SoundMan_setSoundParams(0x74E01054, false, 0, 0, 0, 0);
+ _vm->_soundMan->setSoundParams(0x74E01054, false, 0, 0, 0, 0);
createSmackerScene(kSmackerFileHashList07, true, true, false);
break;
case 8:
@@ -98,7 +99,7 @@ void Module1100::createScene(int sceneNum, int which) {
break;
case 1002:
_countdown = 40;
- // TODO SoundMan_setTwoSoundsPlayFlag(true);
+ _vm->_soundMan->setTwoSoundsPlayFlag(true);
createSmackerScene(0x00012211, true, true, false);
break;
}
@@ -111,9 +112,9 @@ void Module1100::updateScene() {
switch (_vm->gameState().sceneNum) {
case 0:
_countdown = 0;
- // TODO SoundMan_playTwoSounds(0x2C818, 0x48498E46, 0x50399F64);
- // TODO SoundMan_setSoundVolume(0x48498E46, 65);
- // TODO SoundMan_setSoundVolume(0x50399F64, 65);
+ _vm->_soundMan->playTwoSounds(0x0002C818, 0x48498E46, 0x50399F64, 0);
+ _vm->_soundMan->setSoundVolume(0x48498E46, 65);
+ _vm->_soundMan->setSoundVolume(0x50399F64, 65);
if (_moduleResult == 0) {
createScene(1, 0);
} else if (_moduleResult == 1) {
@@ -121,7 +122,7 @@ void Module1100::updateScene() {
}
break;
case 1:
- // TODO SoundMan_playTwoSounds(0x2C818, 0x41861371, 0x43A2507F);
+ _vm->_soundMan->playTwoSounds(0x0002C818, 0x41861371, 0x43A2507F, 0);
if (getGlobalVar(0x0C0288F4)) {
if (_moduleResult == 0) {
createScene(6, -1);
@@ -137,7 +138,7 @@ void Module1100::updateScene() {
}
break;
case 2:
- // TODO SoundMan_setSoundParams(0x74E01054, false, 0, 0, 0, 0);
+ _vm->_soundMan->setSoundParams(0x74E01054, false, 0, 0, 0, 0);
if (_navigationAreaType == 3) {
createScene(7, -1);
} else if (_moduleResult == 1) {
@@ -161,6 +162,7 @@ void Module1100::updateScene() {
}
break;
case 5:
+ _vm->_soundMan->setTwoSoundsPlayFlag(false);
if (getGlobalVar(0x610210B7)) {
createScene(3, 0);
} else {
@@ -168,9 +170,11 @@ void Module1100::updateScene() {
}
break;
case 6:
+ _vm->_soundMan->setTwoSoundsPlayFlag(false);
leaveModule(1);
break;
case 7:
+ _vm->_soundMan->setTwoSoundsPlayFlag(false);
createScene(2, 2);
break;
case 8:
@@ -181,8 +185,9 @@ void Module1100::updateScene() {
}
break;
case 1002:
+ _vm->_soundMan->setTwoSoundsPlayFlag(false);
_countdown = 0;
- // TODO SoundMan_playTwoSounds(0x2C818, 0x48498E46, 0x50399F64, 0);
+ _vm->_soundMan->playTwoSounds(0x0002C818, 0x48498E46, 0x50399F64, 0);
createScene(1, 1);
break;
}
@@ -191,7 +196,7 @@ void Module1100::updateScene() {
case 0:
#if 0 // TODO
if (navigationScene()->soundFlag1 && _countdown != 0 && (--_countdown == 0)) {
- SoundMan_playTwoSounds(0x2C818, 0x48498E46, 0x50399F64);
+ SoundMan_playTwoSounds(0x0002C818, 0x48498E46, 0x50399F64);
SoundMan_setSoundVolume(0x48498E46, 65);
SoundMan_setSoundVolume(0x50399F64, 65);
}
@@ -200,21 +205,21 @@ void Module1100::updateScene() {
case 1:
#if 0 // TODO
if (navigationScene()->soundFlag1 && _countdown != 0 && (--_countdown == 0)) {
- SoundMan_playTwoSounds(0x2C818, 0x41861371, 0x43A2507F);
+ SoundMan_playTwoSounds(0x0002C818, 0x41861371, 0x43A2507F);
}
#endif
break;
case 2:
- // TODO SoundMan_setSoundParams(0x74E01054, !navigationScene()->soundFlag1, 0, 0, 0, 0);
+ _vm->_soundMan->setSoundParams(0x74E01054, !navigationScene()->getSoundFlag1(), 0, 0, 0, 0);
break;
case 5:
case 6:
case 7:
case 1002:
if (_countdown != 0 && (--_countdown == 0)) {
- // TODO SoundMan_playTwoSounds(0x2C818, 0x48498E46, 0x50399F64);
- // TODO SoundMan_setSoundVolume(0x48498E46, 65);
- // TODO SoundMan_setSoundVolume(0x50399F64, 65);
+ _vm->_soundMan->playTwoSounds(0x0002C818, 0x48498E46, 0x50399F64, 0);
+ _vm->_soundMan->setSoundVolume(0x48498E46, 65);
+ _vm->_soundMan->setSoundVolume(0x50399F64, 65);
}
break;
}
diff --git a/engines/neverhood/module1200.cpp b/engines/neverhood/module1200.cpp
index 7599d7655d..33b791aa9b 100644
--- a/engines/neverhood/module1200.cpp
+++ b/engines/neverhood/module1200.cpp
@@ -39,12 +39,12 @@ Module1200::Module1200(NeverhoodEngine *vm, Module *parentModule, int which)
createScene(0, 0);
}
- // TODO SoundMan_addMusic(0x00478311, 0x62222CAE);
- // TODO SoundMan_startMusic(0x62222CAE, 0, 0, 1);
+ _vm->_soundMan->addMusic(0x00478311, 0x62222CAE);
+ _vm->_soundMan->startMusic(0x62222CAE, 0, 0);
}
Module1200::~Module1200() {
- // TODO SoundMan_deleteMusicGroup(0x00478311);
+ _vm->_soundMan->deleteMusicGroup(0x00478311);
}
void Module1200::createScene(int sceneNum, int which) {
@@ -58,7 +58,7 @@ void Module1200::createScene(int sceneNum, int which) {
_childObject = new Scene1202(_vm, this, which);
break;
case 2:
- // TODO SoundMan_stopMusic(0x62222CAE, 0, 0);
+ _vm->_soundMan->stopMusic(0x62222CAE, 0, 0);
createSmackerScene(0x31890001, true, true, false);
setGlobalVar(0x2A02C07B, 1);
break;
@@ -87,7 +87,7 @@ void Module1200::updateScene() {
createScene(0, 1);
break;
case 2:
- // TODO SoundMan_startMusic(0x62222CAE, 0, 0, 1);
+ _vm->_soundMan->startMusic(0x62222CAE, 0, 0);
createScene(0, 3);
break;
}
@@ -371,7 +371,7 @@ AsScene1201TntMan::AsScene1201TntMan(NeverhoodEngine *vm, Scene *parentScene, Sp
}
AsScene1201TntMan::~AsScene1201TntMan() {
- // TODO SoundMan_deleteSoundGroup(0x01D00560);
+ _vm->_soundMan->deleteSoundGroup(0x01D00560);
}
uint32 AsScene1201TntMan::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
@@ -426,8 +426,8 @@ void AsScene1201TntMan::sub40CD60() {
}
void AsScene1201TntMan::sub40CD90() {
- // TODO SoundMan_addSound(0x01D00560, 0x4B044624, true);
- // TODO SoundMan_playSoundLooping(0x4B044624);
+ _vm->_soundMan->addSound(0x01D00560, 0x4B044624);
+ _vm->_soundMan->playSoundLooping(0x4B044624);
_flag = true;
startAnimation(0x85084190, 0, -1);
SetMessageHandler(&AsScene1201TntMan::handleMessage);
@@ -447,7 +447,7 @@ Class465::Class465(NeverhoodEngine *vm, Sprite *asTntMan)
}
Class465::~Class465() {
- // TODO SoundMan_deleteSoundGroup(0x041080A4);
+ _vm->_soundMan->deleteSoundGroup(0x041080A4);
}
void Class465::update() {
@@ -455,8 +455,8 @@ void Class465::update() {
if (getGlobalVar(0x20A0C516)) {
setVisible(true);
SetUpdateHandler(&AnimatedSprite::update);
- // TODO SoundMan_addSound(0x041080A4, 0x460A1050, true);
- // TODO SoundMan_playSoundLooping(0x460A1050);
+ _vm->_soundMan->addSound(0x041080A4, 0x460A1050);
+ _vm->_soundMan->playSoundLooping(0x460A1050);
}
}
@@ -1227,10 +1227,7 @@ bool Scene1202::isSolved() {
}
void Scene1202::doPaletteEffect() {
-#if 0 // TODO
- Palette2 *palette2 = (Palette2*)_palette;
- palette2->startFadeToPalette(24);
-#endif
+ // TODO
}
} // End of namespace Neverhood
diff --git a/engines/neverhood/module1300.cpp b/engines/neverhood/module1300.cpp
index b7c588f114..ee4dc7a42c 100644
--- a/engines/neverhood/module1300.cpp
+++ b/engines/neverhood/module1300.cpp
@@ -35,12 +35,12 @@ namespace Neverhood {
Module1300::Module1300(NeverhoodEngine *vm, Module *parentModule, int which)
: Module(vm, parentModule) {
- // TODO SoundMan_addMusic(0x61C090, 0x203197);
+ _vm->_soundMan->addMusic(0x61C090, 0x203197);
// TODO SoundMan_addSoundList(0x61C090, dword_4B2868, true);
// TODO SoundMan_setSoundListParams(dword_4B2868, false, 50, 600, 20, 150);
- // TODO SoundMan_playTwoSounds(0x61C090, 0x48498E46, 0x50399F64, 0);
- // TODO SoundMan_setSoundVolume(0x48498E46, 70);
- // TODO SoundMan_setSoundVolume(0x50399F64, 70);
+ _vm->_soundMan->playTwoSounds(0x61C090, 0x48498E46, 0x50399F64, 0);
+ _vm->_soundMan->setSoundVolume(0x48498E46, 70);
+ _vm->_soundMan->setSoundVolume(0x50399F64, 70);
if (which < 0) {
if (_vm->gameState().sceneNum >= 1 && _vm->gameState().sceneNum <= 17)
@@ -94,7 +94,7 @@ Module1300::Module1300(NeverhoodEngine *vm, Module *parentModule, int which)
}
Module1300::~Module1300() {
- // TODO SoundMan_deleteGroup(0x61C090);
+ _vm->_soundMan->deleteGroup(0x61C090);
}
void Module1300::createScene(int sceneNum, int which) {
@@ -103,82 +103,82 @@ void Module1300::createScene(int sceneNum, int which) {
switch (_vm->gameState().sceneNum) {
case 1:
// TODO SoundMan_setSoundListParams(dword_4B2868, false, 0, 0, 0, 0);
- // TODO SoundMan_startMusic(0x203197, 0, 2, 1);
+ _vm->_soundMan->startMusic(0x203197, 0, 2);
_childObject = new Scene1302(_vm, this, which);
break;
case 2:
// TODO SoundMan_setSoundListParams(dword_4B2868, false, 0, 0, 0, 0);
- // TODO SoundMan_stopMusic(0x203197, 0, 2);
+ _vm->_soundMan->stopMusic(0x203197, 0, 2);
_childObject = new Scene1303(_vm, this, which);
break;
case 3:
// TODO SoundMan_setSoundListParams(dword_4B2868, false, 0, 0, 0, 0);
- // TODO SoundMan_stopMusic(0x203197, 0, 2);
+ _vm->_soundMan->stopMusic(0x203197, 0, 2);
_childObject = new Scene1304(_vm, this, which);
break;
case 4:
// TODO SoundMan_setSoundListParams(dword_4B2868, false, 0, 0, 0, 0);
- // TODO SoundMan_startMusic(0x203197, 0, 2, 1);
+ _vm->_soundMan->startMusic(0x203197, 0, 2);
_childObject = new Scene1305(_vm, this, which);
break;
case 5:
// TODO SoundMan_setSoundListParams(dword_4B2868, false, 0, 0, 0, 0);
- // TODO SoundMan_startMusic(0x203197, 0, 2, 1);
+ _vm->_soundMan->startMusic(0x203197, 0, 2);
_childObject = new Scene1306(_vm, this, which);
break;
case 6:
// TODO SoundMan_setSoundListParams(dword_4B2868, false, 0, 0, 0, 0);
- // TODO SoundMan_startMusic(0x203197, 0, 2, 1);
+ _vm->_soundMan->startMusic(0x203197, 0, 2);
_childObject = new Scene1307(_vm, this, which);
break;
case 7:
// TODO SoundMan_setSoundListParams(dword_4B2868, false, 0, 0, 0, 0);
- // TODO SoundMan_startMusic(0x203197, 0, 2, 1);
+ _vm->_soundMan->startMusic(0x203197, 0, 2);
_childObject = new Scene1308(_vm, this, which);
break;
case 8:
// TODO SoundMan_setSoundListParams(dword_4B2868, false, 0, 0, 0, 0);
- // TODO SoundMan_stopMusic(0x203197, 0, 2);
+ _vm->_soundMan->stopMusic(0x203197, 0, 2);
_childObject = new DiskplayerScene(_vm, this, 1);
break;
case 9:
// TODO SoundMan_setSoundListParams(dword_4B2868, false, 0, 0, 0, 0);
- // TODO SoundMan_stopMusic(0x203197, 0, 2);
+ _vm->_soundMan->stopMusic(0x203197, 0, 2);
createSmackerScene(0x20082818, true, true, false);
break;
case 10:
// TODO SoundMan_setSoundListParams(dword_4B2868, false, 0, 0, 0, 0);
- // TODO SoundMan_stopMusic(0x203197, 0, 2);
+ _vm->_soundMan->stopMusic(0x203197, 0, 2);
createSmackerScene(0x20082828, true, true, false);
break;
case 11:
// TODO SoundMan_setSoundListParams(0xdword_4B2868, true, 0, 0, 0, 0);
- // TODO SoundMan_stopMusic(0x203197, 0, 2);
+ _vm->_soundMan->stopMusic(0x203197, 0, 2);
createNavigationScene(0x004B27A8, which);
break;
case 12:
// TODO SoundMan_setSoundListParams(0xdword_4B2868, true, 0, 0, 0, 0);
- // TODO SoundMan_stopMusic(0x203197, 0, 2);
+ _vm->_soundMan->stopMusic(0x203197, 0, 2);
createNavigationScene(0x004B2718, which);
break;
case 13:
// TODO SoundMan_setSoundListParams(0xdword_4B2868, true, 0, 0, 0, 0);
- // TODO SoundMan_stopMusic(0x203197, 0, 2);
+ _vm->_soundMan->stopMusic(0x203197, 0, 2);
createNavigationScene(0x004B27D8, which);
break;
case 14:
// TODO SoundMan_setSoundListParams(0xdword_4B2868, true, 0, 0, 0, 0);
- // TODO SoundMan_stopMusic(0x203197, 0, 2);
+ _vm->_soundMan->stopMusic(0x203197, 0, 2);
createNavigationScene(0x004B2808, which);
break;
case 15:
// TODO SoundMan_setSoundListParams(0xdword_4B2868, true, 0, 0, 0, 0);
- // TODO SoundMan_stopMusic(0x203197, 0, 2);
+ _vm->_soundMan->stopMusic(0x203197, 0, 2);
createNavigationScene(0x004B2838, which);
break;
case 16:
// TODO SoundMan_setSoundListParams(dword_4B2868, false, 0, 0, 0, 0);
- // TODO SoundMan_stopMusic(0x203197, 0, 2);
+ _vm->_soundMan->stopMusic(0x203197, 0, 2);
_childObject = new Scene1317(_vm, this, which);
break;
case 17:
diff --git a/engines/neverhood/module1400.cpp b/engines/neverhood/module1400.cpp
index 370735695d..8d40c340ec 100644
--- a/engines/neverhood/module1400.cpp
+++ b/engines/neverhood/module1400.cpp
@@ -32,8 +32,8 @@ namespace Neverhood {
Module1400::Module1400(NeverhoodEngine *vm, Module *parentModule, int which)
: Module(vm, parentModule) {
- // TODO SoundMan_addMusic(0x00AD0012, 0x06333232);
- // TODO SoundMan_addMusic(0x00AD0012, 0x624A220E);
+ _vm->_soundMan->addMusic(0x00AD0012, 0x06333232);
+ _vm->_soundMan->addMusic(0x00AD0012, 0x624A220E);
if (which < 0) {
createScene(_vm->gameState().sceneNum, -1);
@@ -44,7 +44,7 @@ Module1400::Module1400(NeverhoodEngine *vm, Module *parentModule, int which)
}
Module1400::~Module1400() {
- // TODO SoundMan_deleteMusicGroup(0x00AD0012);
+ _vm->_soundMan->deleteMusicGroup(0x00AD0012);
}
void Module1400::createScene(int sceneNum, int which) {
@@ -52,33 +52,33 @@ void Module1400::createScene(int sceneNum, int which) {
_vm->gameState().sceneNum = sceneNum;
switch (_vm->gameState().sceneNum) {
case 0:
- // TODO SoundMan_startMusic(0x06333232, 0, 2, 1);
+ _vm->_soundMan->startMusic(0x06333232, 0, 2);
_childObject = new Scene1401(_vm, this, which);
break;
case 1:
- // TODO SoundMan_stopMusic(0x06333232, 0, 2);
- // TODO SoundMan_stopMusic(0x624A220E, 0, 2);
+ _vm->_soundMan->stopMusic(0x06333232, 0, 2);
+ _vm->_soundMan->stopMusic(0x624A220E, 0, 2);
_childObject = new Scene1402(_vm, this, which);
break;
case 2:
- // TODO SoundMan_stopMusic(0x06333232, 0, 2);
- // TODO SoundMan_startMusic(0x624A220E, 0, 2, 1);
+ _vm->_soundMan->stopMusic(0x06333232, 0, 2);
+ _vm->_soundMan->startMusic(0x624A220E, 0, 2);
_childObject = new Scene1403(_vm, this, which);
break;
case 3:
- // TODO SoundMan_startMusic(0x06333232, 0, 2, 1);
+ _vm->_soundMan->startMusic(0x06333232, 0, 2);
_childObject = new Scene1404(_vm, this, which);
break;
case 4:
- // TODO SoundMan_startMusic(0x06333232, 0, 2, 1);
+ _vm->_soundMan->startMusic(0x06333232, 0, 2);
_childObject = new Scene1405(_vm, this, which);
break;
case 5:
- // TODO SoundMan_stopMusic(0x06333232, 0, 2);
+ _vm->_soundMan->stopMusic(0x06333232, 0, 2);
_childObject = new DiskplayerScene(_vm, this, 2);
break;
case 6:
- // TODO SoundMan_stopMusic(0x06333232, 0, 2);
+ _vm->_soundMan->stopMusic(0x06333232, 0, 2);
_childObject = new Scene1407(_vm, this, which);
break;
}
@@ -148,7 +148,7 @@ Class525::Class525(NeverhoodEngine *vm)
}
Class525::~Class525() {
- // TODO SoundMan_deleteSoundGroup(0x01104C08);
+ _vm->_soundMan->deleteSoundGroup(0x01104C08);
}
void Class525::update4662A0() {
@@ -157,8 +157,8 @@ void Class525::update4662A0() {
sub466460();
}
if (_countdown2 != 0 && (--_countdown2 == 0)) {
- // TODO SoundMan_addSound(0x01104C08, 0x4A116437, true);
- // TODO SoundMan_playSoundLooping(0x4A116437);
+ _vm->_soundMan->addSound(0x01104C08, 0x4A116437);
+ _vm->_soundMan->playSoundLooping(0x4A116437);
}
}
@@ -211,7 +211,7 @@ void Class525::sub466420() {
}
void Class525::sub466460() {
- // TODO SoundMan_deleteSound(0x4A116437);
+ _vm->_soundMan->deleteSound(0x4A116437);
_soundResource1.play(0x4A120435);
startAnimation(0x4C210500, 0, -1);
}
@@ -406,7 +406,7 @@ Class489::Class489(NeverhoodEngine *vm, Scene *parentScene, Sprite *klayman, Spr
}
Class489::~Class489() {
- // TODO SoundMan_deleteSoundGroup(0x05331081);
+ _vm->_soundMan->deleteSoundGroup(0x05331081);
}
uint32 Class489::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
@@ -616,8 +616,8 @@ void Class489::sub434EC0() {
NextState(&Class489::sub434F40);
setGlobalVar(0x12A10DB3, 1);
_soundResource1.play(0xCC4A8456);
- // TODO SoundMan_addSound(0x05331081, 0xCE428854, true);
- // TODO SoundMan_playSoundLooping(0xCE428854);
+ _vm->_soundMan->addSound(0x05331081, 0xCE428854);
+ _vm->_soundMan->playSoundLooping(0xCE428854);
}
void Class489::sub434F40() {
@@ -634,7 +634,7 @@ void Class489::sub434F80() {
NextState(&Class489::sub434E90);
setGlobalVar(0x12A10DB3, 0);
_soundResource1.play(0xCC4A8456);
- // TODO SoundMan_deleteSound(0xCE428854);
+ _vm->_soundMan->deleteSound(0xCE428854);
}
void Class489::sub434FF0() {
diff --git a/engines/neverhood/navigationscene.h b/engines/neverhood/navigationscene.h
index c37a7fc178..4397a4372b 100644
--- a/engines/neverhood/navigationscene.h
+++ b/engines/neverhood/navigationscene.h
@@ -34,6 +34,8 @@ public:
NavigationScene(NeverhoodEngine *vm, Module *parentModule, uint32 navigationListId, int navigationIndex, const byte *itemsTypes);
virtual ~NavigationScene();
int getNavigationAreaType();
+ bool getSoundFlag1() const { return _soundFlag1; }
+ bool getSoundFlag2() const { return _soundFlag2; }
protected:
SmackerPlayer *_smackerPlayer;
bool _smackerDone;
diff --git a/engines/neverhood/neverhood.cpp b/engines/neverhood/neverhood.cpp
index abd937497e..e5c07b5b8d 100644
--- a/engines/neverhood/neverhood.cpp
+++ b/engines/neverhood/neverhood.cpp
@@ -100,6 +100,7 @@ Common::Error NeverhoodEngine::run() {
#if 1
_soundMan = new SoundMan(this);
+ _audioResourceMan = new AudioResourceMan(this);
_collisionMan = new CollisionMan(this);
_gameModule = new GameModule(this);
@@ -139,6 +140,8 @@ Common::Error NeverhoodEngine::run() {
//debug("millis %d", _system->getMillis());
_gameModule->handleUpdate();
_gameModule->draw();
+ _soundMan->update();
+ _audioResourceMan->update();
_screen->wait();
_screen->update();
@@ -149,6 +152,7 @@ Common::Error NeverhoodEngine::run() {
delete _gameModule;
delete _collisionMan;
delete _soundMan;
+ delete _audioResourceMan;
#endif
diff --git a/engines/neverhood/neverhood.h b/engines/neverhood/neverhood.h
index 13ea39986a..2aa84e5cb7 100644
--- a/engines/neverhood/neverhood.h
+++ b/engines/neverhood/neverhood.h
@@ -46,6 +46,7 @@ class GameVars;
class ResourceMan;
class Screen;
class SoundMan;
+class AudioResourceMan;
class StaticData;
struct NPoint;
@@ -87,6 +88,7 @@ public:
CollisionMan *_collisionMan;
SoundMan *_soundMan;
+ AudioResourceMan *_audioResourceMan;
public:
diff --git a/engines/neverhood/resource.cpp b/engines/neverhood/resource.cpp
index 7b0aa94b13..9bf6549ffe 100644
--- a/engines/neverhood/resource.cpp
+++ b/engines/neverhood/resource.cpp
@@ -640,44 +640,20 @@ DataResource::DRDirectoryItem *DataResource::findDRDirectoryItem(uint32 nameHash
return NULL;
}
-// SoundResource
-// ALL TODO
-
-SoundResource::SoundResource(NeverhoodEngine *vm)
- : _vm(vm) {
-}
-
-bool SoundResource::isPlaying() {
- return false;
-}
-
-void SoundResource::load(uint32 fileHash) {
-}
-
-void SoundResource::unload() {
-}
-
-void SoundResource::play(uint32 fileHash, bool looping) {
-}
-
-void SoundResource::play() {
-}
-
-void SoundResource::setVolume(int volume) {
-}
-
uint32 calcHash(const char *value) {
uint32 hash = 0, shiftValue = 0;
while (*value != 0) {
char ch = *value++;
- if (ch >= 'a' && ch <= 'z')
- ch -= 32;
- else if (ch >= '0' && ch <= '9')
- ch += 22;
- shiftValue += ch - 64;
- if (shiftValue >= 32)
- shiftValue -= 32;
- hash ^= 1 << shiftValue;
+ if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9')) {
+ if (ch >= 'a' && ch <= 'z')
+ ch -= 32;
+ else if (ch >= '0' && ch <= '9')
+ ch += 22;
+ shiftValue += ch - 64;
+ if (shiftValue >= 32)
+ shiftValue -= 32;
+ hash ^= 1 << shiftValue;
+ }
}
return hash;
}
diff --git a/engines/neverhood/resource.h b/engines/neverhood/resource.h
index b0cd464e06..16782968f8 100644
--- a/engines/neverhood/resource.h
+++ b/engines/neverhood/resource.h
@@ -191,22 +191,6 @@ protected:
DataResource::DRDirectoryItem *findDRDirectoryItem(uint32 nameHash, uint16 type);
};
-// TODO: Dummy class atm
-
-class SoundResource {
-public:
- SoundResource(NeverhoodEngine *vm);
- bool isPlaying();
- void load(uint32 fileHash);
- void unload();
- void play(uint32 fileHash, bool looping = false);
- void play();
- void stop() { /*DUMMY*/ }
- void setVolume(int volume);
-protected:
- NeverhoodEngine *_vm;
-};
-
uint32 calcHash(const char *value);
} // End of namespace Neverhood
diff --git a/engines/neverhood/resourceman.cpp b/engines/neverhood/resourceman.cpp
index 0538f58e87..c073e976a4 100644
--- a/engines/neverhood/resourceman.cpp
+++ b/engines/neverhood/resourceman.cpp
@@ -35,7 +35,7 @@ void ResourceMan::addArchive(const Common::String &filename) {
uint archiveIndex = _archives.size();
archive->open(filename);
_archives.push_back(archive);
- debug("ResourceMan::addArchive(%s) %d files", filename.c_str(), archive->getCount());
+ debug(3, "ResourceMan::addArchive(%s) %d files", filename.c_str(), archive->getCount());
_entries.reserve(_entries.size() + archive->getCount());
for (uint archiveEntryIndex = 0; archiveEntryIndex < archive->getCount(); archiveEntryIndex++) {
BlbArchiveEntry *archiveEntry = archive->getEntry(archiveEntryIndex);
diff --git a/engines/neverhood/scene.cpp b/engines/neverhood/scene.cpp
index d189fad240..8520d6467d 100644
--- a/engines/neverhood/scene.cpp
+++ b/engines/neverhood/scene.cpp
@@ -375,7 +375,7 @@ uint32 Scene::smackerHandleMessage(int messageNum, const MessageParam &param, En
}
bool Scene::queryPositionSprite(int16 mouseX, int16 mouseY) {
- debug("Scene::queryPositionSprite(%d, %d)", mouseX, mouseY);
+ //debug("Scene::queryPositionSprite(%d, %d)", mouseX, mouseY);
for (uint i = 0; i < _vm->_collisionMan->getSpriteCount(); i++) {
Sprite *sprite = _vm->_collisionMan->getSprite(i);
if (sprite->hasMessageHandler() && sprite->isPointInside(mouseX, mouseY) &&
@@ -397,7 +397,7 @@ bool Scene::queryPositionRectList(int16 mouseX, int16 mouseY) {
for (uint j = 0; j < rectList[i].subRects.size(); j++) {
debug(2, " (%d, %d) ? (%d, %d, %d, %d)", mouseX, mouseY, rectList[i].subRects[j].rect.x1, rectList[i].subRects[j].rect.y1, rectList[i].subRects[j].rect.x2, rectList[i].subRects[j].rect.y2);
if (rectList[i].subRects[j].rect.contains(mouseX, mouseY)) {
- debug("Scene::queryPositionRectList() -> %08X", rectList[i].subRects[j].messageListId);
+ //debug("Scene::queryPositionRectList() -> %08X", rectList[i].subRects[j].messageListId);
return setMessageList2(rectList[i].subRects[j].messageListId);
}
}
@@ -416,7 +416,7 @@ void Scene::setMessageList(uint32 id, bool messageListFlag, bool systemCallbackF
}
void Scene::setMessageList(MessageList *messageList, bool messageListFlag, bool systemCallbackFlag) {
- debug("Scene::setMessageList(%p)", (void*)messageList);
+ //debug("Scene::setMessageList(%p)", (void*)messageList);
_messageList = messageList;
_messageListCount = _messageList ? _messageList->size() : 0;
_messageListIndex = 0;
@@ -426,11 +426,13 @@ void Scene::setMessageList(MessageList *messageList, bool messageListFlag, bool
_messageListStatus = 1;
sendMessage(_klayman, 0x101C, 0);
+#if 0
// DEBUG: Show message list
for (uint i = 0; i < messageList->size(); i++) {
debug("A: %02d: %04X, %08X", i, (*messageList)[i].messageNum, (*messageList)[i].messageValue);
}
debug("A: ================================================================");
+#endif
}
@@ -441,13 +443,15 @@ bool Scene::setMessageList2(uint32 id, bool messageListFlag, bool systemCallback
bool Scene::setMessageList2(MessageList *messageList, bool messageListFlag, bool systemCallbackFlag) {
bool result = false;
- debug("Scene::setMessageList2(%p)", (void*)messageList);
+ //debug("Scene::setMessageList2(%p)", (void*)messageList);
+#if 0
// DEBUG: Show message list
for (uint i = 0; i < messageList->size(); i++) {
debug("B: %02d: %04X, %08X", i, (*messageList)[i].messageNum, (*messageList)[i].messageValue);
}
debug("B: ================================================================");
+#endif
if (_messageListStatus == 1) {
if (messageList != _messageList2) {
@@ -500,7 +504,7 @@ void Scene::runMessageList() {
uint32 messageNum = (*_messageList)[_messageListIndex].messageNum;
uint32 messageParam = (*_messageList)[_messageListIndex].messageValue;
- debug("Scene::runMessageList() %04X, %08X", messageNum, messageParam);
+ //debug("Scene::runMessageList() %04X, %08X", messageNum, messageParam);
_messageListIndex++;
if (_messageListIndex == _messageListCount) {
@@ -573,7 +577,7 @@ void Scene::clearRectList() {
void Scene::loadHitRectList() {
HitRectList *hitRectList = _dataResource.getHitRectList();
- debug("Scene::loadHitRectList() hitRectList = %p", (void*)hitRectList);
+ //debug("Scene::loadHitRectList() hitRectList = %p", (void*)hitRectList);
if (hitRectList) {
_hitRectList = *hitRectList;
_vm->_collisionMan->setHitRects(&_hitRectList);
diff --git a/engines/neverhood/sound.cpp b/engines/neverhood/sound.cpp
index 91a23bfc7b..bd2f223998 100644
--- a/engines/neverhood/sound.cpp
+++ b/engines/neverhood/sound.cpp
@@ -20,36 +20,101 @@
*
*/
+#include "common/memstream.h"
#include "graphics/palette.h"
#include "neverhood/sound.h"
+#include "neverhood/resourceman.h"
namespace Neverhood {
// TODO Put more stuff into the constructors/destructors of the item structs
// TODO Some parts are quite bad here, but my priority is to get sound working at all
+SoundResource::SoundResource(NeverhoodEngine *vm)
+ : _vm(vm), _soundIndex(-1) {
+}
+
+SoundResource::~SoundResource() {
+ unload();
+}
+
+bool SoundResource::isPlaying() {
+ return _soundIndex >= 0 &&
+ _vm->_audioResourceMan->isSoundPlaying(_soundIndex);
+}
+
+void SoundResource::load(uint32 fileHash) {
+ unload();
+ _soundIndex = _vm->_audioResourceMan->addSound(fileHash);
+ _vm->_audioResourceMan->loadSound(_soundIndex);
+}
+
+void SoundResource::unload() {
+ if (_soundIndex >= 0) {
+ _vm->_audioResourceMan->removeSound(_soundIndex);
+ _soundIndex = -1;
+ }
+}
+
+void SoundResource::play(uint32 fileHash) {
+ load(fileHash);
+ play();
+}
+
+void SoundResource::play() {
+ if (_soundIndex >= 0)
+ _vm->_audioResourceMan->playSound(_soundIndex, false);
+}
+
+void SoundResource::stop() {
+ if (_soundIndex >= 0)
+ _vm->_audioResourceMan->stopSound(_soundIndex);
+}
+
+void SoundResource::setVolume(int16 volume) {
+ if (_soundIndex >= 0)
+ _vm->_audioResourceMan->setSoundVolume(_soundIndex, volume);
+}
+
+void SoundResource::setPan(int16 pan) {
+ if (_soundIndex >= 0)
+ _vm->_audioResourceMan->setSoundPan(_soundIndex, pan);
+}
+
MusicResource::MusicResource(NeverhoodEngine *vm)
- : _vm(vm) {
+ : _vm(vm), _musicIndex(-1) {
}
bool MusicResource::isPlaying() {
- return false;
+ return _musicIndex >= 0 &&
+ _vm->_audioResourceMan->isMusicPlaying(_musicIndex);
}
void MusicResource::load(uint32 fileHash) {
- // TODO
+ unload();
+ _musicIndex = _vm->_audioResourceMan->loadMusic(fileHash);
}
void MusicResource::unload() {
- // TODO
+ if (_musicIndex >= 0) {
+ _vm->_audioResourceMan->unloadMusic(_musicIndex);
+ _musicIndex = -1;
+ }
}
void MusicResource::play(int16 fadeVolumeStep) {
- // TODO
+ if (_musicIndex >= 0)
+ _vm->_audioResourceMan->playMusic(_musicIndex, fadeVolumeStep);
}
void MusicResource::stop(int16 fadeVolumeStep) {
- // TODO
+ if (_musicIndex >= 0)
+ _vm->_audioResourceMan->stopMusic(_musicIndex, fadeVolumeStep);
+}
+
+void MusicResource::setVolume(int16 volume) {
+ if (_musicIndex >= 0)
+ _vm->_audioResourceMan->setMusicVolume(_musicIndex, volume);
}
MusicItem::MusicItem()
@@ -80,6 +145,8 @@ SoundItem::~SoundItem() {
delete _soundResource;
}
+// SoundMan
+
SoundMan::SoundMan(NeverhoodEngine *vm)
: _vm(vm),
_soundIndex1(-1), _soundIndex2(-1), _soundIndex3(-1) {
@@ -107,8 +174,8 @@ void SoundMan::deleteMusic(uint32 musicFileHash) {
if (musicItem) {
delete musicItem;
for (uint i = 0; i < _musicItems.size(); ++i)
- if (_musicItems[i]->_musicFileHash == musicFileHash) {
- _musicItems.remove_at(i);
+ if (_musicItems[i] == musicItem) {
+ _musicItems[i] = NULL;
break;
}
}
@@ -149,8 +216,8 @@ void SoundMan::deleteSound(uint32 soundFileHash) {
if (soundItem) {
delete soundItem;
for (uint i = 0; i < _soundItems.size(); ++i)
- if (_soundItems[i]->_soundFileHash == soundFileHash) {
- _soundItems.remove_at(i);
+ if (_soundItems[i] == soundItem) {
+ _soundItems[i] = NULL;
break;
}
}
@@ -213,35 +280,41 @@ void SoundMan::update() {
for (uint i = 0; i < _soundItems.size(); ++i) {
SoundItem *soundItem = _soundItems[i];
- if (soundItem->_playOnceAfterCountdown) {
- if (soundItem->_currCountdown == 0) {
- soundItem->_currCountdown = soundItem->_initialCountdown;
- } else if (--soundItem->_currCountdown == 0) {
- soundItem->_soundResource->play();
+ if (soundItem) {
+ if (soundItem->_playOnceAfterCountdown) {
+ if (soundItem->_currCountdown == 0) {
+ soundItem->_currCountdown = soundItem->_initialCountdown;
+ } else if (--soundItem->_currCountdown == 0) {
+ soundItem->_soundResource->play();
+ }
+ } else if (soundItem->_playOnceAfterRandomCountdown) {
+ if (soundItem->_currCountdown == 0) {
+ if (soundItem->_minCountdown > 0 && soundItem->_maxCountdown > 0 && soundItem->_minCountdown < soundItem->_maxCountdown)
+ soundItem->_currCountdown = _vm->_rnd->getRandomNumberRng(soundItem->_minCountdown, soundItem->_maxCountdown);
+ } else if (--soundItem->_currCountdown == 0) {
+ soundItem->_soundResource->play();
+ }
+ } else if (soundItem->_playLooping && !soundItem->_soundResource->isPlaying()) {
+ soundItem->_soundResource->play(); // TODO Looping parameter?
}
- } else if (soundItem->_playOnceAfterRandomCountdown) {
- if (soundItem->_currCountdown == 0) {
- if (soundItem->_minCountdown > 0 && soundItem->_maxCountdown > 0 && soundItem->_minCountdown < soundItem->_maxCountdown)
- soundItem->_currCountdown = _vm->_rnd->getRandomNumberRng(soundItem->_minCountdown, soundItem->_maxCountdown);
- } else if (--soundItem->_currCountdown == 0) {
- soundItem->_soundResource->play();
- }
- } else if (soundItem->_playLooping && !soundItem->_soundResource->isPlaying()) {
- soundItem->_soundResource->play(); // TODO Looping parameter?
}
}
for (uint i = 0; i < _musicItems.size(); ++i) {
MusicItem *musicItem = _musicItems[i];
- if (musicItem->_countdown) {
- --musicItem->_countdown;
- } else if (musicItem->_play && !musicItem->_musicResource->isPlaying()) {
- musicItem->_musicResource->play(musicItem->_fadeVolumeStep);
- musicItem->_fadeVolumeStep = 0;
- } else if (musicItem->_stop) {
- musicItem->_musicResource->stop(musicItem->_fadeVolumeStep);
- musicItem->_fadeVolumeStep = 0;
- musicItem->_stop = false;
+ if (musicItem) {
+ if (musicItem->_countdown) {
+ --musicItem->_countdown;
+ } else if (musicItem->_play && !musicItem->_musicResource->isPlaying()) {
+ debug("SoundMan: play music %08X (fade %d)", musicItem->_musicFileHash, musicItem->_fadeVolumeStep);
+ musicItem->_musicResource->play(musicItem->_fadeVolumeStep);
+ musicItem->_fadeVolumeStep = 0;
+ } else if (musicItem->_stop) {
+ debug("SoundMan: stop music %08X (fade %d)", musicItem->_musicFileHash, musicItem->_fadeVolumeStep);
+ musicItem->_musicResource->stop(musicItem->_fadeVolumeStep);
+ musicItem->_fadeVolumeStep = 0;
+ musicItem->_stop = false;
+ }
}
}
@@ -253,11 +326,11 @@ void SoundMan::deleteGroup(uint32 nameHash) {
}
void SoundMan::deleteMusicGroup(uint32 nameHash) {
- for (int index = _musicItems.size() - 1; index >= 0; --index) {
+ for (uint index = 0; index < _musicItems.size(); ++index) {
MusicItem *musicItem = _musicItems[index];
- if (musicItem->_nameHash == nameHash) {
+ if (musicItem && musicItem->_nameHash == nameHash) {
delete musicItem;
- _musicItems.remove_at(index);
+ _musicItems[index] = NULL;
}
}
}
@@ -276,11 +349,11 @@ void SoundMan::deleteSoundGroup(uint32 nameHash) {
_soundIndex2 = -1;
}
- for (int index = _soundItems.size() - 1; index >= 0; --index) {
+ for (uint index = 0; index < _soundItems.size(); ++index) {
soundItem = _soundItems[index];
- if (soundItem->_nameHash == nameHash) {
+ if (soundItem && soundItem->_nameHash == nameHash) {
delete soundItem;
- _soundItems.remove_at(index);
+ _soundItems[index] = NULL;
}
}
@@ -359,21 +432,327 @@ void SoundMan::setSoundThreePlayFlag(bool playOnceAfterCountdown) {
MusicItem *SoundMan::getMusicItemByHash(uint32 musicFileHash) {
for (uint i = 0; i < _musicItems.size(); ++i)
- if (_musicItems[i]->_musicFileHash == musicFileHash)
+ if (_musicItems[i] && _musicItems[i]->_musicFileHash == musicFileHash)
return _musicItems[i];
return NULL;
}
SoundItem *SoundMan::getSoundItemByHash(uint32 soundFileHash) {
for (uint i = 0; i < _soundItems.size(); ++i)
- if (_soundItems[i]->_soundFileHash == soundFileHash)
+ if (_soundItems[i] && _soundItems[i]->_soundFileHash == soundFileHash)
return _soundItems[i];
return NULL;
}
+int16 SoundMan::addMusicItem(MusicItem *musicItem) {
+ return 0; // TODO
+}
+
+int16 SoundMan::addSoundItem(SoundItem *soundItem) {
+ for (uint i = 0; i < _soundItems.size(); ++i)
+ if (!_soundItems[i]) {
+ _soundItems[i] = soundItem;
+ return i;
+ }
+ int16 soundIndex = _soundItems.size();
+ _soundItems.push_back(soundItem);
+ return soundIndex;
+}
+
void SoundMan::deleteSoundByIndex(int index) {
delete _soundItems[index];
- _soundItems.remove_at(index);
+ _soundItems[index] = NULL;
+}
+
+// NeverhoodAudioStream
+
+NeverhoodAudioStream::NeverhoodAudioStream(int rate, byte shiftValue, bool isLooping, DisposeAfterUse::Flag disposeStream, Common::SeekableReadStream *stream)
+ : _rate(rate), _shiftValue(shiftValue), _isLooping(isLooping), _isStereo(false), _stream(stream, disposeStream), _endOfData(false), _buffer(0),
+ _isCompressed(_shiftValue != 0xFF), _prevValue(0) {
+ // Setup our buffer for readBuffer
+ _buffer = new byte[kSampleBufferLength * (_isCompressed ? 1 : 2)];
+ assert(_buffer);
+}
+
+NeverhoodAudioStream::~NeverhoodAudioStream() {
+ delete[] _buffer;
+}
+
+int NeverhoodAudioStream::readBuffer(int16 *buffer, const int numSamples) {
+ int samplesLeft = numSamples;
+
+ while (samplesLeft > 0 && !_endOfData) {
+
+ const int maxSamples = MIN<int>(kSampleBufferLength, samplesLeft);
+ const int bytesToRead = maxSamples * (_isCompressed ? 1 : 2);
+ int bytesRead = _stream->read(_buffer, bytesToRead);
+ int samplesRead = bytesRead / (_isCompressed ? 1 : 2);
+
+ samplesLeft -= samplesRead;
+
+ const byte *src = _buffer;
+ if (_isCompressed) {
+ while (samplesRead--) {
+ _prevValue += (int8)(*src++);
+ *buffer++ = _prevValue << _shiftValue;
+ }
+ } else {
+ memcpy(buffer, _buffer, bytesRead);
+ buffer += bytesRead;
+ }
+
+ if (bytesRead < bytesToRead || _stream->pos() >= _stream->size() || _stream->err() || _stream->eos()) {
+ if (_isLooping)
+ _stream->seek(0);
+ else
+ _endOfData = true;
+ }
+
+ }
+
+ return numSamples - samplesLeft;
+}
+
+AudioResourceMan::AudioResourceMan(NeverhoodEngine *vm)
+ : _vm(vm) {
+}
+
+AudioResourceMan::~AudioResourceMan() {
+}
+
+int16 AudioResourceMan::addSound(uint32 fileHash) {
+ AudioResourceManSoundItem *soundItem = new AudioResourceManSoundItem();
+ soundItem->_resourceHandle = _vm->_res->useResource(fileHash);
+ soundItem->_fileHash = fileHash;
+ soundItem->_data = NULL;
+ soundItem->_isLoaded = false;
+ soundItem->_isPlaying = false;
+ soundItem->_volume = 100;
+ soundItem->_panning = 50;
+
+ for (uint i = 0; i < _soundItems.size(); ++i)
+ if (!_soundItems[i]) {
+ _soundItems[i] = soundItem;
+ return i;
+ }
+
+ int16 soundIndex = (int16)_soundItems.size();
+ _soundItems.push_back(soundItem);
+ return soundIndex;
+}
+
+void AudioResourceMan::removeSound(int16 soundIndex) {
+ AudioResourceManSoundItem *soundItem = _soundItems[soundIndex];
+ if (soundItem->_data) {
+ _vm->_res->unloadResource(soundItem->_resourceHandle);
+ soundItem->_data = NULL;
+ }
+ if (soundItem->_resourceHandle != 1) {
+ _vm->_res->unuseResource(soundItem->_resourceHandle);
+ soundItem->_resourceHandle = -1;
+ }
+ if (_vm->_mixer->isSoundHandleActive(soundItem->_soundHandle))
+ _vm->_mixer->stopHandle(soundItem->_soundHandle);
+ delete soundItem;
+ _soundItems[soundIndex] = NULL;
+}
+
+void AudioResourceMan::loadSound(int16 soundIndex) {
+ AudioResourceManSoundItem *soundItem = _soundItems[soundIndex];
+ if (!soundItem->_data) {
+ // TODO Check if it's a sound resource
+ soundItem->_data = _vm->_res->loadResource(soundItem->_resourceHandle);
+ }
+}
+
+void AudioResourceMan::unloadSound(int16 soundIndex) {
+ AudioResourceManSoundItem *soundItem = _soundItems[soundIndex];
+ if (soundItem->_data) {
+ _vm->_res->unloadResource(soundItem->_resourceHandle);
+ soundItem->_data = NULL;
+ }
+}
+
+void AudioResourceMan::setSoundVolume(int16 soundIndex, int16 volume) {
+ AudioResourceManSoundItem *soundItem = _soundItems[soundIndex];
+ soundItem->_volume = MIN<int16>(volume, 100);
+ if (soundItem->_isPlaying && _vm->_mixer->isSoundHandleActive(soundItem->_soundHandle))
+ _vm->_mixer->setChannelVolume(soundItem->_soundHandle, VOLUME(soundItem->_volume));
+}
+
+void AudioResourceMan::setSoundPan(int16 soundIndex, int16 pan) {
+ AudioResourceManSoundItem *soundItem = _soundItems[soundIndex];
+ soundItem->_panning = MIN<int16>(pan, 100);
+ if (soundItem->_isPlaying && _vm->_mixer->isSoundHandleActive(soundItem->_soundHandle))
+ _vm->_mixer->setChannelVolume(soundItem->_soundHandle, PANNING(soundItem->_panning));
+}
+
+void AudioResourceMan::playSound(int16 soundIndex, bool looping) {
+ AudioResourceManSoundItem *soundItem = _soundItems[soundIndex];
+ if (!soundItem->_data)
+ loadSound(soundIndex);
+
+ uint32 soundSize = _vm->_res->getResourceSize(soundItem->_resourceHandle);
+ Common::MemoryReadStream *stream = new Common::MemoryReadStream(soundItem->_data, soundSize, DisposeAfterUse::NO);
+ byte *shiftValue = _vm->_res->getResourceExtData(soundItem->_resourceHandle);
+ NeverhoodAudioStream *audioStream = new NeverhoodAudioStream(22050, *shiftValue, false, DisposeAfterUse::YES, stream);
+
+ _vm->_mixer->playStream(Audio::Mixer::kSFXSoundType, &soundItem->_soundHandle,
+ audioStream, -1, VOLUME(soundItem->_volume), PANNING(soundItem->_panning));
+
+ debug("playing sound %08X", soundItem->_fileHash);
+
+ soundItem->_isPlaying = true;
+
+}
+
+void AudioResourceMan::stopSound(int16 soundIndex) {
+ AudioResourceManSoundItem *soundItem = _soundItems[soundIndex];
+ if (_vm->_mixer->isSoundHandleActive(soundItem->_soundHandle))
+ _vm->_mixer->stopHandle(soundItem->_soundHandle);
+ soundItem->_isPlaying = false;
+}
+
+bool AudioResourceMan::isSoundPlaying(int16 soundIndex) {
+ AudioResourceManSoundItem *soundItem = _soundItems[soundIndex];
+ return soundItem->_isPlaying;
+}
+
+int16 AudioResourceMan::loadMusic(uint32 fileHash) {
+
+ AudioResourceManMusicItem *musicItem;
+
+ for (uint i = 0; i < _musicItems.size(); ++i) {
+ musicItem = _musicItems[i];
+ if (musicItem && musicItem->_fileHash == fileHash && musicItem->_remove) {
+ musicItem->_remove = false;
+ musicItem->_isFadingOut = false;
+ musicItem->_isFadingIn = true;
+ return i;
+ }
+ }
+
+ musicItem = new AudioResourceManMusicItem();
+ musicItem->_fileHash = fileHash;
+ musicItem->_isPlaying = false;
+ musicItem->_remove = false;
+ musicItem->_volume = 100;
+ musicItem->_panning = 50;
+ musicItem->_start = false;
+ musicItem->_isFadingIn = false;
+ musicItem->_isFadingOut = false;
+
+ for (uint i = 0; i < _musicItems.size(); ++i) {
+ if (!_musicItems[i]) {
+ _musicItems[i] = musicItem;
+ return i;
+ }
+ }
+
+ int16 musicIndex = _musicItems.size();
+ _musicItems.push_back(musicItem);
+ return musicIndex;
+
+}
+
+void AudioResourceMan::unloadMusic(int16 musicIndex) {
+ AudioResourceManMusicItem *musicItem = _musicItems[musicIndex];
+ if (musicItem->_isFadingOut) {
+ musicItem->_remove = true;
+ } else {
+ if (_vm->_mixer->isSoundHandleActive(musicItem->_soundHandle))
+ _vm->_mixer->stopHandle(musicItem->_soundHandle);
+ musicItem->_isPlaying = false;
+ _musicItems[musicIndex] = NULL;
+ }
+}
+
+void AudioResourceMan::setMusicVolume(int16 musicIndex, int16 volume) {
+ AudioResourceManMusicItem *musicItem = _musicItems[musicIndex];
+ musicItem->_volume = MIN<int16>(volume, 100);
+ if (musicItem->_isPlaying && _vm->_mixer->isSoundHandleActive(musicItem->_soundHandle))
+ _vm->_mixer->setChannelVolume(musicItem->_soundHandle, VOLUME(musicItem->_volume));
+}
+
+void AudioResourceMan::playMusic(int16 musicIndex, int16 fadeVolumeStep) {
+ AudioResourceManMusicItem *musicItem = _musicItems[musicIndex];
+ if (!musicItem->_isPlaying) {
+ musicItem->_isFadingIn = false;
+ musicItem->_isFadingOut = false;
+ if (fadeVolumeStep != 0) {
+ musicItem->_isFadingIn = true;
+ musicItem->_fadeVolume = 0;
+ musicItem->_fadeVolumeStep = fadeVolumeStep;
+ }
+ musicItem->_start = true;
+ }
+}
+
+void AudioResourceMan::stopMusic(int16 musicIndex, int16 fadeVolumeStep) {
+ AudioResourceManMusicItem *musicItem = _musicItems[musicIndex];
+ if (_vm->_mixer->isSoundHandleActive(musicItem->_soundHandle)) {
+ if (fadeVolumeStep != 0) {
+ if (musicItem->_isFadingIn)
+ musicItem->_isFadingIn = false;
+ else
+ musicItem->_fadeVolume = musicItem->_volume;
+ musicItem->_isFadingOut = true;
+ musicItem->_fadeVolumeStep = fadeVolumeStep;
+ } else {
+ _vm->_mixer->stopHandle(musicItem->_soundHandle);
+ }
+ musicItem->_isPlaying = false;
+ }
+}
+
+bool AudioResourceMan::isMusicPlaying(int16 musicIndex) {
+ AudioResourceManMusicItem *musicItem = _musicItems[musicIndex];
+ return musicItem->_isPlaying;
+}
+
+void AudioResourceMan::updateMusicItem(int16 musicIndex) {
+ AudioResourceManMusicItem *musicItem = _musicItems[musicIndex];
+
+ if (musicItem->_start && !_vm->_mixer->isSoundHandleActive(musicItem->_soundHandle)) {
+ Common::SeekableReadStream *stream = _vm->_res->createStream(musicItem->_fileHash);
+ byte *shiftValue = _vm->_res->getResourceExtDataByHash(musicItem->_fileHash);
+ NeverhoodAudioStream *audioStream = new NeverhoodAudioStream(22050, *shiftValue, true, DisposeAfterUse::YES, stream);
+ _vm->_mixer->playStream(Audio::Mixer::kMusicSoundType, &musicItem->_soundHandle,
+ audioStream, -1, VOLUME(musicItem->_isFadingIn ? musicItem->_fadeVolume : musicItem->_volume),
+ PANNING(musicItem->_panning));
+ musicItem->_start = false;
+ musicItem->_isPlaying = true;
+ }
+
+ if (_vm->_mixer->isSoundHandleActive(musicItem->_soundHandle)) {
+ if (musicItem->_isFadingIn) {
+ musicItem->_fadeVolume += musicItem->_fadeVolumeStep;
+ if (musicItem->_fadeVolume >= musicItem->_volume) {
+ musicItem->_fadeVolume = musicItem->_volume;
+ musicItem->_isFadingIn = false;
+ }
+ _vm->_mixer->setChannelVolume(musicItem->_soundHandle, VOLUME(musicItem->_fadeVolume));
+ }
+ if (musicItem->_isFadingOut) {
+ musicItem->_fadeVolume -= musicItem->_fadeVolumeStep;
+ if (musicItem->_fadeVolume < 0)
+ musicItem->_fadeVolume = 0;
+ _vm->_mixer->setChannelVolume(musicItem->_soundHandle, VOLUME(musicItem->_fadeVolume));
+ if (musicItem->_fadeVolume == 0) {
+ musicItem->_isFadingOut = false;
+ stopMusic(musicIndex, 0);
+ if (musicItem->_remove)
+ unloadMusic(musicIndex);
+ }
+ }
+ }
+
+}
+
+void AudioResourceMan::update() {
+ for (uint i = 0; i < _musicItems.size(); ++i)
+ if (_musicItems[i])
+ updateMusicItem(i);
}
} // End of namespace Neverhood
diff --git a/engines/neverhood/sound.h b/engines/neverhood/sound.h
index 39bf7cd096..b724e898f0 100644
--- a/engines/neverhood/sound.h
+++ b/engines/neverhood/sound.h
@@ -23,6 +23,7 @@
#ifndef NEVERHOOD_SOUND_H
#define NEVERHOOD_SOUND_H
+#include "audio/audiostream.h"
#include "common/array.h"
#include "graphics/surface.h"
#include "neverhood/neverhood.h"
@@ -30,6 +31,29 @@
namespace Neverhood {
+// Convert volume from percent to 0..255
+#define VOLUME(volume) (Audio::Mixer::kMaxChannelVolume / 100 * (volume))
+
+// Convert panning from percent (50% equals center) to -127..0..+127
+#define PANNING(panning) (254 / 100 * (panning) - 127)
+
+class SoundResource {
+public:
+ SoundResource(NeverhoodEngine *vm);
+ ~SoundResource();
+ bool isPlaying();
+ void load(uint32 fileHash);
+ void unload();
+ void play(uint32 fileHash);
+ void play();
+ void stop();
+ void setVolume(int16 volume);
+ void setPan(int16 pan);
+protected:
+ NeverhoodEngine *_vm;
+ int16 _soundIndex;
+};
+
class MusicResource {
public:
MusicResource(NeverhoodEngine *vm);
@@ -38,8 +62,10 @@ public:
void unload();
void play(int16 fadeVolumeStep);
void stop(int16 fadeVolumeStep);
+ void setVolume(int16 volume);
protected:
NeverhoodEngine *_vm;
+ int16 _musicIndex;
};
struct MusicItem {
@@ -72,6 +98,8 @@ struct SoundItem {
~SoundItem();
};
+// TODO Give this a better name
+
class SoundMan {
public:
SoundMan(NeverhoodEngine *vm);
@@ -122,10 +150,102 @@ protected:
MusicItem *getMusicItemByHash(uint32 musicFileHash);
SoundItem *getSoundItemByHash(uint32 soundFileHash);
+ int16 addMusicItem(MusicItem *musicItem);
+ int16 addSoundItem(SoundItem *soundItem);
void deleteSoundByIndex(int index);
};
+class NeverhoodAudioStream : public Audio::AudioStream {
+public:
+ NeverhoodAudioStream(int rate, byte shiftValue, bool isLooping, DisposeAfterUse::Flag disposeStream, Common::SeekableReadStream *stream);
+ ~NeverhoodAudioStream();
+ int readBuffer(int16 *buffer, const int numSamples);
+ bool isStereo() const { return _isStereo; }
+ bool endOfData() const { return _endOfData; }
+ int getRate() const { return _rate; }
+private:
+ const int _rate;
+ const bool _isLooping;
+ const bool _isStereo;
+ const byte _shiftValue;
+ const bool _isCompressed;
+ int16 _prevValue;
+ Common::DisposablePtr<Common::SeekableReadStream> _stream;
+ bool _endOfData;
+ byte *_buffer;
+ enum {
+ kSampleBufferLength = 2048
+ };
+ int fillBuffer(int maxSamples);
+};
+
+// TODO Rename these
+
+struct AudioResourceManSoundItem {
+ uint32 _fileHash;
+ int _resourceHandle;
+ byte *_data;
+ bool _isLoaded;
+ bool _isPlaying;
+ int16 _volume;
+ int16 _panning;
+ Audio::SoundHandle _soundHandle;
+};
+
+struct AudioResourceManMusicItem {
+ uint32 _fileHash;
+ // streamIndex dw
+ // needCreate db
+ bool _isPlaying;
+ bool _remove;
+ int16 _volume;
+ int16 _panning;
+ bool _start;
+ bool _isFadingIn;
+ bool _isFadingOut;
+ int16 _fadeVolume;
+ int16 _fadeVolumeStep;
+ Audio::SoundHandle _soundHandle;
+ // status dw
+ // updateCounter dd
+};
+
+class AudioResourceMan {
+public:
+ AudioResourceMan(NeverhoodEngine *vm);
+ ~AudioResourceMan();
+
+ int16 addSound(uint32 fileHash);
+ void removeSound(int16 soundIndex);
+ void loadSound(int16 soundIndex);
+ void unloadSound(int16 soundIndex);
+ void setSoundVolume(int16 soundIndex, int16 volume);
+ void setSoundPan(int16 soundIndex, int16 pan);
+ void playSound(int16 soundIndex, bool looping);
+ void stopSound(int16 soundIndex);
+ bool isSoundPlaying(int16 soundIndex);
+
+ int16 loadMusic(uint32 fileHash);
+ void unloadMusic(int16 musicIndex);
+ void setMusicVolume(int16 musicIndex, int16 volume);
+ void playMusic(int16 musicIndex, int16 fadeVolumeStep);
+ void stopMusic(int16 musicIndex, int16 fadeVolumeStep);
+ bool isMusicPlaying(int16 musicIndex);
+ void updateMusicItem(int16 musicIndex);
+
+ void update();
+
+protected:
+ NeverhoodEngine *_vm;
+
+ Common::Array<AudioResourceManMusicItem*> _musicItems;
+ Common::Array<AudioResourceManSoundItem*> _soundItems;
+
+ int16 addSoundItem(AudioResourceManSoundItem *soundItem);
+
+};
+
} // End of namespace Neverhood
#endif /* NEVERHOOD_SOUND_H */