aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--saga/actor.cpp121
-rw-r--r--saga/actor.h7
-rw-r--r--saga/ihnm_introproc.cpp2
-rw-r--r--saga/interface.h4
-rw-r--r--saga/itedata.cpp71
-rw-r--r--saga/itedata.h7
-rw-r--r--saga/resnames.h1
-rw-r--r--saga/rscfile.cpp85
-rw-r--r--saga/rscfile.h9
-rw-r--r--saga/scene.cpp15
-rw-r--r--saga/script.h1
-rw-r--r--saga/sfuncs.cpp117
-rw-r--r--saga/sndres.cpp43
-rw-r--r--saga/sndres.h9
-rw-r--r--saga/sprite.cpp3
-rw-r--r--saga/sthread.cpp7
16 files changed, 368 insertions, 134 deletions
diff --git a/saga/actor.cpp b/saga/actor.cpp
index d1da219a80..c44ac5d970 100644
--- a/saga/actor.cpp
+++ b/saga/actor.cpp
@@ -184,6 +184,9 @@ Actor::Actor(SagaEngine *vm) : _vm(vm) {
_debugPointsAlloced = _debugPointsCount = 0;
#endif
+ _protagStates = 0;
+ _protagStatesCount = 0;
+
_pathNodeList = _newPathNodeList = NULL;
_pathList = NULL;
_pathDirectionList = NULL;
@@ -390,8 +393,9 @@ void Actor::loadList(int actorsEntrance, int actorCount, int actorsResourceID, i
_vm->_resource->loadResource(_actorContext, actorsResourceID, actorListData, actorListLength);
+ _actorsCount = actorCount;
+
MemoryReadStream actorS(actorListData, actorListLength);
- _actorsCount = actorListLength / ACTOR_INHM_SIZE;
_actors = (ActorData **)malloc(_actorsCount * sizeof(*_actors));
for (i = 0; i < _actorsCount; i++) {
@@ -442,6 +446,8 @@ void Actor::loadList(int actorsEntrance, int actorCount, int actorsResourceID, i
}
free(actorListData);
+ _actors[actorsEntrance]->flags |= kProtagonist | kExtended;
+
for (i = 0; i < _actorsCount; i++) {
actor = _actors[i];
if (actor->flags & kExtended) {
@@ -451,7 +457,93 @@ void Actor::loadList(int actorsEntrance, int actorCount, int actorsResourceID, i
}
}
}
-//TODO: protagonist stuff
+
+ _centerActor = _protagonist = _actors[actorsEntrance];
+ _protagState = 0;
+
+ if (protagStatesResourceID) {
+ free(_protagStates);
+
+ _protagStates = (ActorFrameSequence *)malloc(sizeof(ActorFrameSequence) * protagStatesCount);
+
+ byte *resourcePointer;
+ size_t resourceLength;
+
+ _vm->_resource->loadResource(_actorContext, protagStatesResourceID,
+ resourcePointer, resourceLength);
+
+
+ MemoryReadStream statesS(resourcePointer, resourceLength);
+
+ for (i = 0; i < protagStatesCount; i++) {
+ for (int j = 0; j < ACTOR_DIRECTIONS_COUNT; j++) {
+ _protagStates[i].directions[j].frameIndex = statesS.readUint16LE();
+ _protagStates[i].directions[j].frameCount = statesS.readUint16LE();
+ }
+ }
+ free(resourcePointer);
+
+ _protagonist->frames = &_protagStates[_protagState];
+ }
+
+ _protagStatesCount = protagStatesCount;
+}
+
+void Actor::freeObjList() {
+ int i;
+ ObjectData *object;
+ for (i = 0; i < _objsCount; i++) {
+ object = _objs[i];
+ delete object;
+ }
+ free(_objs);
+ _objs = NULL;
+ _objsCount = 0;
+}
+
+void Actor::loadObjList(int objectCount, int objectsResourceID) {
+ int i;
+ ObjectData *object;
+ byte* objectListData;
+ size_t objectListLength;
+ freeObjList();
+
+ _vm->_resource->loadResource(_actorContext, objectsResourceID, objectListData, objectListLength);
+
+ _objsCount = objectCount;
+
+ MemoryReadStream objectS(objectListData, objectListLength);
+
+ _objs = (ObjectData **)malloc(_objsCount * sizeof(*_objs));
+ for (i = 0; i < _objsCount; i++) {
+ object = _objs[i] = new ObjectData();
+ object->id = objectIndexToId(kGameObjectObject, i);
+ object->index = i;
+ debug(9, "init object id=%d index=%d", object->id, object->index);
+ objectS.readUint32LE(); //next displayed
+ objectS.readByte(); //type
+ object->flags = objectS.readByte();
+ object->nameIndex = objectS.readUint16LE();
+ object->sceneNumber = objectS.readUint32LE();
+ object->location.fromStream(objectS);
+ object->screenPosition.x = objectS.readUint16LE();
+ object->screenPosition.y = objectS.readUint16LE();
+ object->screenScale = objectS.readUint16LE();
+ object->screenDepth = objectS.readUint16LE();
+ objectS.readUint32LE(); // object->frameListResourceId
+ object->spriteListResourceId = objectS.readUint32LE();
+ object->scriptEntrypointNumber = objectS.readUint32LE();
+ objectS.readByte();
+ objectS.readByte();
+ objectS.readByte();
+ objectS.readByte();
+ objectS.readUint16LE(); //LEFT
+ objectS.readUint16LE(); //RIGHT
+ objectS.readUint16LE(); //TOP
+ objectS.readUint16LE(); //BOTTOM
+ object->interactBits = objectS.readUint16LE();
+ }
+ free(objectListData);
}
void Actor::takeExit(uint16 actorId, const HitZone *hitZone) {
@@ -624,6 +716,9 @@ bool Actor::validFollowerLocation(const Location &location) {
void Actor::setProtagState(int state) {
_protagState = state;
+
+ if (_vm->getGameType() == GType_IHNM)
+ _protagonist->frames = &_protagStates[state];
}
void Actor::updateActorsScene(int actorsEntrance) {
@@ -635,11 +730,6 @@ void Actor::updateActorsScene(int actorsEntrance) {
Point delta;
const SceneEntry *sceneEntry;
- if (_vm->getGameType() == GType_IHNM) {
- warning("Actors aren't implemented for IHNM yet");
- return;
- }
-
if (_vm->_scene->currentSceneNumber() == 0) {
error("Actor::updateActorsScene _vm->_scene->currentSceneNumber() == 0");
}
@@ -768,7 +858,7 @@ ActorFrameRange *Actor::getActorFrameRange(uint16 actorId, int frameType) {
error("Actor::getActorFrameRange Wrong actorId 0x%X", actorId);
if (frameType >= actor->framesCount)
- error("Actor::getActorFrameRange Wrong frameType 0x%X actorId 0x%X", frameType, actorId);
+ error("Actor::getActorFrameRange Wrong frameType 0x%X (%d) actorId 0x%X", frameType, actor->framesCount, actorId);
if ((actor->facingDirection < kDirUp) || (actor->facingDirection > kDirUpLeft))
error("Actor::getActorFrameRange Wrong direction 0x%X actorId 0x%X", actor->facingDirection, actorId);
@@ -933,6 +1023,11 @@ void Actor::handleActions(int msec, bool setup) {
/* if (actor->index == 2)
debug(9, "Action: %d Flags: %x", actor->currentAction, actor->flags);*/
+ if (_vm->getGameType() == GType_IHNM) {
+ if (actor->spriteList.spriteCount == 0)
+ continue;
+ }
+
switch (actor->currentAction) {
case kActionWait:
if (!setup && (actor->flags & kFollower)) {
@@ -1868,11 +1963,6 @@ void Actor::actorSpeech(uint16 actorId, const char **strings, int stringsCount,
int i;
int16 dist;
- if (_vm->getGameType() == GType_IHNM) {
- warning("Actors aren't implemented for IHNM yet");
- return;
- }
-
actor = getActor(actorId);
calcScreenPosition(actor);
for (i = 0; i < stringsCount; i++) {
@@ -1926,11 +2016,6 @@ void Actor::nonActorSpeech(const Common::Rect &box, const char **strings, int st
void Actor::simulSpeech(const char *string, uint16 *actorIds, int actorIdsCount, int speechFlags, int sampleResourceId) {
int i;
- if (_vm->getGameType() == GType_IHNM) {
- warning("Actors aren't implemented for IHNM yet");
- return;
- }
-
for (i = 0; i < actorIdsCount; i++) {
ActorData *actor;
diff --git a/saga/actor.h b/saga/actor.h
index 3ff06709fd..b8c325bf00 100644
--- a/saga/actor.h
+++ b/saga/actor.h
@@ -342,6 +342,7 @@ public:
Location partialTarget;
int32 walkFrameSequence;
+public:
void saveState(Common::OutSaveFile *out) {
int i = 0;
CommonObjectData::saveState(out);
@@ -582,6 +583,8 @@ public:
void freeList();
void loadList(int actorsEntrance, int actorCount, int actorsResourceID,
int protagStatesCount, int protagStatesResourceID);
+ void freeObjList();
+ void loadObjList(int objectCount, int objectsResourceID);
private:
bool loadActorResources(ActorData *actor);
@@ -643,12 +646,16 @@ public:
ActorData *_centerActor;
ActorData *_protagonist;
int _handleActionDiv;
+
protected:
SpeechData _activeSpeech;
int _protagState;
bool _dragonHunt;
private:
+ ActorFrameSequence *_protagStates;
+ int _protagStatesCount;
+
//path stuff
struct PathNode {
Point point;
diff --git a/saga/ihnm_introproc.cpp b/saga/ihnm_introproc.cpp
index 7d162e09a1..89837d9bf2 100644
--- a/saga/ihnm_introproc.cpp
+++ b/saga/ihnm_introproc.cpp
@@ -99,7 +99,7 @@ int Scene::IHNMStartProc() {
}
firstScene.loadFlag = kLoadBySceneNumber;
- firstScene.sceneDescriptor = _vm->getStartSceneNumber();
+ firstScene.sceneDescriptor = -1;
firstScene.sceneDescription = NULL;
firstScene.sceneSkipTarget = true;
firstScene.sceneProc = NULL;
diff --git a/saga/interface.h b/saga/interface.h
index 96b3057247..b8f1945135 100644
--- a/saga/interface.h
+++ b/saga/interface.h
@@ -375,6 +375,9 @@ private:
}
}
+public:
+ SpriteList _defPortraits;
+
private:
SagaEngine *_vm;
@@ -385,7 +388,6 @@ private:
InterfacePanel _conversePanel;
PanelButton *_converseUpButton;
PanelButton *_converseDownButton;
- SpriteList _defPortraits;
SpriteList _scenePortraits;
PanelButton *_verbTypeToPanelButton[kVerbTypesMax];
InterfacePanel _optionPanel;
diff --git a/saga/itedata.cpp b/saga/itedata.cpp
index 73515483dc..95dce36a6d 100644
--- a/saga/itedata.cpp
+++ b/saga/itedata.cpp
@@ -24,6 +24,8 @@
// Actor and Object data tables
#include "saga/saga.h"
#include "saga/itedata.h"
+#include "saga/resnames.h"
+#include "saga/sndres.h"
namespace Saga {
@@ -264,4 +266,73 @@ ObjectTableData ITE_ObjectTable[ITE_OBJECTCOUNT] = {
{ 54, 281, 620, 352, 0, 80, 46, 0 } // Orb of Storms in Dam Lab
};
+FxTable ITE_SfxTable[ITE_SFXCOUNT] = {
+ { FX_DOOR_OPEN, 127 },
+ { FX_DOOR_CLOSE, 127 },
+ { FX_RUSH_WATER, 63 }, // Floppy volume: 127
+ { FX_RUSH_WATER, 26 }, // Floppy volume: 40
+ { FX_CRICKET, 64 },
+ { FX_PORTICULLIS, 84 }, // Floppy volume: 127
+ { FX_CLOCK_1, 64 },
+ { FX_CLOCK_2, 64 },
+ { FX_DAM_MACHINE, 64 },
+ { FX_DAM_MACHINE, 40 },
+ { FX_HUM1, 64 },
+ { FX_HUM2, 64 },
+ { FX_HUM3, 64 },
+ { FX_HUM4, 64 },
+ { FX_WATER_LOOP_S, 32 }, // Floppy volume: 64
+ { FX_SURF, 42 }, // Floppy volume: 127
+ { FX_SURF, 32 }, // Floppy volume: 64
+ { FX_FIRELOOP, 64 }, // Floppy volume: 96
+ { FX_SCRAPING, 84 }, // Floppy volume: 127
+ { FX_BEE_SWARM, 64 }, // Floppy volume: 96
+ { FX_BEE_SWARM, 26 }, // Floppy volume: 40
+ { FX_SQUEAKBOARD, 64 },
+ { FX_KNOCK, 127 },
+ { FX_COINS, 32 }, // Floppy volume: 48
+ { FX_STORM, 84 }, // Floppy volume: 127
+ { FX_DOOR_CLOSE_2, 84 }, // Floppy volume: 127
+ { FX_ARCWELD, 84 }, // Floppy volume: 127
+ { FX_RETRACT_ORB, 127 },
+ { FX_DRAGON, 127 },
+ { FX_SNORES, 127 },
+ { FX_SPLASH, 127 },
+ { FX_LOBBY_DOOR, 127 },
+ { FX_CHIRP_LOOP, 26 }, // Floppy volume: 40
+ { FX_DOOR_CREAK, 96 },
+ { FX_SPOON_DIG, 64 },
+ { FX_CROW, 96 },
+ { FX_COLDWIND, 42 }, // Floppy volume: 64
+ { FX_TOOL_SND_1, 96 },
+ { FX_TOOL_SND_2, 127 },
+ { FX_TOOL_SND_3, 64 },
+ { FX_DOOR_METAL, 96 },
+ { FX_WATER_LOOP_S, 32 },
+ { FX_WATER_LOOP_L, 32 }, // Floppy volume: 64
+ { FX_DOOR_OPEN_2, 127 },
+ { FX_JAIL_DOOR, 64 },
+ { FX_KILN_FIRE, 53 }, // Floppy volume: 80
+
+ // Only in the CD version
+ { FX_CROWD_01, 64 },
+ { FX_CROWD_02, 64 },
+ { FX_CROWD_03, 64 },
+ { FX_CROWD_04, 64 },
+ { FX_CROWD_05, 64 },
+ { FX_CROWD_06, 64 },
+ { FX_CROWD_07, 64 },
+ { FX_CROWD_08, 64 },
+ { FX_CROWD_09, 64 },
+ { FX_CROWD_10, 64 },
+ { FX_CROWD_11, 64 },
+ { FX_CROWD_12, 64 },
+ { FX_CROWD_13, 64 },
+ { FX_CROWD_14, 64 },
+ { FX_CROWD_15, 64 },
+ { FX_CROWD_16, 64 },
+ { FX_CROWD_17, 64 }
+};
+
+
} // End of namespace Saga
diff --git a/saga/itedata.h b/saga/itedata.h
index 299cc365db..fb1f929241 100644
--- a/saga/itedata.h
+++ b/saga/itedata.h
@@ -76,9 +76,16 @@ struct ObjectTableData {
uint16 interactBits;
};
+struct FxTable {
+ int res;
+ int vol;
+};
+
#define ITE_OBJECTCOUNT 39
+#define ITE_SFXCOUNT 63
extern ObjectTableData ITE_ObjectTable[ITE_OBJECTCOUNT];
+extern FxTable ITE_SfxTable[ITE_SFXCOUNT];
} // End of namespace Saga
diff --git a/saga/resnames.h b/saga/resnames.h
index 500fb0a82d..ca1ae7af72 100644
--- a/saga/resnames.h
+++ b/saga/resnames.h
@@ -36,6 +36,7 @@ namespace Saga {
#define RID_IHNM_SCENE_LUT 1272
#define RID_IHNM_SCRIPT_LUT 29
+#define RID_IHNM_SFX_LUT 265
#define RID_IHNMDEMO_SCENE_LUT 286
#define RID_IHNMDEMO_SCRIPT_LUT 18
diff --git a/saga/rscfile.cpp b/saga/rscfile.cpp
index 5625f51b03..dadcd15b4f 100644
--- a/saga/rscfile.cpp
+++ b/saga/rscfile.cpp
@@ -25,7 +25,9 @@
#include "saga/saga.h"
#include "saga/actor.h"
+#include "saga/interface.h"
#include "saga/rscfile.h"
+#include "saga/sndres.h"
#include "saga/stream.h"
namespace Saga {
@@ -432,7 +434,7 @@ void Resource::loadGlobalResources(int chapter, int actorsEntrance) {
//if (module.voiceLUT)
// free module.voiceLUT;
- // TODO: close chapeter context, or rather reassign it in our case
+ // TODO: close chapter context, or rather reassign it in our case
ResourceContext *resourceContext;
@@ -448,16 +450,17 @@ void Resource::loadGlobalResources(int chapter, int actorsEntrance) {
resourcePointer, resourceLength);
if (resourceLength == 0) {
- error("Resource::loadGlobalResources wrong resource");
+ error("Resource::loadGlobalResources wrong metaResource");
}
+
MemoryReadStream metaS(resourcePointer, resourceLength);
_metaResource.sceneIndex = metaS.readSint16LE();
- _metaResource.obectCount = metaS.readSint16LE();
+ _metaResource.objectCount = metaS.readSint16LE();
_metaResource.field_4 = metaS.readSint32LE();
_metaResource.field_8 = metaS.readSint32LE();
_metaResource.mainSpritesID = metaS.readSint32LE();
- _metaResource.objectResourceID = metaS.readSint32LE();
+ _metaResource.objectsResourceID = metaS.readSint32LE();
_metaResource.actorCount = metaS.readSint16LE();
_metaResource.field_16 = metaS.readSint32LE();
_metaResource.actorsResourceID = metaS.readSint32LE();
@@ -477,6 +480,80 @@ void Resource::loadGlobalResources(int chapter, int actorsEntrance) {
_vm->_actor->_protagonist->sceneNumber = _metaResource.sceneIndex;
+ // TODO: field_16
+
+ if (chapter >= _vm->_sndRes->_fxTableIDsLen) {
+ error("Chapter ID exceeds fxTableIDs length");
+ }
+
+ debug(0, "Going to read %d of %d", chapter, _vm->_sndRes->_fxTableIDs[chapter]);
+ _vm->_resource->loadResource(resourceContext, _vm->_sndRes->_fxTableIDs[chapter],
+ resourcePointer, resourceLength);
+
+ if (resourceLength == 0) {
+ error("Resource::loadGlobalResources Can't load sound effects for current track");
+ }
+
+ free(_vm->_sndRes->_fxTable);
+
+ _vm->_sndRes->_fxTableLen = resourceLength / 4;
+ _vm->_sndRes->_fxTable = (FxTable *)malloc(sizeof(FxTable) * _vm->_sndRes->_fxTableLen);
+
+ MemoryReadStream fxS(resourcePointer, resourceLength);
+
+ for (int i = 0; i < _vm->_sndRes->_fxTableLen; i++) {
+ _vm->_sndRes->_fxTable[i].res = fxS.readSint16LE();
+ _vm->_sndRes->_fxTable[i].vol = fxS.readSint16LE();
+ }
+
+ _vm->_interface->_defPortraits.freeMem();
+ _vm->_sprite->loadList(_metaResource.protagFaceSpritesID, _vm->_interface->_defPortraits);
+
+ // TODO: field_4
+
+ // TODO: field_8
+
+ _vm->_sprite->_mainSprites.freeMem();
+ _vm->_sprite->loadList(_metaResource.mainSpritesID, _vm->_sprite->_mainSprites);
+
+ _vm->_actor->loadObjList(_metaResource.objectCount, _metaResource.objectsResourceID);
+
+ // TODO: cutawayList
+
+ // TODO: songTable
+
+ switch (chapter) {
+ case 1:
+ // chapterRes = "voices1.res"
+ // hackVoiceTableListID = 23
+ break;
+ case 2:
+ // chapterRes = "voices2.res"
+ // hackVoiceTableListID = 24
+ break;
+ case 3:
+ // chapterRes = "voices3.res"
+ // hackVoiceTableListID = 25
+ break;
+ case 4:
+ // chapterRes = "voices4.res"
+ // hackVoiceTableListID = 26
+ break;
+ case 5:
+ // chapterRes = "voices5.res"
+ // hackVoiceTableListID = 27
+ break;
+ case 6:
+ // chapterRes = "voices6.res"
+ // hackVoiceTableListID = 28
+ break;
+ case 7:
+ break;
+ case 8:
+ // chapterRes = "voicess.res"
+ // hackVoiceTableListID = 22
+ break;
+ }
}
diff --git a/saga/rscfile.h b/saga/rscfile.h
index 217e4b33d4..d096184ba6 100644
--- a/saga/rscfile.h
+++ b/saga/rscfile.h
@@ -91,11 +91,11 @@ struct ResourceContext {
struct MetaResource {
int16 sceneIndex;
- int16 obectCount;
+ int16 objectCount;
int32 field_4;
int32 field_8;
int32 mainSpritesID;
- int32 objectResourceID;
+ int32 objectsResourceID;
int16 actorCount;
int32 field_16;
int32 actorsResourceID;
@@ -148,7 +148,8 @@ public:
ResourceData *getResourceData(ResourceContext *context, uint32 resourceId) const {
if (!validResourceId(context, resourceId)) {
- error("Resource::getResourceData() wrong resourceId %d", resourceId);
+ warning("Resource::getResourceData() wrong resourceId %d", resourceId);
+ assert(0);
}
return &context->table[resourceId];
}
@@ -162,6 +163,8 @@ private:
bool loadMacContext(ResourceContext *context);
bool loadSagaContext(ResourceContext *context, uint32 contextOffset, uint32 contextSize);
+
+public:
MetaResource _metaResource;
};
diff --git a/saga/scene.cpp b/saga/scene.cpp
index 23570bb5f7..a131eff7e7 100644
--- a/saga/scene.cpp
+++ b/saga/scene.cpp
@@ -418,7 +418,10 @@ static struct SceneSubstitutes {
};
void Scene::changeScene(int16 sceneNumber, int actorsEntrance, SceneTransitionType transitionType, int chapter) {
- // This is used for latter demos where all places on world map except
+
+ debug(5, "Scene::changeScene(%d, %d, %d, %d)", sceneNumber, actorsEntrance, transitionType, chapter);
+
+ // This is used for latter ITE demos where all places on world map except
// Tent Faire are substituted with LBM picture and short description
if (_vm->getFeatures() & GF_SCENE_SUBSTITUTES) {
for (int i = 0; i < ARRAYSIZE(sceneSubstitutes); i++) {
@@ -627,13 +630,19 @@ void Scene::loadScene(LoadSceneParams *loadSceneParams) {
return;
}
}
-//
+
if (_sceneLoaded) {
error("Scene::loadScene(): Error, a scene is already loaded");
}
_loadDescription = true;
+ if (_vm->getGameType() == GType_IHNM) {
+ if (loadSceneParams->loadFlag == kLoadBySceneNumber) // When will we get rid of it?
+ if (loadSceneParams->sceneDescriptor <= 0)
+ loadSceneParams->sceneDescriptor = _vm->_resource->_metaResource.sceneIndex;
+ }
+
switch (loadSceneParams->loadFlag) {
case kLoadByResourceId:
_sceneNumber = 0; // original assign zero for loaded by resource id
@@ -655,7 +664,7 @@ void Scene::loadScene(LoadSceneParams *loadSceneParams) {
break;
}
- debug(3, "Loading scene number %u:", _sceneNumber);
+ debug(3, "Loading scene number %d:", _sceneNumber);
// Load scene descriptor and resource list resources
if (_loadDescription) {
diff --git a/saga/script.h b/saga/script.h
index a0c00521d1..2ff86c7194 100644
--- a/saga/script.h
+++ b/saga/script.h
@@ -549,6 +549,7 @@ private:
void sfDebugShowData(SCRIPTFUNC_PARAMS);
void SF_stub(SCRIPTFUNC_PARAMS);
void sfNull(SCRIPTFUNC_PARAMS);
+ void sfWaitFramesEsc(SCRIPTFUNC_PARAMS);
void sfPsychicProfile(SCRIPTFUNC_PARAMS);
void sfPsychicProfileOff(SCRIPTFUNC_PARAMS);
};
diff --git a/saga/sfuncs.cpp b/saga/sfuncs.cpp
index a8d9eee34c..2bbc00d20f 100644
--- a/saga/sfuncs.cpp
+++ b/saga/sfuncs.cpp
@@ -237,7 +237,7 @@ static const ScriptFunctionDescription IHNMscriptFunctionsList[IHNM_SCRIPT_FUNCT
OPCODE(SF_stub),
OPCODE(SF_stub),
OPCODE(sfDebugShowData),
- OPCODE(SF_stub),
+ OPCODE(sfWaitFramesEsc),
OPCODE(SF_stub),
OPCODE(SF_stub)
};
@@ -1098,11 +1098,6 @@ void Script::sfPlaceActor(SCRIPTFUNC_PARAMS) {
debug(1, "sfPlaceActor(id = %d, x=%d, y=%d, dir=%d, frameType=%d, frameOffset=%d)", actorId, actorLocation.x,
actorLocation.y, actorDirection, frameType, frameOffset);
- if (_vm->getGameType() == GType_IHNM) {
- warning("Actors aren't implemented for IHNM yet");
- return;
- }
-
actor = _vm->_actor->getActor(actorId);
actor->location.x = actorLocation.x;
actor->location.y = actorLocation.y;
@@ -1728,95 +1723,16 @@ void Script::sfEnableEscape(SCRIPTFUNC_PARAMS) {
}
}
-static struct {
- int res;
- int vol;
-} sfxTable[] = {
- { FX_DOOR_OPEN, 127 },
- { FX_DOOR_CLOSE, 127 },
- { FX_RUSH_WATER, 63 }, // Floppy volume: 127
- { FX_RUSH_WATER, 26 }, // Floppy volume: 40
- { FX_CRICKET, 64 },
- { FX_PORTICULLIS, 84 }, // Floppy volume: 127
- { FX_CLOCK_1, 64 },
- { FX_CLOCK_2, 64 },
- { FX_DAM_MACHINE, 64 },
- { FX_DAM_MACHINE, 40 },
- { FX_HUM1, 64 },
- { FX_HUM2, 64 },
- { FX_HUM3, 64 },
- { FX_HUM4, 64 },
- { FX_WATER_LOOP_S, 32 }, // Floppy volume: 64
- { FX_SURF, 42 }, // Floppy volume: 127
- { FX_SURF, 32 }, // Floppy volume: 64
- { FX_FIRELOOP, 64 }, // Floppy volume: 96
- { FX_SCRAPING, 84 }, // Floppy volume: 127
- { FX_BEE_SWARM, 64 }, // Floppy volume: 96
- { FX_BEE_SWARM, 26 }, // Floppy volume: 40
- { FX_SQUEAKBOARD, 64 },
- { FX_KNOCK, 127 },
- { FX_COINS, 32 }, // Floppy volume: 48
- { FX_STORM, 84 }, // Floppy volume: 127
- { FX_DOOR_CLOSE_2, 84 }, // Floppy volume: 127
- { FX_ARCWELD, 84 }, // Floppy volume: 127
- { FX_RETRACT_ORB, 127 },
- { FX_DRAGON, 127 },
- { FX_SNORES, 127 },
- { FX_SPLASH, 127 },
- { FX_LOBBY_DOOR, 127 },
- { FX_CHIRP_LOOP, 26 }, // Floppy volume: 40
- { FX_DOOR_CREAK, 96 },
- { FX_SPOON_DIG, 64 },
- { FX_CROW, 96 },
- { FX_COLDWIND, 42 }, // Floppy volume: 64
- { FX_TOOL_SND_1, 96 },
- { FX_TOOL_SND_2, 127 },
- { FX_TOOL_SND_3, 64 },
- { FX_DOOR_METAL, 96 },
- { FX_WATER_LOOP_S, 32 },
- { FX_WATER_LOOP_L, 32 }, // Floppy volume: 64
- { FX_DOOR_OPEN_2, 127 },
- { FX_JAIL_DOOR, 64 },
- { FX_KILN_FIRE, 53 }, // Floppy volume: 80
-
- // Only in the CD version
- { FX_CROWD_01, 64 },
- { FX_CROWD_02, 64 },
- { FX_CROWD_03, 64 },
- { FX_CROWD_04, 64 },
- { FX_CROWD_05, 64 },
- { FX_CROWD_06, 64 },
- { FX_CROWD_07, 64 },
- { FX_CROWD_08, 64 },
- { FX_CROWD_09, 64 },
- { FX_CROWD_10, 64 },
- { FX_CROWD_11, 64 },
- { FX_CROWD_12, 64 },
- { FX_CROWD_13, 64 },
- { FX_CROWD_14, 64 },
- { FX_CROWD_15, 64 },
- { FX_CROWD_16, 64 },
- { FX_CROWD_17, 64 }
-};
-
// Script function #70 (0x46)
void Script::sfPlaySound(SCRIPTFUNC_PARAMS) {
int16 param = thread->pop();
int res;
- if (_vm->getGameType() == GType_IHNM) {
- int16 param2 = thread->pop();
-
- // Here sfxTable comes from Resource #265
- debug(0, "STUB: sfPlaySound(%d, %d)", param, param2);
- return;
- }
-
- if (param >= 0 && param < ARRAYSIZE(sfxTable)) {
- res = sfxTable[param].res;
+ if (param >= 0 && param < _vm->_sndRes->_fxTableLen) {
+ res = _vm->_sndRes->_fxTable[param].res;
if (_vm->getFeatures() & GF_CD_FX)
res -= 14;
- _vm->_sndRes->playSound(res, sfxTable[param].vol, false);
+ _vm->_sndRes->playSound(res, _vm->_sndRes->_fxTable[param].vol, false);
} else {
_vm->_sound->stopSound();
}
@@ -1827,20 +1743,12 @@ void Script::sfPlayLoopedSound(SCRIPTFUNC_PARAMS) {
int16 param = thread->pop();
int res;
- if (_vm->getGameType() == GType_IHNM) {
- int16 param2 = thread->pop();
-
- // Here sfxTable comes from Resource #265
- debug(0, "STUB: sfPlayLoopedSound(%d, %d)", param, param2);
- return;
- }
-
- if (param >= 0 && param < ARRAYSIZE(sfxTable)) {
- res = sfxTable[param].res;
+ if (param >= 0 && param < _vm->_sndRes->_fxTableLen) {
+ res = _vm->_sndRes->_fxTable[param].res;
if (_vm->getFeatures() & GF_CD_FX)
res -= 14;
- _vm->_sndRes->playSound(res, sfxTable[param].vol, true);
+ _vm->_sndRes->playSound(res, _vm->_sndRes->_fxTable[param].vol, true);
} else {
_vm->_sound->stopSound();
}
@@ -1977,10 +1885,11 @@ void Script::sfDemoIsInteractive(SCRIPTFUNC_PARAMS) {
}
void Script::sfVsetTrack(SCRIPTFUNC_PARAMS) {
- for (int i = 0; i < nArgs; i++)
- thread->pop();
+ int16 chapter = thread->pop();
+ int16 sceneNumber = thread->pop();
+ int16 actorsEntrance = thread->pop();
- debug(0, "STUB: sfVsetTrack(), %d args", nArgs);
+ _vm->_scene->changeScene(sceneNumber, actorsEntrance, kTransitionFade, chapter);
}
void Script::sfDebugShowData(SCRIPTFUNC_PARAMS) {
@@ -1992,6 +1901,10 @@ void Script::sfDebugShowData(SCRIPTFUNC_PARAMS) {
_vm->_interface->setStatusText(buf);
}
+void Script::sfWaitFramesEsc(SCRIPTFUNC_PARAMS) {
+ thread->_returnValue = 0;
+}
+
void Script::sfNull(SCRIPTFUNC_PARAMS) {
for (int i = 0; i < nArgs; i++)
thread->pop();
diff --git a/saga/sndres.cpp b/saga/sndres.cpp
index f93c595d90..a4e21551b3 100644
--- a/saga/sndres.cpp
+++ b/saga/sndres.cpp
@@ -25,6 +25,8 @@
#include "saga/saga.h"
+#include "saga/itedata.h"
+#include "saga/resnames.h"
#include "saga/rscfile.h"
#include "saga/sndres.h"
#include "saga/sound.h"
@@ -49,6 +51,47 @@ SndRes::SndRes(SagaEngine *vm) : _vm(vm) {
_voiceSerial = -1;
setVoiceBank(0);
+
+ if (_vm->getGameType() == GType_ITE) {
+ _fxTable = ITE_SfxTable;
+ _fxTableLen = ITE_SFXCOUNT;
+ } else {
+ ResourceContext *resourceContext;
+
+ resourceContext = _vm->_resource->getContext(GAME_RESOURCEFILE);
+ if (resourceContext == NULL) {
+ error("Resource::loadGlobalResources() resource context not found");
+ }
+
+ byte *resourcePointer;
+ size_t resourceLength;
+
+ _vm->_resource->loadResource(resourceContext, RID_IHNM_SFX_LUT,
+ resourcePointer, resourceLength);
+
+ if (resourceLength == 0) {
+ error("Sndres::SndRes can't read SfxIDs table");
+ }
+
+ _fxTableIDsLen = resourceLength / 2;
+ _fxTableIDs = (int16 *)malloc(_fxTableIDsLen * sizeof(int16));
+
+ MemoryReadStream metaS(resourcePointer, resourceLength);
+ for (int i = 0; i < _fxTableIDsLen; i++)
+ _fxTableIDs[i] = metaS.readSint16LE();
+
+ free(resourcePointer);
+
+ _fxTable = 0;
+ _fxTableLen = 0;
+ }
+}
+
+SndRes::~SndRes() {
+ if (_vm->getGameType() == GType_IHNM) {
+ free(_fxTable);
+ free(_fxTableIDs);
+ }
}
void SndRes::setVoiceBank(int serial)
diff --git a/saga/sndres.h b/saga/sndres.h
index 0a7c3c129c..b4b985979d 100644
--- a/saga/sndres.h
+++ b/saga/sndres.h
@@ -26,6 +26,7 @@
#ifndef SAGA_SNDRES_H_
#define SAGA_SNDRES_H_
+#include "saga/itedata.h"
#include "saga/sound.h"
namespace Saga {
@@ -34,12 +35,20 @@ class SndRes {
public:
SndRes(SagaEngine *vm);
+ ~SndRes();
int loadSound(uint32 resourceId);
void playSound(uint32 resourceId, int volume, bool loop);
void playVoice(uint32 resourceId);
int getVoiceLength(uint32 resourceId);
void setVoiceBank(int serial);
+
+ FxTable *_fxTable;
+ int _fxTableLen;
+
+ int16 *_fxTableIDs;
+ int _fxTableIDsLen;
+
private:
bool load(ResourceContext *context, uint32 resourceId, SoundBuffer &buffer, bool onlyHeader);
bool loadVocSound(byte *soundResource, size_t soundResourceLength, SoundBuffer &buffer);
diff --git a/saga/sprite.cpp b/saga/sprite.cpp
index 6a4b94c441..fb74d85967 100644
--- a/saga/sprite.cpp
+++ b/saga/sprite.cpp
@@ -51,7 +51,8 @@ Sprite::Sprite(SagaEngine *vm) : _vm(vm) {
memoryError("Sprite::Sprite");
}
- loadList(_vm->getResourceDescription()->mainSpritesResourceId, _mainSprites);
+ if (_vm->getGameType() == GType_ITE)
+ loadList(_vm->getResourceDescription()->mainSpritesResourceId, _mainSprites);
}
Sprite::~Sprite(void) {
diff --git a/saga/sthread.cpp b/saga/sthread.cpp
index a52578b554..5816c6c49f 100644
--- a/saga/sthread.cpp
+++ b/saga/sthread.cpp
@@ -338,7 +338,7 @@ bool Script::runThread(ScriptThread *thread, uint instructionLimit) {
error("Script::runThread() Invalid script function number (%d)", functionNumber);
}
- debug(8, "Calling 0x%X %s argCount=%i", functionNumber, _scriptFunctionsList[functionNumber].scriptFunctionName, argumentsCount);
+ debug(8, "Calling #%d %s argCount=%i", functionNumber, _scriptFunctionsList[functionNumber].scriptFunctionName, argumentsCount);
scriptFunction = _scriptFunctionsList[functionNumber].scriptFunction;
checkStackTopIndex = thread->_stackTopIndex + argumentsCount;
disContinue = false;
@@ -611,6 +611,11 @@ bool Script::runThread(ScriptThread *thread, uint instructionLimit) {
int16 first;
const char *strings[ACTOR_SPEECH_STRING_MAX];
+ if (_vm->getGameType() == GType_IHNM) {
+ warning("STUB: opSpeak");
+ break;
+ }
+
if (_vm->_actor->isSpeaking()) {
thread->wait(kWaitTypeSpeech);
return false;