finally Resource manager rewritten:
-adds patch file support -global _vm removed cleanups svn-id: r18560
This commit is contained in:
parent
546a9d852b
commit
50c2d8954d
40 changed files with 1024 additions and 1516 deletions
|
@ -25,7 +25,6 @@
|
||||||
#include "saga/gfx.h"
|
#include "saga/gfx.h"
|
||||||
|
|
||||||
#include "saga/console.h"
|
#include "saga/console.h"
|
||||||
#include "saga/rscfile_mod.h"
|
|
||||||
#include "saga/script.h"
|
#include "saga/script.h"
|
||||||
#include "saga/sndres.h"
|
#include "saga/sndres.h"
|
||||||
#include "saga/sprite.h"
|
#include "saga/sprite.h"
|
||||||
|
@ -40,6 +39,9 @@
|
||||||
#include "saga/interface.h"
|
#include "saga/interface.h"
|
||||||
#include "saga/events.h"
|
#include "saga/events.h"
|
||||||
#include "saga/objectmap.h"
|
#include "saga/objectmap.h"
|
||||||
|
#include "saga/rscfile.h"
|
||||||
|
#include "saga/resnames.h"
|
||||||
|
|
||||||
#include "common/config-manager.h"
|
#include "common/config-manager.h"
|
||||||
|
|
||||||
namespace Saga {
|
namespace Saga {
|
||||||
|
@ -164,7 +166,6 @@ static const DragonMove dragonMoveTable[12] = {
|
||||||
|
|
||||||
Actor::Actor(SagaEngine *vm) : _vm(vm) {
|
Actor::Actor(SagaEngine *vm) : _vm(vm) {
|
||||||
int i;
|
int i;
|
||||||
int result;
|
|
||||||
byte *stringsPointer;
|
byte *stringsPointer;
|
||||||
size_t stringsLength;
|
size_t stringsLength;
|
||||||
ActorData *actor;
|
ActorData *actor;
|
||||||
|
@ -207,18 +208,15 @@ Actor::Actor(SagaEngine *vm) : _vm(vm) {
|
||||||
|
|
||||||
if (_vm->getGameType() == GType_ITE) {
|
if (_vm->getGameType() == GType_ITE) {
|
||||||
// Get actor resource file context
|
// Get actor resource file context
|
||||||
_actorContext = _vm->getFileContext(GAME_RESOURCEFILE, 0);
|
_actorContext = _vm->_resource->getContext(GAME_RESOURCEFILE);
|
||||||
if (_actorContext == NULL) {
|
if (_actorContext == NULL) {
|
||||||
error("Actor::Actor(): Couldn't load actor module resource context.");
|
error("Actor::Actor() resource context not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
result = RSC_LoadResource(_actorContext, _vm->getResourceDescription()->actorsStringsResourceId, &stringsPointer, &stringsLength);
|
_vm->_resource->loadResource(_actorContext, _vm->getResourceDescription()->actorsStringsResourceId, stringsPointer, stringsLength);
|
||||||
if ((result != SUCCESS) || (stringsLength == 0)) {
|
|
||||||
error("Error loading strings list resource");
|
|
||||||
}
|
|
||||||
|
|
||||||
_vm->loadStrings(_actorsStrings, stringsPointer, stringsLength);
|
_vm->loadStrings(_actorsStrings, stringsPointer, stringsLength);
|
||||||
RSC_FreeResource(stringsPointer);
|
free(stringsPointer);
|
||||||
} else {
|
} else {
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
|
@ -325,10 +323,7 @@ bool Actor::loadActorResources(ActorData *actor) {
|
||||||
}
|
}
|
||||||
|
|
||||||
debug(9, "Loading frame resource id %d", actor->frameListResourceId);
|
debug(9, "Loading frame resource id %d", actor->frameListResourceId);
|
||||||
if (RSC_LoadResource(_actorContext, actor->frameListResourceId, &resourcePointer, &resourceLength) != SUCCESS) {
|
_vm->_resource->loadResource(_actorContext, actor->frameListResourceId, resourcePointer, resourceLength);
|
||||||
warning("Couldn't load sprite action index resource");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
framesCount = resourceLength / 16;
|
framesCount = resourceLength / 16;
|
||||||
debug(9, "Frame resource contains %d frames", framesCount);
|
debug(9, "Frame resource contains %d frames", framesCount);
|
||||||
|
@ -338,7 +333,7 @@ bool Actor::loadActorResources(ActorData *actor) {
|
||||||
memoryError("Actor::loadActorResources");
|
memoryError("Actor::loadActorResources");
|
||||||
}
|
}
|
||||||
|
|
||||||
MemoryReadStreamEndian readS(resourcePointer, resourceLength, IS_BIG_ENDIAN);
|
MemoryReadStreamEndian readS(resourcePointer, resourceLength, _actorContext->isBigEndian);
|
||||||
|
|
||||||
lastFrame = 0;
|
lastFrame = 0;
|
||||||
|
|
||||||
|
@ -355,27 +350,22 @@ bool Actor::loadActorResources(ActorData *actor) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RSC_FreeResource(resourcePointer);
|
free(resourcePointer);
|
||||||
|
|
||||||
actor->frames = framesPointer;
|
actor->frames = framesPointer;
|
||||||
actor->framesCount = framesCount;
|
actor->framesCount = framesCount;
|
||||||
|
|
||||||
resourceId = actor->spriteListResourceId;
|
resourceId = actor->spriteListResourceId;
|
||||||
debug(9, "Loading sprite resource id %d", resourceId);
|
debug(9, "Loading sprite resource id %d", resourceId);
|
||||||
if (_vm->_sprite->loadList(resourceId, actor->spriteList) != SUCCESS) {
|
|
||||||
warning("loadActorResources: Unable to load sprite list");
|
_vm->_sprite->loadList(resourceId, actor->spriteList);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
i = actor->spriteList.spriteCount;
|
i = actor->spriteList.spriteCount;
|
||||||
if ((actor->flags & kExtended)) {
|
if ((actor->flags & kExtended)) {
|
||||||
while ((lastFrame >= actor->spriteList.spriteCount)) {
|
while ((lastFrame >= actor->spriteList.spriteCount)) {
|
||||||
resourceId++;
|
resourceId++;
|
||||||
debug(9, "Appending to sprite list %d", resourceId);
|
debug(9, "Appending to sprite list %d", resourceId);
|
||||||
if (_vm->_sprite->loadList(resourceId, actor->spriteList) != SUCCESS) {
|
_vm->_sprite->loadList(resourceId, actor->spriteList);
|
||||||
warning("Unable append sprite list");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2652,7 +2642,7 @@ void Actor::loadState(Common::InSaveFile *in) {
|
||||||
|
|
||||||
for (i = 0; i < _actorsCount; i++) {
|
for (i = 0; i < _actorsCount; i++) {
|
||||||
ActorData *a = _actors[i];
|
ActorData *a = _actors[i];
|
||||||
a->loadState(in);
|
a->loadState(_vm->getCurrentLoadVersion(), in);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < _objsCount; i++) {
|
for (i = 0; i < _objsCount; i++) {
|
||||||
|
|
|
@ -375,7 +375,7 @@ public:
|
||||||
out->writeSint32LE(walkFrameSequence);
|
out->writeSint32LE(walkFrameSequence);
|
||||||
}
|
}
|
||||||
|
|
||||||
void loadState(Common::InSaveFile *in) {
|
void loadState(uint32 version, Common::InSaveFile *in) {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
CommonObjectData::loadState(in);
|
CommonObjectData::loadState(in);
|
||||||
actorFlags = in->readUint16LE();
|
actorFlags = in->readUint16LE();
|
||||||
|
@ -390,14 +390,14 @@ public:
|
||||||
cycleDelay = in->readByte();
|
cycleDelay = in->readByte();
|
||||||
cycleTimeCount = in->readByte();
|
cycleTimeCount = in->readByte();
|
||||||
cycleFlags = in->readByte();
|
cycleFlags = in->readByte();
|
||||||
if (_vm->getCurrentLoadVersion() > 1) {
|
if (version > 1) {
|
||||||
fallVelocity = in->readSint16LE();
|
fallVelocity = in->readSint16LE();
|
||||||
fallAcceleration = in->readSint16LE();
|
fallAcceleration = in->readSint16LE();
|
||||||
fallPosition = in->readSint16LE();
|
fallPosition = in->readSint16LE();
|
||||||
} else {
|
} else {
|
||||||
fallVelocity = fallAcceleration = fallPosition = 0;
|
fallVelocity = fallAcceleration = fallPosition = 0;
|
||||||
}
|
}
|
||||||
if (_vm->getCurrentLoadVersion() > 2) {
|
if (version > 2) {
|
||||||
dragonBaseFrame = in->readByte();
|
dragonBaseFrame = in->readByte();
|
||||||
dragonStepCycle = in->readByte();
|
dragonStepCycle = in->readByte();
|
||||||
dragonMoveType = in->readByte();
|
dragonMoveType = in->readByte();
|
||||||
|
@ -621,7 +621,7 @@ protected:
|
||||||
ObjectData **_objs;
|
ObjectData **_objs;
|
||||||
|
|
||||||
SagaEngine *_vm;
|
SagaEngine *_vm;
|
||||||
RSCFILE_CONTEXT *_actorContext;
|
ResourceContext *_actorContext;
|
||||||
|
|
||||||
StringsTable _actorsStrings;
|
StringsTable _actorsStrings;
|
||||||
int _lastTickMsec;
|
int _lastTickMsec;
|
||||||
|
|
|
@ -46,6 +46,7 @@ Anim::~Anim(void) {
|
||||||
|
|
||||||
void Anim::load(uint16 animId, const byte *animResourceData, size_t animResourceLength) {
|
void Anim::load(uint16 animId, const byte *animResourceData, size_t animResourceLength) {
|
||||||
AnimationData *anim;
|
AnimationData *anim;
|
||||||
|
uint16 temp;
|
||||||
|
|
||||||
if (animId >= MAX_ANIMATIONS) {
|
if (animId >= MAX_ANIMATIONS) {
|
||||||
error("Anim::load could not find unused animation slot");
|
error("Anim::load could not find unused animation slot");
|
||||||
|
@ -53,7 +54,7 @@ void Anim::load(uint16 animId, const byte *animResourceData, size_t animResource
|
||||||
|
|
||||||
anim = _animations[animId] = new AnimationData(animResourceData, animResourceLength);
|
anim = _animations[animId] = new AnimationData(animResourceData, animResourceLength);
|
||||||
|
|
||||||
MemoryReadStreamEndian headerReadS(anim->resourceData, anim->resourceLength, IS_BIG_ENDIAN);
|
MemoryReadStreamEndian headerReadS(anim->resourceData, anim->resourceLength, _vm->isBigEndian());
|
||||||
anim->magic = headerReadS.readUint16LE(); // cause ALWAYS LE
|
anim->magic = headerReadS.readUint16LE(); // cause ALWAYS LE
|
||||||
anim->screenWidth = headerReadS.readUint16();
|
anim->screenWidth = headerReadS.readUint16();
|
||||||
anim->screenHeight = headerReadS.readUint16();
|
anim->screenHeight = headerReadS.readUint16();
|
||||||
|
@ -62,9 +63,12 @@ void Anim::load(uint16 animId, const byte *animResourceData, size_t animResource
|
||||||
anim->unknown07 = headerReadS.readByte();
|
anim->unknown07 = headerReadS.readByte();
|
||||||
anim->maxFrame = headerReadS.readByte() - 1;
|
anim->maxFrame = headerReadS.readByte() - 1;
|
||||||
anim->loopFrame = headerReadS.readByte() - 1;
|
anim->loopFrame = headerReadS.readByte() - 1;
|
||||||
anim->start = headerReadS.readUint16BE();
|
temp = headerReadS.readUint16BE();
|
||||||
|
anim->start = headerReadS.pos();
|
||||||
anim->start += headerReadS.pos();
|
if (temp == (uint16)(-1)) {
|
||||||
|
temp = 0;
|
||||||
|
}
|
||||||
|
anim->start += temp;
|
||||||
|
|
||||||
|
|
||||||
if (_vm->getGameType() == GType_ITE) {
|
if (_vm->getGameType() == GType_ITE) {
|
||||||
|
@ -76,8 +80,15 @@ void Anim::load(uint16 animId, const byte *animResourceData, size_t animResource
|
||||||
|
|
||||||
fillFrameOffsets(anim);
|
fillFrameOffsets(anim);
|
||||||
} else {
|
} else {
|
||||||
anim->cur_frame_p = anim->resourceData + SAGA_FRAME_HEADER_LEN; // ? len - may vary
|
/* anim->frameOffsets = (size_t *)malloc((anim->maxFrame + 1) * sizeof(*anim->frameOffsets));
|
||||||
anim->cur_frame_len = anim->resourceLength - SAGA_FRAME_HEADER_LEN;
|
if (anim->frameOffsets == NULL) {
|
||||||
|
memoryError("Anim::load");
|
||||||
|
}
|
||||||
|
|
||||||
|
fillFrameOffsets(anim);*/
|
||||||
|
|
||||||
|
anim->cur_frame_p = anim->resourceData + getFrameHeaderLength(); // ? len - may vary
|
||||||
|
anim->cur_frame_len = anim->resourceLength - getFrameHeaderLength();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set animation data
|
// Set animation data
|
||||||
|
@ -179,8 +190,8 @@ void Anim::play(uint16 animId, int vectorTime, bool playing) {
|
||||||
|
|
||||||
if (_vm->getGameType() == GType_IHNM) {
|
if (_vm->getGameType() == GType_IHNM) {
|
||||||
// FIXME: HACK. probably needs more testing for IHNM
|
// FIXME: HACK. probably needs more testing for IHNM
|
||||||
anim->cur_frame_p = anim->resourceData + SAGA_FRAME_HEADER_LEN;
|
anim->cur_frame_p = anim->resourceData + getFrameHeaderLength();
|
||||||
anim->cur_frame_len = anim->resourceLength - SAGA_FRAME_HEADER_LEN;
|
anim->cur_frame_len = anim->resourceLength - getFrameHeaderLength();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (anim->flags & ANIM_STOPPING || anim->currentFrame == -1) {
|
if (anim->flags & ANIM_STOPPING || anim->currentFrame == -1) {
|
||||||
|
@ -489,7 +500,7 @@ int Anim::IHNM_DecodeFrame(byte *decode_buf, size_t decode_buf_len, const byte *
|
||||||
|
|
||||||
size_t in_ch_offset;
|
size_t in_ch_offset;
|
||||||
|
|
||||||
MemoryReadStreamEndian readS(thisf_p, thisf_len, !IS_BIG_ENDIAN); // RLE has inversion BE<>LE
|
MemoryReadStreamEndian readS(thisf_p, thisf_len, !_vm->isBigEndian()); // RLE has inversion BE<>LE
|
||||||
|
|
||||||
byte *outbuf_p = decode_buf;
|
byte *outbuf_p = decode_buf;
|
||||||
byte *outbuf_endp = (decode_buf + decode_buf_len) - 1;
|
byte *outbuf_endp = (decode_buf + decode_buf_len) - 1;
|
||||||
|
@ -502,7 +513,7 @@ int Anim::IHNM_DecodeFrame(byte *decode_buf, size_t decode_buf_len, const byte *
|
||||||
in_ch_offset = readS.pos();
|
in_ch_offset = readS.pos();
|
||||||
in_ch = readS.readByte();
|
in_ch = readS.readByte();
|
||||||
switch (in_ch) {
|
switch (in_ch) {
|
||||||
case 0x0F: // 15: Frame header
|
case SAGA_FRAME_START: // Frame header
|
||||||
{
|
{
|
||||||
int param1;
|
int param1;
|
||||||
int param2;
|
int param2;
|
||||||
|
@ -702,12 +713,16 @@ void Anim::fillFrameOffsets(AnimationData *anim) {
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
MemoryReadStreamEndian readS(anim->resourceData, anim->resourceLength, IS_BIG_ENDIAN);
|
MemoryReadStreamEndian readS(anim->resourceData, anim->resourceLength, _vm->isBigEndian());
|
||||||
|
|
||||||
readS.seek(12);
|
if (_vm->getGameType() == GType_ITE) {
|
||||||
|
readS.seek(12);
|
||||||
|
} else {
|
||||||
|
readS.seek(15); // ihnm has longer anim header
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
readS._bigEndian = !IS_BIG_ENDIAN; // RLE has inversion BE<>LE
|
readS._bigEndian = !_vm->isBigEndian(); // RLE has inversion BE<>LE
|
||||||
|
|
||||||
for (currentFrame = 0; currentFrame <= anim->maxFrame; currentFrame++) {
|
for (currentFrame = 0; currentFrame <= anim->maxFrame; currentFrame++) {
|
||||||
anim->frameOffsets[currentFrame] = readS.pos();
|
anim->frameOffsets[currentFrame] = readS.pos();
|
||||||
|
@ -723,14 +738,14 @@ void Anim::fillFrameOffsets(AnimationData *anim) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// skip header
|
// skip header
|
||||||
readS.seek(SAGA_FRAME_HEADER_LEN, SEEK_CUR);
|
readS.seek(getFrameHeaderLength(), SEEK_CUR);
|
||||||
|
|
||||||
// For some strange reason, the animation header is in little
|
// For some strange reason, the animation header is in little
|
||||||
// endian format, but the actual RLE encoded frame data,
|
// endian format, but the actual RLE encoded frame data,
|
||||||
// including the frame header, is in big endian format. */
|
// including the frame header, is in big endian format. */
|
||||||
do {
|
do {
|
||||||
mark_byte = readS.readByte();
|
mark_byte = readS.readByte();
|
||||||
// debug(7, "_pos=%x mark_byte=%x", readS.pos(), mark_byte);
|
// debug(7, "_pos=%x currentFrame=%i mark_byte=%x", readS.pos(), currentFrame, mark_byte);
|
||||||
|
|
||||||
switch (mark_byte) {
|
switch (mark_byte) {
|
||||||
case SAGA_FRAME_END: // End of frame marker
|
case SAGA_FRAME_END: // End of frame marker
|
||||||
|
|
|
@ -33,7 +33,6 @@ namespace Saga {
|
||||||
#define MAX_ANIMATIONS 7
|
#define MAX_ANIMATIONS 7
|
||||||
#define DEFAULT_FRAME_TIME 140
|
#define DEFAULT_FRAME_TIME 140
|
||||||
|
|
||||||
#define SAGA_FRAME_HEADER_LEN (_vm->getFeatures() & GF_MAC_RESOURCES ? 13 : 12)
|
|
||||||
|
|
||||||
#define SAGA_FRAME_START 0xF
|
#define SAGA_FRAME_START 0xF
|
||||||
#define SAGA_FRAME_END 0x3F
|
#define SAGA_FRAME_END 0x3F
|
||||||
|
@ -146,6 +145,10 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int getFrameHeaderLength() const {
|
||||||
|
return (_vm->getFeatures() & GF_MAC_RESOURCES ? 13 : 12);
|
||||||
|
}
|
||||||
|
|
||||||
AnimationData* getAnimation(uint16 animId) {
|
AnimationData* getAnimation(uint16 animId) {
|
||||||
validateAnimationId(animId);
|
validateAnimationId(animId);
|
||||||
return _animations[animId];
|
return _animations[animId];
|
||||||
|
|
|
@ -66,18 +66,8 @@ Console::Console(SagaEngine *vm) : Common::Debugger<Console>() {
|
||||||
|
|
||||||
// Scene commands
|
// Scene commands
|
||||||
DCmd_Register("scene_change", &Console::cmdSceneChange);
|
DCmd_Register("scene_change", &Console::cmdSceneChange);
|
||||||
DCmd_Register("scene_info", &Console::cmdSceneInfo);
|
|
||||||
DCmd_Register("action_map_info", &Console::cmdActionMapInfo);
|
DCmd_Register("action_map_info", &Console::cmdActionMapInfo);
|
||||||
DCmd_Register("object_map_info", &Console::cmdObjectMapInfo);
|
DCmd_Register("object_map_info", &Console::cmdObjectMapInfo);
|
||||||
// CVAR_Register_I(&_sceneNumber, "scene", NULL, CVAR_READONLY, 0, 0);
|
|
||||||
|
|
||||||
// Script commands
|
|
||||||
DCmd_Register("script_info", &Console::Cmd_ScriptInfo);
|
|
||||||
DCmd_Register("script_exec", &Console::Cmd_ScriptExec);
|
|
||||||
DCmd_Register("script_togglestep", &Console::Cmd_ScriptToggleStep);
|
|
||||||
// CVAR_RegisterFunc(CF_script_info, "script_info", NULL, CVAR_NONE, 0, 0, this);
|
|
||||||
// CVAR_RegisterFunc(CF_script_exec, "script_exec", "<Script number>", CVAR_NONE, 1, 1, this);
|
|
||||||
// CVAR_RegisterFunc(CF_script_togglestep, "script_togglestep", NULL, CVAR_NONE, 0, 0, this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Console::~Console() {
|
Console::~Console() {
|
||||||
|
@ -154,11 +144,6 @@ bool Console::cmdSceneChange(int argc, const char **argv) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Console::cmdSceneInfo(int argc, const char **argv) {
|
|
||||||
_vm->_scene->cmdSceneInfo();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Console::cmdActionMapInfo(int argc, const char **argv) {
|
bool Console::cmdActionMapInfo(int argc, const char **argv) {
|
||||||
_vm->_scene->cmdActionMapInfo();
|
_vm->_scene->cmdActionMapInfo();
|
||||||
return true;
|
return true;
|
||||||
|
@ -169,22 +154,4 @@ bool Console::cmdObjectMapInfo(int argc, const char **argv) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Console::Cmd_ScriptInfo(int argc, const char **argv) {
|
|
||||||
_vm->_script->scriptInfo();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Console::Cmd_ScriptExec(int argc, const char **argv) {
|
|
||||||
if (argc != 2)
|
|
||||||
DebugPrintf("Usage: %s <Script number>\n", argv[0]);
|
|
||||||
else
|
|
||||||
_vm->_script->scriptExec(argc, argv);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Console::Cmd_ScriptToggleStep(int argc, const char **argv) {
|
|
||||||
_vm->_script->CF_script_togglestep();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // End of namespace Saga
|
} // End of namespace Saga
|
||||||
|
|
|
@ -48,13 +48,9 @@ private:
|
||||||
bool Cmd_AnimInfo(int argc, const char **argv);
|
bool Cmd_AnimInfo(int argc, const char **argv);
|
||||||
|
|
||||||
bool cmdSceneChange(int argc, const char **argv);
|
bool cmdSceneChange(int argc, const char **argv);
|
||||||
bool cmdSceneInfo(int argc, const char **argv);
|
|
||||||
bool cmdActionMapInfo(int argc, const char **argv);
|
bool cmdActionMapInfo(int argc, const char **argv);
|
||||||
bool cmdObjectMapInfo(int argc, const char **argv);
|
bool cmdObjectMapInfo(int argc, const char **argv);
|
||||||
|
|
||||||
bool Cmd_ScriptInfo(int argc, const char **argv);
|
|
||||||
bool Cmd_ScriptExec(int argc, const char **argv);
|
|
||||||
bool Cmd_ScriptToggleStep(int argc, const char **argv);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SagaEngine *_vm;
|
SagaEngine *_vm;
|
||||||
|
|
|
@ -278,7 +278,7 @@ int Events::handleOneShot(EVENT *event) {
|
||||||
case TEXT_EVENT:
|
case TEXT_EVENT:
|
||||||
switch (event->op) {
|
switch (event->op) {
|
||||||
case EVENT_DISPLAY:
|
case EVENT_DISPLAY:
|
||||||
((TextListEntry *)event->data)->display = 1;
|
((TextListEntry *)event->data)->display = true;
|
||||||
break;
|
break;
|
||||||
case EVENT_REMOVE:
|
case EVENT_REMOVE:
|
||||||
_vm->_scene->_textList.remove((TextListEntry *)event->data);
|
_vm->_scene->_textList.remove((TextListEntry *)event->data);
|
||||||
|
@ -299,7 +299,7 @@ int Events::handleOneShot(EVENT *event) {
|
||||||
case MUSIC_EVENT:
|
case MUSIC_EVENT:
|
||||||
_vm->_music->stop();
|
_vm->_music->stop();
|
||||||
if (event->op == EVENT_PLAY)
|
if (event->op == EVENT_PLAY)
|
||||||
_vm->_music->play(event->param, event->param2);
|
_vm->_music->play(event->param, (MusicFlags)event->param2);
|
||||||
break;
|
break;
|
||||||
case BG_EVENT:
|
case BG_EVENT:
|
||||||
{
|
{
|
||||||
|
@ -332,9 +332,9 @@ int Events::handleOneShot(EVENT *event) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event->param == SET_PALETTE) {
|
if (event->param == SET_PALETTE) {
|
||||||
PalEntry *pal_p;
|
PalEntry *palPointer;
|
||||||
_vm->_scene->getBGPal(&pal_p);
|
_vm->_scene->getBGPal(palPointer);
|
||||||
_vm->_gfx->setPalette(pal_p);
|
_vm->_gfx->setPalette(palPointer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,8 +24,7 @@
|
||||||
// Font management and font drawing module
|
// Font management and font drawing module
|
||||||
#include "saga/saga.h"
|
#include "saga/saga.h"
|
||||||
#include "saga/gfx.h"
|
#include "saga/gfx.h"
|
||||||
|
#include "saga/rscfile.h"
|
||||||
#include "saga/rscfile_mod.h"
|
|
||||||
|
|
||||||
#include "saga/font.h"
|
#include "saga/font.h"
|
||||||
#include "saga/stream.h"
|
#include "saga/stream.h"
|
||||||
|
@ -69,26 +68,24 @@ void Font::loadFont(uint32 fontResourceId) {
|
||||||
size_t fontResourceLength;
|
size_t fontResourceLength;
|
||||||
int numBits;
|
int numBits;
|
||||||
int c;
|
int c;
|
||||||
RSCFILE_CONTEXT *fontContext;
|
ResourceContext *fontContext;
|
||||||
|
|
||||||
|
|
||||||
debug(1, "Font::loadFont(): Reading fontResourceId %d...", fontResourceId);
|
debug(1, "Font::loadFont(): Reading fontResourceId %d...", fontResourceId);
|
||||||
|
|
||||||
fontContext = _vm->getFileContext(GAME_RESOURCEFILE, 0);
|
fontContext = _vm->_resource->getContext(GAME_RESOURCEFILE);
|
||||||
if (fontContext == NULL) {
|
if (fontContext == NULL) {
|
||||||
error("Font::Font(): Couldn't get resource context.");
|
error("Font::Font() resource context not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load font resource
|
// Load font resource
|
||||||
if (RSC_LoadResource(fontContext, fontResourceId, &fontResourcePointer, &fontResourceLength) != SUCCESS) {
|
_vm->_resource->loadResource(fontContext, fontResourceId, fontResourcePointer, fontResourceLength);
|
||||||
error("Font::loadFont(): Couldn't load font resource.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fontResourceLength < FONT_DESCSIZE) {
|
if (fontResourceLength < FONT_DESCSIZE) {
|
||||||
error("Font::loadFont(): Invalid font length (%d < %d)", fontResourceLength, FONT_DESCSIZE);
|
error("Font::loadFont() Invalid font length (%i < %i)", fontResourceLength, FONT_DESCSIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
MemoryReadStreamEndian readS(fontResourcePointer, fontResourceLength, IS_BIG_ENDIAN);
|
MemoryReadStreamEndian readS(fontResourcePointer, fontResourceLength, fontContext->isBigEndian);
|
||||||
|
|
||||||
// Create new font structure
|
// Create new font structure
|
||||||
font = (FontData *)malloc(sizeof(*font));
|
font = (FontData *)malloc(sizeof(*font));
|
||||||
|
@ -127,7 +124,7 @@ void Font::loadFont(uint32 fontResourceId) {
|
||||||
font->normal.font = (byte*)malloc(fontResourceLength - FONT_DESCSIZE);
|
font->normal.font = (byte*)malloc(fontResourceLength - FONT_DESCSIZE);
|
||||||
memcpy(font->normal.font, fontResourcePointer + FONT_DESCSIZE, fontResourceLength - FONT_DESCSIZE);
|
memcpy(font->normal.font, fontResourcePointer + FONT_DESCSIZE, fontResourceLength - FONT_DESCSIZE);
|
||||||
|
|
||||||
RSC_FreeResource(fontResourcePointer);
|
free(fontResourcePointer);
|
||||||
|
|
||||||
|
|
||||||
// Create outline font style
|
// Create outline font style
|
||||||
|
@ -437,12 +434,13 @@ void Font::textDraw(FontId fontId, Surface *ds, const char *text, const Common::
|
||||||
fitWidth = ((ds->w - TEXT_MARGIN) - textPoint.x) * 2;
|
fitWidth = ((ds->w - TEXT_MARGIN) - textPoint.x) * 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fitWidth >= textWidth) {
|
if (fitWidth < textWidth) {
|
||||||
// Entire string fits, draw it
|
warning("text too long to be displayed in one line");
|
||||||
textPoint.x = textPoint.x - (textWidth / 2);
|
|
||||||
draw(fontId, ds, text, textLength, textPoint, color, effectColor, flags);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// Entire string fits, draw it
|
||||||
|
textPoint.x = textPoint.x - (textWidth / 2);
|
||||||
|
draw(fontId, ds, text, textLength, textPoint, color, effectColor, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Font::getHeight(FontId fontId, const char *text, int width, FontEffectFlags flags) {
|
int Font::getHeight(FontId fontId, const char *text, int width, FontEffectFlags flags) {
|
||||||
|
|
|
@ -54,9 +54,10 @@ namespace Saga {
|
||||||
#define TEXT_LINESPACING 2
|
#define TEXT_LINESPACING 2
|
||||||
|
|
||||||
struct TextListEntry {
|
struct TextListEntry {
|
||||||
int display;
|
bool display;
|
||||||
// int id;
|
bool useRect;
|
||||||
Common::Point point;
|
Common::Point point;
|
||||||
|
Common::Rect rect;
|
||||||
int color;
|
int color;
|
||||||
int effectColor;
|
int effectColor;
|
||||||
FontEffectFlags flags;
|
FontEffectFlags flags;
|
||||||
|
|
234
saga/game.cpp
234
saga/game.cpp
|
@ -32,9 +32,10 @@
|
||||||
#include "base/gameDetector.h"
|
#include "base/gameDetector.h"
|
||||||
#include "backends/fs/fs.h"
|
#include "backends/fs/fs.h"
|
||||||
|
|
||||||
#include "saga/rscfile_mod.h"
|
#include "saga/rscfile.h"
|
||||||
#include "saga/interface.h"
|
#include "saga/interface.h"
|
||||||
#include "saga/scene.h"
|
#include "saga/scene.h"
|
||||||
|
#include "saga/resnames.h"
|
||||||
|
|
||||||
namespace Saga {
|
namespace Saga {
|
||||||
|
|
||||||
|
@ -202,11 +203,6 @@ static GameSoundInfo ITEDEMO_GameSound = {
|
||||||
GAME_SOUND_VOC, 0, 0, 0
|
GAME_SOUND_VOC, 0, 0, 0
|
||||||
};
|
};
|
||||||
|
|
||||||
static GameFontDescription ITEMACDEMO_GameFonts[] = {
|
|
||||||
{2},
|
|
||||||
{0}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Inherit the Earth - Wyrmkeep Win32 Demo version
|
// Inherit the Earth - Wyrmkeep Win32 Demo version
|
||||||
static GameFileDescription ITEWINDEMO_GameFiles[] = {
|
static GameFileDescription ITEWINDEMO_GameFiles[] = {
|
||||||
{"ited.rsc", GAME_RESOURCEFILE},
|
{"ited.rsc", GAME_RESOURCEFILE},
|
||||||
|
@ -215,6 +211,11 @@ static GameFileDescription ITEWINDEMO_GameFiles[] = {
|
||||||
{"voicesd.rsc", GAME_VOICEFILE}
|
{"voicesd.rsc", GAME_VOICEFILE}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static GameFontDescription ITEWINDEMO_GameFonts[] = {
|
||||||
|
{2},
|
||||||
|
{0}
|
||||||
|
};
|
||||||
|
|
||||||
// Inherit the Earth - Wyrmkeep Linux Demo version
|
// Inherit the Earth - Wyrmkeep Linux Demo version
|
||||||
static GameFileDescription ITELINDEMO_GameFiles[] = {
|
static GameFileDescription ITELINDEMO_GameFiles[] = {
|
||||||
{"ited.rsc", GAME_RESOURCEFILE},
|
{"ited.rsc", GAME_RESOURCEFILE},
|
||||||
|
@ -247,11 +248,6 @@ static GameFileDescription ITEMULTICD_GameFiles[] = {
|
||||||
{"music.rsc", GAME_MUSICFILE}
|
{"music.rsc", GAME_MUSICFILE}
|
||||||
};
|
};
|
||||||
|
|
||||||
static GameFontDescription ITEWINDEMO_GameFonts[] = {
|
|
||||||
{2},
|
|
||||||
{0}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Inherit the Earth - Mac Wyrmkeep version
|
// Inherit the Earth - Mac Wyrmkeep version
|
||||||
static GameFileDescription ITEMACCD_GameFiles[] = {
|
static GameFileDescription ITEMACCD_GameFiles[] = {
|
||||||
{"ite.rsc", GAME_RESOURCEFILE},
|
{"ite.rsc", GAME_RESOURCEFILE},
|
||||||
|
@ -274,7 +270,7 @@ static GameFontDescription ITEDISK_GameFonts[] = {
|
||||||
{1}
|
{1}
|
||||||
};
|
};
|
||||||
|
|
||||||
static GameSoundInfo ITE_GameSound = {
|
static GameSoundInfo ITEDISK_GameSound = {
|
||||||
GAME_SOUND_VOC, 0, 0, 0
|
GAME_SOUND_VOC, 0, 0, 0
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -296,7 +292,79 @@ static GameSoundInfo ITECD_GameSound = {
|
||||||
GAME_SOUND_PCM,
|
GAME_SOUND_PCM,
|
||||||
22050,
|
22050,
|
||||||
16,
|
16,
|
||||||
0
|
false
|
||||||
|
};
|
||||||
|
|
||||||
|
static GamePatchDescription ITEWinPatch1_Files[] = {
|
||||||
|
{ "cave.mid", GAME_RESOURCEFILE, 9},
|
||||||
|
{ "intro.mid", GAME_RESOURCEFILE, 10},
|
||||||
|
{ "fvillage.mid", GAME_RESOURCEFILE, 11},
|
||||||
|
{ "elkhall.mid", GAME_RESOURCEFILE, 12},
|
||||||
|
{ "mouse.mid", GAME_RESOURCEFILE, 13},
|
||||||
|
{ "darkclaw.mid", GAME_RESOURCEFILE, 14},
|
||||||
|
{ "birdchrp.mid", GAME_RESOURCEFILE, 15},
|
||||||
|
{ "orbtempl.mid", GAME_RESOURCEFILE, 16},
|
||||||
|
{ "spooky.mid", GAME_RESOURCEFILE, 17},
|
||||||
|
{ "catfest.mid", GAME_RESOURCEFILE, 18},
|
||||||
|
{ "elkfanfare.mid", GAME_RESOURCEFILE, 19},
|
||||||
|
{ "bcexpl.mid", GAME_RESOURCEFILE, 20},
|
||||||
|
{ "boargtnt.mid", GAME_RESOURCEFILE, 21},
|
||||||
|
{ "boarking.mid", GAME_RESOURCEFILE, 22},
|
||||||
|
{ "explorea.mid", GAME_RESOURCEFILE, 23},
|
||||||
|
{ "exploreb.mid", GAME_RESOURCEFILE, 24},
|
||||||
|
{ "explorec.mid", GAME_RESOURCEFILE, 25},
|
||||||
|
{ "sunstatm.mid", GAME_RESOURCEFILE, 26},
|
||||||
|
{ "nitstrlm.mid", GAME_RESOURCEFILE, 27},
|
||||||
|
{ "humruinm.mid", GAME_RESOURCEFILE, 28},
|
||||||
|
{ "damexplm.mid", GAME_RESOURCEFILE, 29},
|
||||||
|
{ "tychom.mid", GAME_RESOURCEFILE, 30},
|
||||||
|
{ "kitten.mid", GAME_RESOURCEFILE, 31},
|
||||||
|
{ "sweet.mid", GAME_RESOURCEFILE, 32},
|
||||||
|
{ "brutalmt.mid", GAME_RESOURCEFILE, 33},
|
||||||
|
{ "shiala.mid", GAME_RESOURCEFILE, 34},
|
||||||
|
|
||||||
|
{ "wyrm.pak", GAME_RESOURCEFILE, 1529},
|
||||||
|
{ "wyrm1.dlt", GAME_RESOURCEFILE, 1530},
|
||||||
|
{ "wyrm2.dlt", GAME_RESOURCEFILE, 1531},
|
||||||
|
{ "wyrm3.dlt", GAME_RESOURCEFILE, 1532},
|
||||||
|
{ "wyrm4.dlt", GAME_RESOURCEFILE, 1533},
|
||||||
|
{ "credit3n.dlt", GAME_RESOURCEFILE, 1796},
|
||||||
|
{ "credit4n.dlt", GAME_RESOURCEFILE, 1797},
|
||||||
|
{ "p2_a.voc", GAME_VOICEFILE, 4},
|
||||||
|
};
|
||||||
|
|
||||||
|
static GamePatchDescription ITEWinPatch2_Files[] = {
|
||||||
|
{ "cave.mid", GAME_RESOURCEFILE, 9},
|
||||||
|
{ "intro.mid", GAME_RESOURCEFILE, 10},
|
||||||
|
{ "fvillage.mid", GAME_RESOURCEFILE, 11},
|
||||||
|
{ "elkfanfare.mid", GAME_RESOURCEFILE, 19},
|
||||||
|
{ "bcexpl.mid", GAME_RESOURCEFILE, 20},
|
||||||
|
{ "boargtnt.mid", GAME_RESOURCEFILE, 21},
|
||||||
|
{ "explorea.mid", GAME_RESOURCEFILE, 23},
|
||||||
|
{ "sweet.mid", GAME_RESOURCEFILE, 32},
|
||||||
|
|
||||||
|
{ "wyrm.pak", GAME_RESOURCEFILE, 1529},
|
||||||
|
{ "wyrm1.dlt", GAME_RESOURCEFILE, 1530},
|
||||||
|
{ "wyrm2.dlt", GAME_RESOURCEFILE, 1531},
|
||||||
|
{ "wyrm3.dlt", GAME_RESOURCEFILE, 1532},
|
||||||
|
{ "p2_a.iaf", GAME_VOICEFILE, 4}
|
||||||
|
/* boarhall.bbm
|
||||||
|
elkenter.bbm
|
||||||
|
ferrets.bbm
|
||||||
|
ratdoor.bbm
|
||||||
|
sanctuar.bbm
|
||||||
|
tycho.bbm*/
|
||||||
|
};
|
||||||
|
|
||||||
|
static GamePatchDescription ITEMacPatch_Files[] = {
|
||||||
|
{ "wyrm.pak", GAME_RESOURCEFILE, 1529},
|
||||||
|
{ "wyrm1.dlt", GAME_RESOURCEFILE, 1530},
|
||||||
|
{ "wyrm2.dlt", GAME_RESOURCEFILE, 1531},
|
||||||
|
{ "wyrm3.dlt", GAME_RESOURCEFILE, 1532},
|
||||||
|
{ "wyrm4.dlt", GAME_RESOURCEFILE, 1533},
|
||||||
|
{ "credit3m.dlt", GAME_RESOURCEFILE, 1796},
|
||||||
|
{ "credit4m.dlt", GAME_RESOURCEFILE, 1797},
|
||||||
|
{ "p2_a.iaf", GAME_VOICEFILE, 4}
|
||||||
};
|
};
|
||||||
|
|
||||||
// IHNM section
|
// IHNM section
|
||||||
|
@ -588,6 +656,8 @@ static GameDescription gameDescriptions[] = {
|
||||||
ARRAYSIZE(ITEDEMO_GameFonts),
|
ARRAYSIZE(ITEDEMO_GameFonts),
|
||||||
ITEDEMO_GameFonts,
|
ITEDEMO_GameFonts,
|
||||||
&ITEDEMO_GameSound,
|
&ITEDEMO_GameSound,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
0, // features
|
0, // features
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -602,9 +672,11 @@ static GameDescription gameDescriptions[] = {
|
||||||
&ITE_Resources,
|
&ITE_Resources,
|
||||||
ARRAYSIZE(ITEWINDEMO_GameFiles),
|
ARRAYSIZE(ITEWINDEMO_GameFiles),
|
||||||
ITEWINDEMO_GameFiles,
|
ITEWINDEMO_GameFiles,
|
||||||
ARRAYSIZE(ITEMACDEMO_GameFonts),
|
ARRAYSIZE(ITEWINDEMO_GameFonts),
|
||||||
ITEMACDEMO_GameFonts,
|
ITEWINDEMO_GameFonts,
|
||||||
&ITECD_GameSound,
|
&ITECD_GameSound,
|
||||||
|
ARRAYSIZE(ITEMacPatch_Files),
|
||||||
|
ITEMacPatch_Files,
|
||||||
GF_VOX_VOICES | GF_BIG_ENDIAN_DATA | GF_MAC_RESOURCES | GF_WYRMKEEP | GF_CD_FX
|
GF_VOX_VOICES | GF_BIG_ENDIAN_DATA | GF_MAC_RESOURCES | GF_WYRMKEEP | GF_CD_FX
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -619,9 +691,11 @@ static GameDescription gameDescriptions[] = {
|
||||||
&ITE_Resources,
|
&ITE_Resources,
|
||||||
ARRAYSIZE(ITEWINDEMO_GameFiles),
|
ARRAYSIZE(ITEWINDEMO_GameFiles),
|
||||||
ITEWINDEMO_GameFiles,
|
ITEWINDEMO_GameFiles,
|
||||||
ARRAYSIZE(ITEMACDEMO_GameFonts),
|
ARRAYSIZE(ITEWINDEMO_GameFonts),
|
||||||
ITEMACDEMO_GameFonts,
|
ITEWINDEMO_GameFonts,
|
||||||
&ITECD_GameSound,
|
&ITECD_GameSound,
|
||||||
|
ARRAYSIZE(ITEMacPatch_Files),
|
||||||
|
ITEMacPatch_Files,
|
||||||
GF_VOX_VOICES | GF_BIG_ENDIAN_DATA | GF_MAC_RESOURCES | GF_WYRMKEEP | GF_CD_FX
|
GF_VOX_VOICES | GF_BIG_ENDIAN_DATA | GF_MAC_RESOURCES | GF_WYRMKEEP | GF_CD_FX
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -636,9 +710,11 @@ static GameDescription gameDescriptions[] = {
|
||||||
&ITE_Resources,
|
&ITE_Resources,
|
||||||
ARRAYSIZE(ITEMACCD_GameFiles),
|
ARRAYSIZE(ITEMACCD_GameFiles),
|
||||||
ITEMACCD_GameFiles,
|
ITEMACCD_GameFiles,
|
||||||
ARRAYSIZE(ITEMACDEMO_GameFonts),
|
ARRAYSIZE(ITEWINDEMO_GameFonts),
|
||||||
ITEMACDEMO_GameFonts,
|
ITEWINDEMO_GameFonts,
|
||||||
&ITECD_GameSound,
|
&ITECD_GameSound,
|
||||||
|
ARRAYSIZE(ITEMacPatch_Files),
|
||||||
|
ITEMacPatch_Files,
|
||||||
GF_BIG_ENDIAN_DATA | GF_MAC_RESOURCES | GF_WYRMKEEP | GF_CD_FX
|
GF_BIG_ENDIAN_DATA | GF_MAC_RESOURCES | GF_WYRMKEEP | GF_CD_FX
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -657,6 +733,8 @@ static GameDescription gameDescriptions[] = {
|
||||||
ARRAYSIZE(ITECD_GameFonts),
|
ARRAYSIZE(ITECD_GameFonts),
|
||||||
ITECD_GameFonts,
|
ITECD_GameFonts,
|
||||||
&ITECD_GameSound,
|
&ITECD_GameSound,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
GF_VOX_VOICES | GF_WYRMKEEP | GF_CD_FX
|
GF_VOX_VOICES | GF_WYRMKEEP | GF_CD_FX
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -674,6 +752,8 @@ static GameDescription gameDescriptions[] = {
|
||||||
ARRAYSIZE(ITEWINDEMO_GameFonts),
|
ARRAYSIZE(ITEWINDEMO_GameFonts),
|
||||||
ITEWINDEMO_GameFonts,
|
ITEWINDEMO_GameFonts,
|
||||||
&ITECD_GameSound,
|
&ITECD_GameSound,
|
||||||
|
ARRAYSIZE(ITEWinPatch2_Files),
|
||||||
|
ITEWinPatch2_Files,
|
||||||
GF_VOX_VOICES | GF_WYRMKEEP | GF_CD_FX
|
GF_VOX_VOICES | GF_WYRMKEEP | GF_CD_FX
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -691,6 +771,8 @@ static GameDescription gameDescriptions[] = {
|
||||||
ARRAYSIZE(ITEWINDEMO_GameFonts),
|
ARRAYSIZE(ITEWINDEMO_GameFonts),
|
||||||
ITEWINDEMO_GameFonts,
|
ITEWINDEMO_GameFonts,
|
||||||
&ITECD_GameSound,
|
&ITECD_GameSound,
|
||||||
|
ARRAYSIZE(ITEWinPatch1_Files),
|
||||||
|
ITEWinPatch1_Files,
|
||||||
GF_VOX_VOICES | GF_WYRMKEEP | GF_CD_FX
|
GF_VOX_VOICES | GF_WYRMKEEP | GF_CD_FX
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -708,6 +790,8 @@ static GameDescription gameDescriptions[] = {
|
||||||
ARRAYSIZE(ITECD_GameFonts),
|
ARRAYSIZE(ITECD_GameFonts),
|
||||||
ITECD_GameFonts,
|
ITECD_GameFonts,
|
||||||
&ITECD_GameSound,
|
&ITECD_GameSound,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
GF_WYRMKEEP | GF_BIG_ENDIAN_VOICES | GF_CD_FX
|
GF_WYRMKEEP | GF_BIG_ENDIAN_VOICES | GF_CD_FX
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -726,6 +810,8 @@ static GameDescription gameDescriptions[] = {
|
||||||
ARRAYSIZE(ITECD_GameFonts),
|
ARRAYSIZE(ITECD_GameFonts),
|
||||||
ITECD_GameFonts,
|
ITECD_GameFonts,
|
||||||
&ITECD_GameSound,
|
&ITECD_GameSound,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
GF_WYRMKEEP | GF_CD_FX
|
GF_WYRMKEEP | GF_CD_FX
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -743,6 +829,8 @@ static GameDescription gameDescriptions[] = {
|
||||||
ARRAYSIZE(ITECD_GameFonts),
|
ARRAYSIZE(ITECD_GameFonts),
|
||||||
ITECD_GameFonts,
|
ITECD_GameFonts,
|
||||||
&ITECD_GameSound,
|
&ITECD_GameSound,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
GF_CD_FX
|
GF_CD_FX
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -760,6 +848,8 @@ static GameDescription gameDescriptions[] = {
|
||||||
ARRAYSIZE(ITECD_GameFonts),
|
ARRAYSIZE(ITECD_GameFonts),
|
||||||
ITECD_GameFonts,
|
ITECD_GameFonts,
|
||||||
&ITECD_GameSound,
|
&ITECD_GameSound,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
GF_LANG_DE | GF_CD_FX
|
GF_LANG_DE | GF_CD_FX
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -777,6 +867,8 @@ static GameDescription gameDescriptions[] = {
|
||||||
ARRAYSIZE(ITECD_GameFonts),
|
ARRAYSIZE(ITECD_GameFonts),
|
||||||
ITECD_GameFonts,
|
ITECD_GameFonts,
|
||||||
&ITECD_GameSound,
|
&ITECD_GameSound,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
GF_CD_FX
|
GF_CD_FX
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -793,7 +885,9 @@ static GameDescription gameDescriptions[] = {
|
||||||
ITEDISK_GameFiles,
|
ITEDISK_GameFiles,
|
||||||
ARRAYSIZE(ITEDISK_GameFonts),
|
ARRAYSIZE(ITEDISK_GameFonts),
|
||||||
ITEDISK_GameFonts,
|
ITEDISK_GameFonts,
|
||||||
&ITE_GameSound,
|
&ITEDISK_GameSound,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
GF_LANG_DE
|
GF_LANG_DE
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -810,7 +904,9 @@ static GameDescription gameDescriptions[] = {
|
||||||
ITEDISK_GameFiles,
|
ITEDISK_GameFiles,
|
||||||
ARRAYSIZE(ITEDISK_GameFonts),
|
ARRAYSIZE(ITEDISK_GameFonts),
|
||||||
ITEDISK_GameFonts,
|
ITEDISK_GameFonts,
|
||||||
&ITE_GameSound,
|
&ITEDISK_GameSound,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
0
|
0
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -828,6 +924,8 @@ static GameDescription gameDescriptions[] = {
|
||||||
ARRAYSIZE(IHNMCD_GameFonts),
|
ARRAYSIZE(IHNMCD_GameFonts),
|
||||||
IHNMCD_GameFonts,
|
IHNMCD_GameFonts,
|
||||||
&IHNM_GameSound,
|
&IHNM_GameSound,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
GF_DEFAULT_TO_1X_SCALER
|
GF_DEFAULT_TO_1X_SCALER
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -845,6 +943,8 @@ static GameDescription gameDescriptions[] = {
|
||||||
ARRAYSIZE(IHNMCD_GameFonts),
|
ARRAYSIZE(IHNMCD_GameFonts),
|
||||||
IHNMCD_GameFonts,
|
IHNMCD_GameFonts,
|
||||||
&IHNM_GameSound,
|
&IHNM_GameSound,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
GF_DEFAULT_TO_1X_SCALER
|
GF_DEFAULT_TO_1X_SCALER
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -862,56 +962,39 @@ static GameDescription gameDescriptions[] = {
|
||||||
ARRAYSIZE(IHNMCD_GameFonts),
|
ARRAYSIZE(IHNMCD_GameFonts),
|
||||||
IHNMCD_GameFonts,
|
IHNMCD_GameFonts,
|
||||||
&IHNM_GameSound,
|
&IHNM_GameSound,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
GF_DEFAULT_TO_1X_SCALER
|
GF_DEFAULT_TO_1X_SCALER
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
int SagaEngine::initGame(void) {
|
bool SagaEngine::initGame(void) {
|
||||||
|
uint16 gameCount = ARRAYSIZE(gameDescriptions);
|
||||||
int gameNumber;
|
int gameNumber;
|
||||||
FSList dummy;
|
FSList dummy;
|
||||||
|
|
||||||
if ((gameNumber = detectGame(dummy)) == -1) {
|
if ((gameNumber = detectGame(dummy)) == -1) {
|
||||||
warning("No valid games were found in the specified directory.");
|
warning("No valid games were found in the specified directory.");
|
||||||
return FAILURE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (loadGame(gameNumber) != SUCCESS) {
|
|
||||||
warning("Error loading game resource files.");
|
|
||||||
return FAILURE;
|
if (gameNumber >= gameCount) {
|
||||||
|
error("SagaEngine::loadGame wrong gameNumber");
|
||||||
}
|
}
|
||||||
|
|
||||||
return SUCCESS;
|
_gameNumber = gameNumber;
|
||||||
}
|
_gameDescription = &gameDescriptions[gameNumber];
|
||||||
|
_gameDisplayInfo = *_gameDescription->gameDisplayInfo;
|
||||||
|
_displayClip.right = _gameDisplayInfo.logicalWidth;
|
||||||
|
_displayClip.bottom = _gameDisplayInfo.logicalHeight;
|
||||||
|
|
||||||
RSCFILE_CONTEXT *SagaEngine::getFileContext(uint16 type, int param) {
|
|
||||||
uint16 i;
|
|
||||||
|
|
||||||
for (i = 0; i < _gameDescription->filesCount; i++) {
|
if (!_resource->createContexts()) {
|
||||||
if (_gameDescription->filesDescriptions[i].fileType & type) {
|
return false;
|
||||||
return _gameFileContexts[i];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SagaEngine::isBigEndianFile(const char *filename) {
|
|
||||||
bool isBigEndian = IS_BIG_ENDIAN;
|
|
||||||
|
|
||||||
if (isBigEndian)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
if (!(_vm->getFeatures() & GF_BIG_ENDIAN_VOICES))
|
|
||||||
return isBigEndian;
|
|
||||||
|
|
||||||
for (int i = 0; i < _gameDescription->filesCount; i++) {
|
|
||||||
GameFileDescription *desc = &_gameDescription->filesDescriptions[i];
|
|
||||||
if (desc->fileType & GAME_VOICEFILE && scumm_stricmp(filename, desc->fileName) == 0) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return isBigEndian;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DetectedGameList GAME_ProbeGame(const FSList &fslist) {
|
DetectedGameList GAME_ProbeGame(const FSList &fslist) {
|
||||||
|
@ -1044,45 +1127,4 @@ int detectGame(const FSList &fslist, bool mode) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SagaEngine::loadGame(int gameNumber) {
|
|
||||||
RSCFILE_CONTEXT *loadContext;
|
|
||||||
uint16 gameCount = ARRAYSIZE(gameDescriptions);
|
|
||||||
const char *gameFileName;
|
|
||||||
uint16 gameFileCount;
|
|
||||||
uint16 i;
|
|
||||||
|
|
||||||
if (gameNumber >= gameCount) {
|
|
||||||
error("SagaEngine::loadGame wrong gameNumber");
|
|
||||||
}
|
|
||||||
|
|
||||||
_gameNumber = gameNumber;
|
|
||||||
_gameDescription = &gameDescriptions[gameNumber];
|
|
||||||
_gameDisplayInfo = *_gameDescription->gameDisplayInfo;
|
|
||||||
_displayClip.right = _gameDisplayInfo.logicalWidth;
|
|
||||||
_displayClip.bottom = _gameDisplayInfo.logicalHeight;
|
|
||||||
|
|
||||||
gameFileCount = _gameDescription->filesCount;
|
|
||||||
|
|
||||||
_gameFileContexts = (RSCFILE_CONTEXT **)realloc(_gameFileContexts, gameFileCount * sizeof(*_gameFileContexts));
|
|
||||||
//TODO: on exit - FREE!
|
|
||||||
if (_gameFileContexts == NULL) {
|
|
||||||
memoryError("SagaEngine::loadGame");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Load game resource files
|
|
||||||
for (i = 0; i < gameFileCount; i++) {
|
|
||||||
loadContext = RSC_CreateContext();
|
|
||||||
gameFileName = _gameDescription->filesDescriptions[i].fileName;
|
|
||||||
if (RSC_OpenContext(loadContext, gameFileName) != SUCCESS) {
|
|
||||||
return FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
debug(3, "Opened resource file: %s", gameFileName);
|
|
||||||
_gameFileContexts[i] = loadContext;
|
|
||||||
}
|
|
||||||
|
|
||||||
return SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // End of namespace Saga
|
} // End of namespace Saga
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
|
|
||||||
namespace Saga {
|
namespace Saga {
|
||||||
|
|
||||||
Gfx::Gfx(OSystem *system, int width, int height, GameDetector &detector) : _system(system) {
|
Gfx::Gfx(SagaEngine *vm, OSystem *system, int width, int height, GameDetector &detector) : _vm(vm), _system(system) {
|
||||||
_system->beginGFXTransaction();
|
_system->beginGFXTransaction();
|
||||||
_vm->initCommonGFX(detector);
|
_vm->initCommonGFX(detector);
|
||||||
_system->initSize(width, height);
|
_system->initSize(width, height);
|
||||||
|
|
|
@ -123,11 +123,12 @@ struct Surface : Graphics::Surface {
|
||||||
#define CURSOR_ORIGIN_Y 4
|
#define CURSOR_ORIGIN_Y 4
|
||||||
|
|
||||||
bool hitTestPoly(const Point *points, unsigned int npoints, const Point& test_point);
|
bool hitTestPoly(const Point *points, unsigned int npoints, const Point& test_point);
|
||||||
|
class SagaEngine;
|
||||||
|
|
||||||
class Gfx {
|
class Gfx {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Gfx(OSystem *system, int width, int height, GameDetector &detector);
|
Gfx(SagaEngine *vm, OSystem *system, int width, int height, GameDetector &detector);
|
||||||
~Gfx();
|
~Gfx();
|
||||||
Surface *getBackBuffer() {
|
Surface *getBackBuffer() {
|
||||||
return &_backBuffer;
|
return &_backBuffer;
|
||||||
|
@ -146,6 +147,7 @@ private:
|
||||||
Surface _backBuffer;
|
Surface _backBuffer;
|
||||||
byte _currentPal[PAL_ENTRIES * 4];
|
byte _currentPal[PAL_ENTRIES * 4];
|
||||||
OSystem *_system;
|
OSystem *_system;
|
||||||
|
SagaEngine *_vm;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // End of namespace Saga
|
} // End of namespace Saga
|
||||||
|
|
|
@ -28,7 +28,6 @@
|
||||||
|
|
||||||
#include "saga/animation.h"
|
#include "saga/animation.h"
|
||||||
#include "saga/events.h"
|
#include "saga/events.h"
|
||||||
#include "saga/rscfile_mod.h"
|
|
||||||
#include "saga/sndres.h"
|
#include "saga/sndres.h"
|
||||||
#include "saga/music.h"
|
#include "saga/music.h"
|
||||||
|
|
||||||
|
@ -36,9 +35,9 @@
|
||||||
|
|
||||||
namespace Saga {
|
namespace Saga {
|
||||||
|
|
||||||
SCENE_RESLIST IHNM_IntroMovie1RL[] = {
|
SceneResourceData IHNM_IntroMovie1RL[] = {
|
||||||
{30, SAGA_BG_IMAGE, 0, 0} ,
|
{30, SAGA_BG_IMAGE, 0, 0, false} ,
|
||||||
{31, SAGA_ANIM_1, 0, 0}
|
{31, SAGA_ANIM_1, 0, 0, false}
|
||||||
};
|
};
|
||||||
|
|
||||||
SceneDescription IHNM_IntroMovie1Desc = {
|
SceneDescription IHNM_IntroMovie1Desc = {
|
||||||
|
@ -47,9 +46,9 @@ SceneDescription IHNM_IntroMovie1Desc = {
|
||||||
ARRAYSIZE(IHNM_IntroMovie1RL)
|
ARRAYSIZE(IHNM_IntroMovie1RL)
|
||||||
};
|
};
|
||||||
|
|
||||||
SCENE_RESLIST IHNM_IntroMovie2RL[] = {
|
SceneResourceData IHNM_IntroMovie2RL[] = {
|
||||||
{32, SAGA_BG_IMAGE, 0, 0} ,
|
{32, SAGA_BG_IMAGE, 0, 0, false} ,
|
||||||
{33, SAGA_ANIM_1, 0, 0}
|
{33, SAGA_ANIM_1, 0, 0, false}
|
||||||
};
|
};
|
||||||
|
|
||||||
SceneDescription IHNM_IntroMovie2Desc = {
|
SceneDescription IHNM_IntroMovie2Desc = {
|
||||||
|
@ -58,9 +57,9 @@ SceneDescription IHNM_IntroMovie2Desc = {
|
||||||
ARRAYSIZE(IHNM_IntroMovie2RL)
|
ARRAYSIZE(IHNM_IntroMovie2RL)
|
||||||
};
|
};
|
||||||
|
|
||||||
SCENE_RESLIST IHNM_IntroMovie3RL[] = {
|
SceneResourceData IHNM_IntroMovie3RL[] = {
|
||||||
{34, SAGA_BG_IMAGE, 0, 0},
|
{34, SAGA_BG_IMAGE, 0, 0, false},
|
||||||
{35, SAGA_ANIM_1, 0, 0}
|
{35, SAGA_ANIM_1, 0, 0, false}
|
||||||
};
|
};
|
||||||
|
|
||||||
SceneDescription IHNM_IntroMovie3Desc = {
|
SceneDescription IHNM_IntroMovie3Desc = {
|
||||||
|
@ -69,9 +68,9 @@ SceneDescription IHNM_IntroMovie3Desc = {
|
||||||
ARRAYSIZE(IHNM_IntroMovie3RL)
|
ARRAYSIZE(IHNM_IntroMovie3RL)
|
||||||
};
|
};
|
||||||
|
|
||||||
SCENE_RESLIST IHNM_IntroMovie4RL[] = {
|
SceneResourceData IHNM_IntroMovie4RL[] = {
|
||||||
{1227, SAGA_BG_IMAGE, 0, 0},
|
{1227, SAGA_BG_IMAGE, 0, 0, false},
|
||||||
{1226, SAGA_ANIM_1, 0, 0}
|
{1226, SAGA_ANIM_1, 0, 0, false}
|
||||||
};
|
};
|
||||||
|
|
||||||
SceneDescription IHNM_IntroMovie4Desc = {
|
SceneDescription IHNM_IntroMovie4Desc = {
|
||||||
|
@ -207,7 +206,7 @@ int Scene::IHNMIntroMovieProc2(int param) {
|
||||||
q_event = _vm->_events->chain(q_event, &event);
|
q_event = _vm->_events->chain(q_event, &event);
|
||||||
|
|
||||||
// Fade in from black to the scene background palette
|
// Fade in from black to the scene background palette
|
||||||
_vm->_scene->getBGPal(&pal);
|
_vm->_scene->getBGPal(pal);
|
||||||
|
|
||||||
event.type = CONTINUOUS_EVENT;
|
event.type = CONTINUOUS_EVENT;
|
||||||
event.code = PAL_EVENT;
|
event.code = PAL_EVENT;
|
||||||
|
@ -275,7 +274,7 @@ int Scene::IHNMIntroMovieProc3(int param) {
|
||||||
event.type = ONESHOT_EVENT;
|
event.type = ONESHOT_EVENT;
|
||||||
event.code = MUSIC_EVENT;
|
event.code = MUSIC_EVENT;
|
||||||
event.param = 1;
|
event.param = 1;
|
||||||
event.param2 = 0;
|
event.param2 = MUSIC_NORMAL;
|
||||||
event.op = EVENT_PLAY;
|
event.op = EVENT_PLAY;
|
||||||
event.time = 0;
|
event.time = 0;
|
||||||
|
|
||||||
|
@ -292,7 +291,7 @@ int Scene::IHNMIntroMovieProc3(int param) {
|
||||||
q_event = _vm->_events->chain(q_event, &event);
|
q_event = _vm->_events->chain(q_event, &event);
|
||||||
|
|
||||||
// Fade in from black to the scene background palette
|
// Fade in from black to the scene background palette
|
||||||
_vm->_scene->getBGPal(&pal);
|
_vm->_scene->getBGPal(pal);
|
||||||
|
|
||||||
event.type = CONTINUOUS_EVENT;
|
event.type = CONTINUOUS_EVENT;
|
||||||
event.code = PAL_EVENT;
|
event.code = PAL_EVENT;
|
||||||
|
|
|
@ -58,11 +58,10 @@ int SagaEngine::decodeBGImage(const byte *image_data, size_t image_size,
|
||||||
size_t out_buf_len;
|
size_t out_buf_len;
|
||||||
|
|
||||||
if (image_size <= SAGA_IMAGE_DATA_OFFSET) {
|
if (image_size <= SAGA_IMAGE_DATA_OFFSET) {
|
||||||
/* Image size is way too small */
|
error("decodeBGImage() Image size is way too small");
|
||||||
return FAILURE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MemoryReadStreamEndian readS(image_data, image_size, IS_BIG_ENDIAN);
|
MemoryReadStreamEndian readS(image_data, image_size, isBigEndian());
|
||||||
|
|
||||||
hdr.width = readS.readUint16();
|
hdr.width = readS.readUint16();
|
||||||
hdr.height = readS.readUint16();
|
hdr.height = readS.readUint16();
|
||||||
|
@ -91,7 +90,7 @@ int SagaEngine::decodeBGImage(const byte *image_data, size_t image_size,
|
||||||
unbankBGImage(out_buf, decode_buf, hdr.width, hdr.height);
|
unbankBGImage(out_buf, decode_buf, hdr.width, hdr.height);
|
||||||
|
|
||||||
// For some reason bg images in IHNM are upside down
|
// For some reason bg images in IHNM are upside down
|
||||||
if (_vm->getGameType() == GType_IHNM) {
|
if (getGameType() == GType_IHNM) {
|
||||||
flipImage(out_buf, hdr.width, hdr.height);
|
flipImage(out_buf, hdr.width, hdr.height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -76,7 +76,7 @@ int SagaEngine::processInput() {
|
||||||
break;*/
|
break;*/
|
||||||
case 282: // F1
|
case 282: // F1
|
||||||
_render->toggleFlag(RF_SHOW_FPS);
|
_render->toggleFlag(RF_SHOW_FPS);
|
||||||
_vm->_actor->_handleActionDiv = (_vm->_actor->_handleActionDiv == 15) ? 50 : 15;
|
_actor->_handleActionDiv = (_actor->_handleActionDiv == 15) ? 50 : 15;
|
||||||
break;
|
break;
|
||||||
case 283: // F2
|
case 283: // F2
|
||||||
_render->toggleFlag(RF_PALETTE_TEST);
|
_render->toggleFlag(RF_PALETTE_TEST);
|
||||||
|
@ -94,9 +94,6 @@ int SagaEngine::processInput() {
|
||||||
break;
|
break;
|
||||||
case 289: // F8
|
case 289: // F8
|
||||||
break;
|
break;
|
||||||
case 9: // Tab
|
|
||||||
_script->SThreadDebugStep();
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Actual game keys
|
// Actual game keys
|
||||||
case 32: // space
|
case 32: // space
|
||||||
|
@ -140,7 +137,7 @@ int SagaEngine::processInput() {
|
||||||
_mousePos = event.mouse;
|
_mousePos = event.mouse;
|
||||||
break;
|
break;
|
||||||
case OSystem::EVENT_QUIT:
|
case OSystem::EVENT_QUIT:
|
||||||
_vm->shutDown();
|
shutDown();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -33,10 +33,11 @@
|
||||||
#include "saga/itedata.h"
|
#include "saga/itedata.h"
|
||||||
#include "saga/puzzle.h"
|
#include "saga/puzzle.h"
|
||||||
#include "saga/render.h"
|
#include "saga/render.h"
|
||||||
#include "saga/rscfile_mod.h"
|
|
||||||
#include "saga/scene.h"
|
#include "saga/scene.h"
|
||||||
#include "saga/script.h"
|
#include "saga/script.h"
|
||||||
#include "saga/sprite.h"
|
#include "saga/sprite.h"
|
||||||
|
#include "saga/rscfile.h"
|
||||||
|
#include "saga/resnames.h"
|
||||||
|
|
||||||
#include "saga/interface.h"
|
#include "saga/interface.h"
|
||||||
|
|
||||||
|
@ -63,21 +64,16 @@ static int verbTypeToTextStringsIdLUT[kVerbTypesMax] = {
|
||||||
-1
|
-1
|
||||||
};
|
};
|
||||||
|
|
||||||
Interface::Interface(SagaEngine *vm) : _vm(vm), _initialized(false) {
|
Interface::Interface(SagaEngine *vm) : _vm(vm) {
|
||||||
byte *resource;
|
byte *resource;
|
||||||
size_t resourceLength;
|
size_t resourceLength;
|
||||||
int result;
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (_initialized) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Load interface module resource file context
|
// Load interface module resource file context
|
||||||
_interfaceContext = _vm->getFileContext(GAME_RESOURCEFILE, 0);
|
_interfaceContext = _vm->_resource->getContext(GAME_RESOURCEFILE);
|
||||||
if (_interfaceContext == NULL) {
|
if (_interfaceContext == NULL) {
|
||||||
error("Interface::Interface(): unable to load resource");
|
error("Interface::Interface() resource context not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
_mainPanel.buttons = _vm->getDisplayInfo().mainPanelButtons;
|
_mainPanel.buttons = _vm->getDisplayInfo().mainPanelButtons;
|
||||||
|
@ -93,46 +89,33 @@ Interface::Interface(SagaEngine *vm) : _vm(vm), _initialized(false) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
result = RSC_LoadResource(_interfaceContext, _vm->getResourceDescription()->mainPanelResourceId, &resource, &resourceLength);
|
_vm->_resource->loadResource(_interfaceContext, _vm->getResourceDescription()->mainPanelResourceId, resource, resourceLength);
|
||||||
if ((result != SUCCESS) || (resourceLength == 0)) {
|
|
||||||
error("Interface::Interface(): unable to load mainPanel resource");
|
|
||||||
}
|
|
||||||
_vm->decodeBGImage(resource, resourceLength, &_mainPanel.image,
|
_vm->decodeBGImage(resource, resourceLength, &_mainPanel.image,
|
||||||
&_mainPanel.imageLength, &_mainPanel.imageWidth, &_mainPanel.imageHeight);
|
&_mainPanel.imageLength, &_mainPanel.imageWidth, &_mainPanel.imageHeight);
|
||||||
|
|
||||||
RSC_FreeResource(resource);
|
free(resource);
|
||||||
|
|
||||||
_conversePanel.buttons = _vm->getDisplayInfo().conversePanelButtons;
|
_conversePanel.buttons = _vm->getDisplayInfo().conversePanelButtons;
|
||||||
_conversePanel.buttonsCount = _vm->getDisplayInfo().conversePanelButtonsCount;
|
_conversePanel.buttonsCount = _vm->getDisplayInfo().conversePanelButtonsCount;
|
||||||
|
|
||||||
result = RSC_LoadResource(_interfaceContext, _vm->getResourceDescription()->conversePanelResourceId, &resource, &resourceLength);
|
_vm->_resource->loadResource(_interfaceContext, _vm->getResourceDescription()->conversePanelResourceId, resource, resourceLength);
|
||||||
if ((result != SUCCESS) || (resourceLength == 0)) {
|
|
||||||
error("Interface::Interface unable to load conversePanel resource");
|
|
||||||
}
|
|
||||||
_vm->decodeBGImage(resource, resourceLength, &_conversePanel.image,
|
_vm->decodeBGImage(resource, resourceLength, &_conversePanel.image,
|
||||||
&_conversePanel.imageLength, &_conversePanel.imageWidth, &_conversePanel.imageHeight);
|
&_conversePanel.imageLength, &_conversePanel.imageWidth, &_conversePanel.imageHeight);
|
||||||
RSC_FreeResource(resource);
|
free(resource);
|
||||||
|
|
||||||
_optionPanel.buttons = _vm->getDisplayInfo().optionPanelButtons;
|
_optionPanel.buttons = _vm->getDisplayInfo().optionPanelButtons;
|
||||||
_optionPanel.buttonsCount = _vm->getDisplayInfo().optionPanelButtonsCount;
|
_optionPanel.buttonsCount = _vm->getDisplayInfo().optionPanelButtonsCount;
|
||||||
|
|
||||||
result = RSC_LoadResource(_interfaceContext, _vm->getResourceDescription()->optionPanelResourceId, &resource, &resourceLength);
|
_vm->_resource->loadResource(_interfaceContext, _vm->getResourceDescription()->optionPanelResourceId, resource, resourceLength);
|
||||||
if ((result != SUCCESS) || (resourceLength == 0)) {
|
|
||||||
error("Interface::Interface unable to load optionPanel resource");
|
|
||||||
}
|
|
||||||
_vm->decodeBGImage(resource, resourceLength, &_optionPanel.image,
|
_vm->decodeBGImage(resource, resourceLength, &_optionPanel.image,
|
||||||
&_optionPanel.imageLength, &_optionPanel.imageWidth, &_optionPanel.imageHeight);
|
&_optionPanel.imageLength, &_optionPanel.imageWidth, &_optionPanel.imageHeight);
|
||||||
RSC_FreeResource(resource);
|
free(resource);
|
||||||
|
|
||||||
|
|
||||||
if (_vm->_sprite->loadList(_vm->getResourceDescription()->mainPanelSpritesResourceId, _mainPanel.sprites) != SUCCESS) {
|
_vm->_sprite->loadList(_vm->getResourceDescription()->mainPanelSpritesResourceId, _mainPanel.sprites);
|
||||||
error("Interface::Interface(): Unable to load sprite list");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_vm->getGameType() == GType_ITE) {
|
if (_vm->getGameType() == GType_ITE) {
|
||||||
if (_vm->_sprite->loadList(_vm->getResourceDescription()->defaultPortraitsResourceId, _defPortraits) != SUCCESS) {
|
_vm->_sprite->loadList(_vm->getResourceDescription()->defaultPortraitsResourceId, _defPortraits);
|
||||||
error("Interface::Interface(): Unable to load sprite list");
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
|
@ -212,8 +195,6 @@ Interface::Interface(SagaEngine *vm) : _vm(vm), _initialized(false) {
|
||||||
_textInput = false;
|
_textInput = false;
|
||||||
_statusTextInput = false;
|
_statusTextInput = false;
|
||||||
_statusTextInputState = kStatusTextInputFirstRun;
|
_statusTextInputState = kStatusTextInputFirstRun;
|
||||||
|
|
||||||
_initialized = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Interface::~Interface(void) {
|
Interface::~Interface(void) {
|
||||||
|
@ -222,7 +203,6 @@ Interface::~Interface(void) {
|
||||||
_mainPanel.sprites.freeMem();
|
_mainPanel.sprites.freeMem();
|
||||||
_defPortraits.freeMem();
|
_defPortraits.freeMem();
|
||||||
_scenePortraits.freeMem();
|
_scenePortraits.freeMem();
|
||||||
_initialized = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int Interface::activate() {
|
int Interface::activate() {
|
||||||
|
@ -505,10 +485,10 @@ void Interface::setStatusText(const char *text, int statusColor) {
|
||||||
drawStatusBar();
|
drawStatusBar();
|
||||||
}
|
}
|
||||||
|
|
||||||
int Interface::loadScenePortraits(int resourceId) {
|
void Interface::loadScenePortraits(int resourceId) {
|
||||||
_scenePortraits.freeMem();
|
_scenePortraits.freeMem();
|
||||||
|
|
||||||
return _vm->_sprite->loadList(resourceId, _scenePortraits);
|
_vm->_sprite->loadList(resourceId, _scenePortraits);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interface::drawVerbPanel(Surface *backBuffer, PanelButton* panelButton) {
|
void Interface::drawVerbPanel(Surface *backBuffer, PanelButton* panelButton) {
|
||||||
|
@ -2037,7 +2017,6 @@ void Interface::mapPanelShow() {
|
||||||
Rect rect;
|
Rect rect;
|
||||||
byte *image;
|
byte *image;
|
||||||
int imageWidth, imageHeight;
|
int imageWidth, imageHeight;
|
||||||
int result;
|
|
||||||
const byte *pal;
|
const byte *pal;
|
||||||
PalEntry cPal[PAL_ENTRIES];
|
PalEntry cPal[PAL_ENTRIES];
|
||||||
|
|
||||||
|
@ -2047,9 +2026,9 @@ void Interface::mapPanelShow() {
|
||||||
|
|
||||||
rect.left = rect.top = 0;
|
rect.left = rect.top = 0;
|
||||||
|
|
||||||
result = RSC_LoadResource(_interfaceContext, RID_ITE_TYCHO_MAP, &resource, &resourceLength);
|
_vm->_resource->loadResource(_interfaceContext, RID_ITE_TYCHO_MAP, resource, resourceLength);
|
||||||
if ((result != SUCCESS) || (resourceLength == 0)) {
|
if (resourceLength == 0) {
|
||||||
error("Interface::mapPanelShow(): unable to load Tycho map resource");
|
error("Interface::mapPanelShow() unable to load Tycho map resource");
|
||||||
}
|
}
|
||||||
|
|
||||||
_vm->_gfx->getCurrentPal(_mapSavedPal);
|
_vm->_gfx->getCurrentPal(_mapSavedPal);
|
||||||
|
@ -2083,7 +2062,7 @@ void Interface::mapPanelShow() {
|
||||||
_vm->_system->delayMillis(5);
|
_vm->_system->delayMillis(5);
|
||||||
}
|
}
|
||||||
|
|
||||||
RSC_FreeResource(resource);
|
free(resource);
|
||||||
free(image);
|
free(image);
|
||||||
|
|
||||||
setSaveReminderState(false);
|
setSaveReminderState(false);
|
||||||
|
|
|
@ -209,7 +209,7 @@ public:
|
||||||
void restoreMode();
|
void restoreMode();
|
||||||
bool isInMainMode() { return _inMainMode; }
|
bool isInMainMode() { return _inMainMode; }
|
||||||
void setStatusText(const char *text, int statusColor = -1);
|
void setStatusText(const char *text, int statusColor = -1);
|
||||||
int loadScenePortraits(int resourceId);
|
void loadScenePortraits(int resourceId);
|
||||||
void setLeftPortrait(int portrait) {
|
void setLeftPortrait(int portrait) {
|
||||||
_leftPortrait = portrait;
|
_leftPortrait = portrait;
|
||||||
draw();
|
draw();
|
||||||
|
@ -376,8 +376,7 @@ private:
|
||||||
private:
|
private:
|
||||||
SagaEngine *_vm;
|
SagaEngine *_vm;
|
||||||
|
|
||||||
bool _initialized;
|
ResourceContext *_interfaceContext;
|
||||||
RSCFILE_CONTEXT *_interfaceContext;
|
|
||||||
InterfacePanel _mainPanel;
|
InterfacePanel _mainPanel;
|
||||||
PanelButton *_inventoryUpButton;
|
PanelButton *_inventoryUpButton;
|
||||||
PanelButton *_inventoryDownButton;
|
PanelButton *_inventoryDownButton;
|
||||||
|
|
|
@ -114,7 +114,7 @@ void IsoMap::loadImages(const byte *resourcePointer, size_t resourceLength) {
|
||||||
_tileDataLength = resourceLength;
|
_tileDataLength = resourceLength;
|
||||||
memcpy(_tileData, resourcePointer, resourceLength);
|
memcpy(_tileData, resourcePointer, resourceLength);
|
||||||
|
|
||||||
MemoryReadStreamEndian readS(_tileData, _tileDataLength, IS_BIG_ENDIAN);
|
MemoryReadStreamEndian readS(_tileData, _tileDataLength, _vm->isBigEndian());
|
||||||
readS.readUint16(); // skip
|
readS.readUint16(); // skip
|
||||||
_tilesCount = readS.readUint16();
|
_tilesCount = readS.readUint16();
|
||||||
_tilesCount = _tilesCount / SAGA_ISOTILEDATA_LEN;
|
_tilesCount = _tilesCount / SAGA_ISOTILEDATA_LEN;
|
||||||
|
@ -146,7 +146,7 @@ void IsoMap::loadPlatforms(const byte * resourcePointer, size_t resourceLength)
|
||||||
error("IsoMap::loadPlatforms wrong resourceLength");
|
error("IsoMap::loadPlatforms wrong resourceLength");
|
||||||
}
|
}
|
||||||
|
|
||||||
MemoryReadStreamEndian readS(resourcePointer, resourceLength, IS_BIG_ENDIAN);
|
MemoryReadStreamEndian readS(resourcePointer, resourceLength, _vm->isBigEndian());
|
||||||
|
|
||||||
_tilePlatformsCount = resourceLength / SAGA_TILEPLATFORMDATA_LEN;
|
_tilePlatformsCount = resourceLength / SAGA_TILEPLATFORMDATA_LEN;
|
||||||
_tilePlatformList = (TilePlatformData *)malloc(_tilePlatformsCount * sizeof(*_tilePlatformList));
|
_tilePlatformList = (TilePlatformData *)malloc(_tilePlatformsCount * sizeof(*_tilePlatformList));
|
||||||
|
@ -177,7 +177,7 @@ void IsoMap::loadMap(const byte * resourcePointer, size_t resourceLength) {
|
||||||
error("IsoMap::loadMap wrong resourceLength");
|
error("IsoMap::loadMap wrong resourceLength");
|
||||||
}
|
}
|
||||||
|
|
||||||
MemoryReadStreamEndian readS(resourcePointer, resourceLength, IS_BIG_ENDIAN);
|
MemoryReadStreamEndian readS(resourcePointer, resourceLength, _vm->isBigEndian());
|
||||||
_tileMap.edgeType = readS.readByte();
|
_tileMap.edgeType = readS.readByte();
|
||||||
readS.readByte(); //skip
|
readS.readByte(); //skip
|
||||||
|
|
||||||
|
@ -197,7 +197,7 @@ void IsoMap::loadMetaTiles(const byte * resourcePointer, size_t resourceLength)
|
||||||
error("IsoMap::loadMetaTiles wrong resourceLength");
|
error("IsoMap::loadMetaTiles wrong resourceLength");
|
||||||
}
|
}
|
||||||
|
|
||||||
MemoryReadStreamEndian readS(resourcePointer, resourceLength, IS_BIG_ENDIAN);
|
MemoryReadStreamEndian readS(resourcePointer, resourceLength, _vm->isBigEndian());
|
||||||
_metaTilesCount = resourceLength / SAGA_METATILEDATA_LEN;
|
_metaTilesCount = resourceLength / SAGA_METATILEDATA_LEN;
|
||||||
|
|
||||||
_metaTileList = (MetaTileData *)malloc(_metaTilesCount * sizeof(*_metaTileList));
|
_metaTileList = (MetaTileData *)malloc(_metaTilesCount * sizeof(*_metaTileList));
|
||||||
|
@ -224,7 +224,7 @@ void IsoMap::loadMulti(const byte * resourcePointer, size_t resourceLength) {
|
||||||
error("IsoMap::loadMetaTiles wrong resourceLength");
|
error("IsoMap::loadMetaTiles wrong resourceLength");
|
||||||
}
|
}
|
||||||
|
|
||||||
MemoryReadStreamEndian readS(resourcePointer, resourceLength, IS_BIG_ENDIAN);
|
MemoryReadStreamEndian readS(resourcePointer, resourceLength, _vm->isBigEndian());
|
||||||
_multiCount = readS.readUint16();
|
_multiCount = readS.readUint16();
|
||||||
_multiTable = (MultiTileEntryData *)malloc(_multiCount * sizeof(*_multiTable));
|
_multiTable = (MultiTileEntryData *)malloc(_multiCount * sizeof(*_multiTable));
|
||||||
if (_multiTable == NULL) {
|
if (_multiTable == NULL) {
|
||||||
|
|
|
@ -30,12 +30,13 @@
|
||||||
#include "saga/animation.h"
|
#include "saga/animation.h"
|
||||||
#include "saga/events.h"
|
#include "saga/events.h"
|
||||||
#include "saga/font.h"
|
#include "saga/font.h"
|
||||||
#include "saga/rscfile_mod.h"
|
|
||||||
#include "saga/sndres.h"
|
#include "saga/sndres.h"
|
||||||
#include "saga/palanim.h"
|
#include "saga/palanim.h"
|
||||||
#include "saga/music.h"
|
#include "saga/music.h"
|
||||||
|
|
||||||
#include "saga/scene.h"
|
#include "saga/scene.h"
|
||||||
|
#include "saga/resnames.h"
|
||||||
|
#include "saga/rscfile.h"
|
||||||
|
|
||||||
namespace Saga {
|
namespace Saga {
|
||||||
|
|
||||||
|
@ -56,17 +57,17 @@ LoadSceneParams ITE_IntroList[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
int Scene::ITEStartProc() {
|
int Scene::ITEStartProc() {
|
||||||
size_t n_introscenes;
|
size_t scenesCount;
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
LoadSceneParams firstScene;
|
LoadSceneParams firstScene;
|
||||||
LoadSceneParams tempScene;
|
LoadSceneParams tempScene;
|
||||||
|
|
||||||
n_introscenes = ARRAYSIZE(ITE_IntroList);
|
scenesCount = ARRAYSIZE(ITE_IntroList);
|
||||||
|
|
||||||
for (i = 0; i < n_introscenes; i++) {
|
for (i = 0; i < scenesCount; i++) {
|
||||||
tempScene = ITE_IntroList[i];
|
tempScene = ITE_IntroList[i];
|
||||||
tempScene.sceneDescriptor = RSC_ConvertID(tempScene.sceneDescriptor);
|
tempScene.sceneDescriptor = _vm->_resource->convertResourceId(tempScene.sceneDescriptor);
|
||||||
_vm->_scene->queueScene(&tempScene);
|
_vm->_scene->queueScene(&tempScene);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,8 +95,11 @@ EVENT *Scene::ITEQueueDialogue(EVENT *q_event, int n_dialogues, const INTRO_DIAL
|
||||||
// Queue narrator dialogue list
|
// Queue narrator dialogue list
|
||||||
textEntry.color = 255;
|
textEntry.color = 255;
|
||||||
textEntry.effectColor = 0;
|
textEntry.effectColor = 0;
|
||||||
textEntry.point.x = 320 / 2;
|
textEntry.useRect = true;
|
||||||
textEntry.point.y = (_vm->getFeatures() & GF_LANG_DE) ? INTRO_DE_CAPTION_Y : INTRO_CAPTION_Y;
|
textEntry.rect.left = 0;
|
||||||
|
textEntry.rect.right = _vm->getDisplayWidth();
|
||||||
|
textEntry.rect.top = (_vm->getFeatures() & GF_LANG_DE) ? INTRO_DE_CAPTION_Y : INTRO_CAPTION_Y;
|
||||||
|
textEntry.rect.bottom = _vm->getDisplayHeight();
|
||||||
textEntry.fontId = kMediumFont;
|
textEntry.fontId = kMediumFont;
|
||||||
textEntry.flags = (FontEffectFlags)(kFontOutline | kFontCentered);
|
textEntry.flags = (FontEffectFlags)(kFontOutline | kFontCentered);
|
||||||
|
|
||||||
|
@ -754,7 +758,7 @@ int Scene::ITEIntroValleyProc(int param) {
|
||||||
event.type = ONESHOT_EVENT;
|
event.type = ONESHOT_EVENT;
|
||||||
event.code = MUSIC_EVENT;
|
event.code = MUSIC_EVENT;
|
||||||
event.param = MUSIC_2;
|
event.param = MUSIC_2;
|
||||||
event.param2 = 0;
|
event.param2 = MUSIC_NORMAL;
|
||||||
event.op = EVENT_PLAY;
|
event.op = EVENT_PLAY;
|
||||||
event.time = 0;
|
event.time = 0;
|
||||||
|
|
||||||
|
|
340
saga/music.cpp
340
saga/music.cpp
|
@ -22,8 +22,8 @@
|
||||||
*/
|
*/
|
||||||
#include "saga/saga.h"
|
#include "saga/saga.h"
|
||||||
|
|
||||||
|
#include "saga/rscfile.h"
|
||||||
#include "saga/music.h"
|
#include "saga/music.h"
|
||||||
#include "saga/rscfile_mod.h"
|
|
||||||
#include "saga/stream.h"
|
#include "saga/stream.h"
|
||||||
#include "sound/audiostream.h"
|
#include "sound/audiostream.h"
|
||||||
#include "sound/mididrv.h"
|
#include "sound/mididrv.h"
|
||||||
|
@ -42,10 +42,11 @@ namespace Saga {
|
||||||
|
|
||||||
class RAWInputStream : public AudioStream {
|
class RAWInputStream : public AudioStream {
|
||||||
private:
|
private:
|
||||||
|
ResourceContext *_context;
|
||||||
Common::File *_file;
|
Common::File *_file;
|
||||||
uint32 _file_pos;
|
uint32 _filePos;
|
||||||
uint32 _start_pos;
|
uint32 _startPos;
|
||||||
uint32 _end_pos;
|
uint32 _endPos;
|
||||||
bool _finished;
|
bool _finished;
|
||||||
bool _looping;
|
bool _looping;
|
||||||
int16 _buf[BUFFER_SIZE];
|
int16 _buf[BUFFER_SIZE];
|
||||||
|
@ -53,11 +54,12 @@ private:
|
||||||
const int16 *_pos;
|
const int16 *_pos;
|
||||||
|
|
||||||
void refill();
|
void refill();
|
||||||
inline bool eosIntern() const;
|
bool eosIntern() const {
|
||||||
|
return _pos >= _bufferEnd;
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
RAWInputStream(Common::File *file, int size, bool looping);
|
RAWInputStream(SagaEngine *vm, ResourceContext *context, uint32 resourceId, bool looping);
|
||||||
~RAWInputStream();
|
|
||||||
|
|
||||||
int readBuffer(int16 *buffer, const int numSamples);
|
int readBuffer(int16 *buffer, const int numSamples);
|
||||||
|
|
||||||
|
@ -66,28 +68,23 @@ public:
|
||||||
int getRate() const { return 11025; }
|
int getRate() const { return 11025; }
|
||||||
};
|
};
|
||||||
|
|
||||||
RAWInputStream::RAWInputStream(Common::File *file, int size, bool looping)
|
RAWInputStream::RAWInputStream(SagaEngine *vm, ResourceContext *context, uint32 resourceId, bool looping)
|
||||||
: _file(file), _finished(false), _looping(looping),
|
: _context(context), _finished(false), _looping(looping), _bufferEnd(_buf + BUFFER_SIZE) {
|
||||||
_bufferEnd(_buf + BUFFER_SIZE) {
|
|
||||||
|
ResourceData * resourceData;
|
||||||
|
|
||||||
_file->incRef();
|
resourceData = vm->_resource->getResourceData(context, resourceId);
|
||||||
|
_file = context->getFile(resourceData);
|
||||||
|
|
||||||
// Determine the end position
|
// Determine the end position
|
||||||
_file_pos = _file->pos();
|
_startPos = resourceData->offset;
|
||||||
_start_pos = _file_pos;
|
_endPos = _startPos + resourceData->size;
|
||||||
_end_pos = _file_pos + size;
|
_filePos = _startPos;
|
||||||
|
|
||||||
// Read in initial data
|
// Read in initial data
|
||||||
refill();
|
refill();
|
||||||
}
|
}
|
||||||
|
|
||||||
RAWInputStream::~RAWInputStream() {
|
|
||||||
_file->decRef();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool RAWInputStream::eosIntern() const {
|
|
||||||
return _pos >= _bufferEnd;
|
|
||||||
}
|
|
||||||
|
|
||||||
int RAWInputStream::readBuffer(int16 *buffer, const int numSamples) {
|
int RAWInputStream::readBuffer(int16 *buffer, const int numSamples) {
|
||||||
int samples = 0;
|
int samples = 0;
|
||||||
|
@ -108,61 +105,47 @@ void RAWInputStream::refill() {
|
||||||
if (_finished)
|
if (_finished)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
uint32 len_left;
|
uint32 lengthLeft;
|
||||||
byte *ptr = (byte *) _buf;
|
byte *ptr = (byte *) _buf;
|
||||||
|
|
||||||
|
|
||||||
_file->seek(_file_pos, SEEK_SET);
|
_file->seek(_filePos, SEEK_SET);
|
||||||
|
|
||||||
if (_looping)
|
if (_looping)
|
||||||
len_left = 2 * BUFFER_SIZE;
|
lengthLeft = 2 * BUFFER_SIZE;
|
||||||
else
|
else
|
||||||
len_left = MIN((uint32) (2 * BUFFER_SIZE), _end_pos - _file_pos);
|
lengthLeft = MIN((uint32) (2 * BUFFER_SIZE), _endPos - _filePos);
|
||||||
|
|
||||||
while (len_left > 0) {
|
while (lengthLeft > 0) {
|
||||||
uint32 len = _file->read(ptr, MIN(len_left, _end_pos - _file->pos()));
|
uint32 len = _file->read(ptr, MIN(lengthLeft, _endPos - _file->pos()));
|
||||||
|
|
||||||
if (len & 1)
|
if (len & 1)
|
||||||
len--;
|
len--;
|
||||||
|
|
||||||
if (_vm->getFeatures() & GF_BIG_ENDIAN_DATA) {
|
if (_context->isBigEndian) {
|
||||||
uint16 *ptr16 = (uint16 *)ptr;
|
uint16 *ptr16 = (uint16 *)ptr;
|
||||||
for (uint32 i = 0; i < (len / 2); i++)
|
for (uint32 i = 0; i < (len / 2); i++)
|
||||||
ptr16[i] = TO_BE_16(ptr16[i]);
|
ptr16[i] = TO_BE_16(ptr16[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
len_left -= len;
|
lengthLeft -= len;
|
||||||
ptr += len;
|
ptr += len;
|
||||||
|
|
||||||
if (len_left > 0)
|
if (lengthLeft > 0)
|
||||||
_file->seek(_start_pos);
|
_file->seek(_startPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
_file_pos = _file->pos();
|
_filePos = _file->pos();
|
||||||
_pos = _buf;
|
_pos = _buf;
|
||||||
_bufferEnd = (int16 *)ptr;
|
_bufferEnd = (int16 *)ptr;
|
||||||
|
|
||||||
if (!_looping && _file_pos >= _end_pos)
|
if (!_looping && _filePos >= _endPos) {
|
||||||
_finished = true;
|
_finished = true;
|
||||||
}
|
|
||||||
|
|
||||||
AudioStream *makeRAWStream(const char *filename, uint32 pos, int size, bool looping) {
|
|
||||||
Common::File *file = new Common::File();
|
|
||||||
|
|
||||||
if (!file->open(filename)) {
|
|
||||||
delete file;
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
file->seek(pos);
|
|
||||||
|
|
||||||
AudioStream *audioStream = new RAWInputStream(file, size, looping);
|
|
||||||
|
|
||||||
file->decRef();
|
|
||||||
return audioStream;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MusicPlayer::MusicPlayer(MidiDriver *driver) : _parser(0), _driver(driver), _looping(false), _isPlaying(false), _passThrough(false), _isGM(false) {
|
|
||||||
|
MusicPlayer::MusicPlayer(MidiDriver *driver) : _parser(0), _driver(driver), _looping(false), _isPlaying(false), _passThrough(false), _isGM(false) {
|
||||||
memset(_channel, 0, sizeof(_channel));
|
memset(_channel, 0, sizeof(_channel));
|
||||||
_masterVolume = 0;
|
_masterVolume = 0;
|
||||||
this->open();
|
this->open();
|
||||||
|
@ -274,19 +257,20 @@ void MusicPlayer::stopMusic() {
|
||||||
_isPlaying = false;
|
_isPlaying = false;
|
||||||
if (_parser) {
|
if (_parser) {
|
||||||
_parser->unloadMusic();
|
_parser->unloadMusic();
|
||||||
delete _parser;
|
|
||||||
_parser = NULL;
|
_parser = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Music::Music(Audio::Mixer *mixer, MidiDriver *driver, int enabled) : _mixer(mixer), _enabled(enabled), _adlib(false) {
|
Music::Music(SagaEngine *vm, Audio::Mixer *mixer, MidiDriver *driver, int enabled) : _vm(vm), _mixer(mixer), _enabled(enabled), _adlib(false) {
|
||||||
_player = new MusicPlayer(driver);
|
_player = new MusicPlayer(driver);
|
||||||
_musicInitialized = 1;
|
|
||||||
_currentVolume = 0;
|
_currentVolume = 0;
|
||||||
|
|
||||||
|
xmidiParser = MidiParser::createParser_XMIDI();
|
||||||
|
smfParser = MidiParser::createParser_SMF();
|
||||||
|
|
||||||
if (_vm->getGameType() == GType_ITE) {
|
if (_vm->getGameType() == GType_ITE) {
|
||||||
Common::File file;
|
Common::File file;
|
||||||
byte footerBuf[ARRAYSIZE(_digiTableITECD) * 8];
|
// byte footerBuf[ARRAYSIZE(_digiTableITECD) * 8];
|
||||||
|
|
||||||
// The lookup table is stored at the end of music.rsc. I don't
|
// The lookup table is stored at the end of music.rsc. I don't
|
||||||
// know why it has 27 elements, but the last one represents a
|
// know why it has 27 elements, but the last one represents a
|
||||||
|
@ -300,40 +284,19 @@ Music::Music(Audio::Mixer *mixer, MidiDriver *driver, int enabled) : _mixer(mixe
|
||||||
// Proper approach would be to extend resource manager so it could
|
// Proper approach would be to extend resource manager so it could
|
||||||
// return File object.
|
// return File object.
|
||||||
|
|
||||||
_musicContext = _vm->getFileContext(GAME_MUSICFILE, 0);
|
_musicContext = _vm->_resource->getContext(GAME_MUSICFILE);
|
||||||
if (_musicContext != NULL) {
|
if (_musicContext != NULL) {
|
||||||
_hasDigiMusic = true;
|
|
||||||
|
|
||||||
_musicFname = RSC_FileName(_musicContext);
|
|
||||||
|
|
||||||
file.open(_musicFname);
|
|
||||||
assert(file.size() > sizeof(footerBuf));
|
|
||||||
|
|
||||||
file.seek(-ARRAYSIZE(_digiTableITECD) * 8, SEEK_END);
|
|
||||||
file.read(footerBuf, sizeof(footerBuf));
|
|
||||||
|
|
||||||
MemoryReadStreamEndian readS(footerBuf, sizeof(footerBuf), IS_BIG_ENDIAN);
|
|
||||||
|
|
||||||
|
|
||||||
for (int i = 0; i < ARRAYSIZE(_digiTableITECD); i++) {
|
|
||||||
_digiTableITECD[i].start = readS.readUint32();
|
|
||||||
_digiTableITECD[i].length = readS.readUint32();
|
|
||||||
}
|
|
||||||
|
|
||||||
file.close();
|
|
||||||
|
|
||||||
// The "birdchrp" is just a short, high-pitched
|
// The "birdchrp" is just a short, high-pitched
|
||||||
// whining. Use the MIDI/XMIDI version instead.
|
// whining. Use the MIDI/XMIDI version instead.
|
||||||
_digiTableITECD[6].length = 0;
|
///_digiTableITECD[6].length = 0;
|
||||||
} else {
|
|
||||||
_hasDigiMusic = false;
|
|
||||||
memset(_digiTableITECD, 0, sizeof(_digiTableITECD));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Music::~Music() {
|
Music::~Music() {
|
||||||
delete _player;
|
delete _player;
|
||||||
|
delete xmidiParser;
|
||||||
|
delete smfParser;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Music::musicVolumeGaugeCallback(void *refCon) {
|
void Music::musicVolumeGaugeCallback(void *refCon) {
|
||||||
|
@ -389,207 +352,140 @@ bool Music::isPlaying() {
|
||||||
//
|
//
|
||||||
// reset.mid seems to be unused.
|
// reset.mid seems to be unused.
|
||||||
|
|
||||||
const MUSIC_MIDITABLE Music::_midiTableITECD[26] = {
|
|
||||||
{ "cave.mid", MUSIC_LOOP }, // 9
|
|
||||||
{ "intro.mid", MUSIC_LOOP }, // 10
|
|
||||||
{ "fvillage.mid", MUSIC_LOOP }, // 11
|
|
||||||
{ "elkhall.mid", MUSIC_LOOP }, // 12
|
|
||||||
{ "mouse.mid", 0 }, // 13
|
|
||||||
{ "darkclaw.mid", MUSIC_LOOP }, // 14
|
|
||||||
{ "birdchrp.mid", MUSIC_LOOP }, // 15
|
|
||||||
{ "orbtempl.mid", MUSIC_LOOP }, // 16
|
|
||||||
{ "spooky.mid", MUSIC_LOOP }, // 17
|
|
||||||
{ "catfest.mid", MUSIC_LOOP }, // 18
|
|
||||||
{ "elkfanfare.mid", 0 }, // 19
|
|
||||||
{ "bcexpl.mid", MUSIC_LOOP }, // 20
|
|
||||||
{ "boargtnt.mid", MUSIC_LOOP }, // 21
|
|
||||||
{ "boarking.mid", MUSIC_LOOP }, // 22
|
|
||||||
{ "explorea.mid", MUSIC_LOOP }, // 23
|
|
||||||
{ "exploreb.mid", MUSIC_LOOP }, // 24
|
|
||||||
{ "explorec.mid", MUSIC_LOOP }, // 25
|
|
||||||
{ "sunstatm.mid", MUSIC_LOOP }, // 26
|
|
||||||
{ "nitstrlm.mid", MUSIC_LOOP }, // 27
|
|
||||||
{ "humruinm.mid", MUSIC_LOOP }, // 28
|
|
||||||
{ "damexplm.mid", MUSIC_LOOP }, // 29
|
|
||||||
{ "tychom.mid", MUSIC_LOOP }, // 30
|
|
||||||
{ "kitten.mid", MUSIC_LOOP }, // 31
|
|
||||||
{ "sweet.mid", MUSIC_LOOP }, // 32
|
|
||||||
{ "brutalmt.mid", MUSIC_LOOP }, // 33
|
|
||||||
{ "shiala.mid", MUSIC_LOOP } // 34
|
|
||||||
};
|
|
||||||
|
|
||||||
int Music::play(uint32 music_rn, uint16 flags) {
|
void Music::play(uint32 resourceId, MusicFlags flags) {
|
||||||
RSCFILE_CONTEXT *rsc_ctxt = NULL;
|
AudioStream *audioStream = NULL;
|
||||||
|
MidiParser *parser;
|
||||||
byte *resource_data;
|
ResourceContext *context;
|
||||||
size_t resource_size;
|
byte *resourceData;
|
||||||
|
size_t resourceSize;
|
||||||
if (!_musicInitialized) {
|
debug(2, "Music::play %d, %d", resourceId, flags);
|
||||||
return FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!_enabled) {
|
if (!_enabled) {
|
||||||
return SUCCESS;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isPlaying() && _trackNumber == music_rn) {
|
if (isPlaying() && _trackNumber == resourceId) {
|
||||||
return SUCCESS;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_trackNumber = music_rn;
|
_trackNumber = resourceId;
|
||||||
|
|
||||||
_player->stopMusic();
|
_player->stopMusic();
|
||||||
|
|
||||||
_mixer->stopHandle(_musicHandle);
|
_mixer->stopHandle(_musicHandle);
|
||||||
|
|
||||||
AudioStream *audioStream = NULL;
|
|
||||||
MidiParser *parser;
|
|
||||||
Common::File midiFile;
|
|
||||||
|
|
||||||
if (_vm->getGameType() == GType_ITE) {
|
if (_vm->getGameType() == GType_ITE) {
|
||||||
if (music_rn >= 9 && music_rn <= 34) {
|
|
||||||
|
if (resourceId >= 9 && resourceId <= 34) {
|
||||||
if (flags == MUSIC_DEFAULT) {
|
if (flags == MUSIC_DEFAULT) {
|
||||||
flags = _midiTableITECD[music_rn - 9].flags;
|
if ((resourceId == 13) || (resourceId == 19)) {
|
||||||
}
|
flags = MUSIC_NORMAL;
|
||||||
|
} else {
|
||||||
if (_hasDigiMusic) {
|
flags = MUSIC_LOOP;
|
||||||
uint32 start = _digiTableITECD[music_rn - 9].start;
|
|
||||||
uint32 length = _digiTableITECD[music_rn - 9].length;
|
|
||||||
|
|
||||||
if (length > 0) {
|
|
||||||
audioStream = makeRAWStream(_musicFname, start, length, flags == MUSIC_LOOP);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// No digitized music - try standalone MIDI.
|
|
||||||
if (!audioStream) {
|
|
||||||
midiFile.open(_midiTableITECD[music_rn - 9].filename);
|
|
||||||
|
|
||||||
if (!midiFile.isOpen()) {
|
if (_musicContext != NULL) {
|
||||||
debug(2, "Cannot open music file %s", _midiTableITECD[music_rn - 9].filename);
|
//TODO: check resource size
|
||||||
}
|
audioStream = new RAWInputStream(_vm, _musicContext, resourceId, flags == MUSIC_LOOP);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags == MUSIC_DEFAULT) {
|
|
||||||
flags = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (audioStream) {
|
if (audioStream) {
|
||||||
debug(2, "Playing digitized music");
|
debug(2, "Playing digitized music");
|
||||||
_mixer->playInputStream(Audio::Mixer::kMusicSoundType, &_musicHandle, audioStream);
|
_mixer->playInputStream(Audio::Mixer::kMusicSoundType, &_musicHandle, audioStream);
|
||||||
return SUCCESS;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags == MUSIC_DEFAULT) {
|
||||||
|
flags = MUSIC_NORMAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: Is resource_data ever freed?
|
// FIXME: Is resource_data ever freed?
|
||||||
|
// Load MIDI/XMI resource data
|
||||||
|
|
||||||
if (midiFile.isOpen()) {
|
if (_vm->getGameType() == GType_ITE) {
|
||||||
debug(2, "Using external MIDI file: %s", midiFile.name());
|
context = _vm->_resource->getContext(GAME_RESOURCEFILE);
|
||||||
resource_size = midiFile.size();
|
|
||||||
resource_data = (byte *) malloc(resource_size);
|
|
||||||
midiFile.read(resource_data, resource_size);
|
|
||||||
midiFile.close();
|
|
||||||
|
|
||||||
_player->setGM(true);
|
|
||||||
parser = MidiParser::createParser_SMF();
|
|
||||||
} else {
|
} else {
|
||||||
// Load MIDI/XMI resource data
|
// I've listened to music from both the FM and the GM
|
||||||
|
// file, and I've tentatively reached the conclusion
|
||||||
|
// that they are both General MIDI. My guess is that
|
||||||
|
// the FM file has been reorchestrated to sound better
|
||||||
|
// on Adlib and other FM synths.
|
||||||
|
//
|
||||||
|
// Sev says the Adlib music does not sound like in the
|
||||||
|
// original, but I still think assuming General MIDI is
|
||||||
|
// the right thing to do. Some music, like the End
|
||||||
|
// Title (song 0) sound absolutely atrocious when piped
|
||||||
|
// through our MT-32 to GM mapping.
|
||||||
|
//
|
||||||
|
// It is, however, quite possible that the original
|
||||||
|
// used a different GM to FM mapping. If the original
|
||||||
|
// sounded markedly better, perhaps we should add some
|
||||||
|
// way of replacing our stock mapping in adlib.cpp?
|
||||||
|
//
|
||||||
|
// For the composer's own recording of the End Title,
|
||||||
|
// see http://www.johnottman.com/
|
||||||
|
|
||||||
if (_vm->getGameType() == GType_ITE) {
|
// Oddly enough, the intro music (song 1) is very
|
||||||
rsc_ctxt = _vm->getFileContext(GAME_RESOURCEFILE, 0);
|
// different in the two files. I have no idea why.
|
||||||
|
|
||||||
|
if (hasAdlib()) {
|
||||||
|
context = _vm->_resource->getContext(GAME_MUSICFILE_FM);
|
||||||
} else {
|
} else {
|
||||||
// I've listened to music from both the FM and the GM
|
context = _vm->_resource->getContext(GAME_MUSICFILE_GM);
|
||||||
// file, and I've tentatively reached the conclusion
|
|
||||||
// that they are both General MIDI. My guess is that
|
|
||||||
// the FM file has been reorchestrated to sound better
|
|
||||||
// on Adlib and other FM synths.
|
|
||||||
//
|
|
||||||
// Sev says the Adlib music does not sound like in the
|
|
||||||
// original, but I still think assuming General MIDI is
|
|
||||||
// the right thing to do. Some music, like the End
|
|
||||||
// Title (song 0) sound absolutely atrocious when piped
|
|
||||||
// through our MT-32 to GM mapping.
|
|
||||||
//
|
|
||||||
// It is, however, quite possible that the original
|
|
||||||
// used a different GM to FM mapping. If the original
|
|
||||||
// sounded markedly better, perhaps we should add some
|
|
||||||
// way of replacing our stock mapping in adlib.cpp?
|
|
||||||
//
|
|
||||||
// For the composer's own recording of the End Title,
|
|
||||||
// see http://www.johnottman.com/
|
|
||||||
|
|
||||||
// Oddly enough, the intro music (song 1) is very
|
|
||||||
// different in the two files. I have no idea why.
|
|
||||||
|
|
||||||
if (hasAdlib()) {
|
|
||||||
rsc_ctxt = _vm->getFileContext(GAME_MUSICFILE_FM, 0);
|
|
||||||
} else {
|
|
||||||
rsc_ctxt = _vm->getFileContext(GAME_MUSICFILE_GM, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
_player->setGM(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (RSC_LoadResource(rsc_ctxt, music_rn, &resource_data,
|
}
|
||||||
&resource_size) != SUCCESS) {
|
|
||||||
warning("Music::play(): Resource load failed: %u", music_rn);
|
_player->setGM(true);
|
||||||
return FAILURE;
|
|
||||||
|
_vm->_resource->loadResource(context, resourceId, resourceData, resourceSize);
|
||||||
|
|
||||||
|
if (resourceSize < 4) {
|
||||||
|
error("Music::play() wrong music resource size");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (xmidiParser->loadMusic(resourceData, resourceSize)) {
|
||||||
|
parser = xmidiParser;
|
||||||
|
} else {
|
||||||
|
if (smfParser->loadMusic(resourceData, resourceSize)) {
|
||||||
|
parser = smfParser;
|
||||||
|
} else {
|
||||||
|
error("Music::play() wrong music resource");
|
||||||
}
|
}
|
||||||
|
|
||||||
parser = MidiParser::createParser_XMIDI();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (resource_size <= 0) {
|
|
||||||
warning("Music::play(): Resource load failed: %u", music_rn);
|
|
||||||
return FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!parser->loadMusic(resource_data, resource_size)) {
|
|
||||||
warning("Error reading track!");
|
|
||||||
delete parser;
|
|
||||||
parser = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
debug(2, "Music::play(%d, %d)", music_rn, flags);
|
|
||||||
|
|
||||||
parser->setTrack(0);
|
parser->setTrack(0);
|
||||||
parser->setMidiDriver(_player);
|
parser->setMidiDriver(_player);
|
||||||
parser->setTimerRate(_player->getBaseTempo());
|
parser->setTimerRate(_player->getBaseTempo());
|
||||||
|
|
||||||
_player->_parser = parser;
|
_player->_parser = parser;
|
||||||
_player->setVolume(ConfMan.getInt("music_volume"));
|
_player->setVolume(ConfMan.getInt("music_volume"));
|
||||||
|
|
||||||
if (flags & MUSIC_LOOP)
|
if (flags & MUSIC_LOOP)
|
||||||
_player->setLoop(true);
|
_player->setLoop(true);
|
||||||
else
|
else
|
||||||
_player->setLoop(false);
|
_player->setLoop(false);
|
||||||
|
|
||||||
_player->playMusic();
|
_player->playMusic();
|
||||||
return SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int Music::pause(void) {
|
void Music::pause(void) {
|
||||||
if (!_musicInitialized) {
|
//TODO: do it
|
||||||
return FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int Music::resume(void) {
|
void Music::resume(void) {
|
||||||
if (!_musicInitialized) {
|
//TODO: do it}
|
||||||
return FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int Music::stop(void) {
|
void Music::stop(void) {
|
||||||
if (!_musicInitialized) {
|
//TODO: do it
|
||||||
return FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // End of namespace Saga
|
} // End of namespace Saga
|
||||||
|
|
37
saga/music.h
37
saga/music.h
|
@ -26,27 +26,18 @@
|
||||||
#ifndef SAGA_MUSIC_H_
|
#ifndef SAGA_MUSIC_H_
|
||||||
#define SAGA_MUSIC_H_
|
#define SAGA_MUSIC_H_
|
||||||
|
|
||||||
#include "saga/rscfile_mod.h"
|
|
||||||
#include "sound/mixer.h"
|
#include "sound/mixer.h"
|
||||||
#include "sound/mididrv.h"
|
#include "sound/mididrv.h"
|
||||||
#include "sound/midiparser.h"
|
#include "sound/midiparser.h"
|
||||||
|
|
||||||
namespace Saga {
|
namespace Saga {
|
||||||
enum MUSIC_FLAGS {
|
|
||||||
|
enum MusicFlags {
|
||||||
|
MUSIC_NORMAL = 0,
|
||||||
MUSIC_LOOP = 0x0001,
|
MUSIC_LOOP = 0x0001,
|
||||||
MUSIC_DEFAULT = 0xffff
|
MUSIC_DEFAULT = 0xffff
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MUSIC_MIDITABLE {
|
|
||||||
const char *filename;
|
|
||||||
int flags;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct MUSIC_DIGITABLE {
|
|
||||||
uint32 start;
|
|
||||||
uint32 length;
|
|
||||||
};
|
|
||||||
|
|
||||||
class MusicPlayer : public MidiDriver {
|
class MusicPlayer : public MidiDriver {
|
||||||
public:
|
public:
|
||||||
MusicPlayer(MidiDriver *driver);
|
MusicPlayer(MidiDriver *driver);
|
||||||
|
@ -106,7 +97,7 @@ protected:
|
||||||
class Music {
|
class Music {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Music(Audio::Mixer *mixer, MidiDriver *driver, int enabled);
|
Music(SagaEngine *vm, Audio::Mixer *mixer, MidiDriver *driver, int enabled);
|
||||||
~Music(void);
|
~Music(void);
|
||||||
void setNativeMT32(bool b) { _player->setNativeMT32(b); }
|
void setNativeMT32(bool b) { _player->setNativeMT32(b); }
|
||||||
bool hasNativeMT32() { return _player->hasNativeMT32(); }
|
bool hasNativeMT32() { return _player->hasNativeMT32(); }
|
||||||
|
@ -115,35 +106,31 @@ public:
|
||||||
void setPassThrough(bool b) { _player->setPassThrough(b); }
|
void setPassThrough(bool b) { _player->setPassThrough(b); }
|
||||||
bool isPlaying(void);
|
bool isPlaying(void);
|
||||||
|
|
||||||
int play(uint32 music_rn, uint16 flags = MUSIC_DEFAULT);
|
void play(uint32 resourceId, MusicFlags flags = MUSIC_DEFAULT);
|
||||||
int pause(void);
|
void pause(void);
|
||||||
int resume(void);
|
void resume(void);
|
||||||
int stop(void);
|
void stop(void);
|
||||||
|
|
||||||
void setVolume(int volume, int time);
|
void setVolume(int volume, int time);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
SagaEngine *_vm;
|
||||||
Audio::Mixer *_mixer;
|
Audio::Mixer *_mixer;
|
||||||
|
|
||||||
MusicPlayer *_player;
|
MusicPlayer *_player;
|
||||||
Audio::SoundHandle _musicHandle;
|
Audio::SoundHandle _musicHandle;
|
||||||
uint32 _trackNumber;
|
uint32 _trackNumber;
|
||||||
|
|
||||||
static const MUSIC_MIDITABLE _midiTableITECD[26];
|
|
||||||
MUSIC_DIGITABLE _digiTableITECD[27];
|
|
||||||
|
|
||||||
int _musicInitialized;
|
|
||||||
int _enabled;
|
int _enabled;
|
||||||
bool _hasDigiMusic;
|
|
||||||
bool _adlib;
|
bool _adlib;
|
||||||
|
|
||||||
int _targetVolume;
|
int _targetVolume;
|
||||||
int _currentVolume;
|
int _currentVolume;
|
||||||
int _currentVolumePercent;
|
int _currentVolumePercent;
|
||||||
|
|
||||||
RSCFILE_CONTEXT *_musicContext;
|
ResourceContext *_musicContext;
|
||||||
const char *_musicFname;
|
MidiParser *xmidiParser;
|
||||||
|
MidiParser *smfParser;
|
||||||
|
|
||||||
static void musicVolumeGaugeCallback(void *refCon);
|
static void musicVolumeGaugeCallback(void *refCon);
|
||||||
void musicVolumeGauge(void);
|
void musicVolumeGauge(void);
|
||||||
|
|
|
@ -132,7 +132,7 @@ bool HitZone::hitTest(const Point &testPoint) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void HitZone::draw(Surface *ds, int color) {
|
void HitZone::draw(SagaEngine *vm, Surface *ds, int color) {
|
||||||
int i, pointsCount, j;
|
int i, pointsCount, j;
|
||||||
Location location;
|
Location location;
|
||||||
HitZone::ClickArea *clickArea;
|
HitZone::ClickArea *clickArea;
|
||||||
|
@ -140,15 +140,14 @@ void HitZone::draw(Surface *ds, int color) {
|
||||||
for (i = 0; i < _clickAreasCount; i++) {
|
for (i = 0; i < _clickAreasCount; i++) {
|
||||||
clickArea = &_clickAreas[i];
|
clickArea = &_clickAreas[i];
|
||||||
pointsCount = clickArea->pointsCount;
|
pointsCount = clickArea->pointsCount;
|
||||||
if (_vm->_scene->getFlags() & kSceneFlagISO) {
|
if (vm->_scene->getFlags() & kSceneFlagISO) {
|
||||||
points = (Point*)malloc(sizeof(Point) * pointsCount);
|
points = (Point*)malloc(sizeof(Point) * pointsCount);
|
||||||
for (j = 0; j < pointsCount; j++) {
|
for (j = 0; j < pointsCount; j++) {
|
||||||
location.u() = clickArea->points[j].x;
|
location.u() = clickArea->points[j].x;
|
||||||
location.v() = clickArea->points[j].y;
|
location.v() = clickArea->points[j].y;
|
||||||
location.z = 0;
|
location.z = 0;
|
||||||
_vm->_isoMap->tileCoordsToScreenPoint(location, points[j]);
|
vm->_isoMap->tileCoordsToScreenPoint(location, points[j]);
|
||||||
}
|
}
|
||||||
//
|
|
||||||
} else {
|
} else {
|
||||||
points = clickArea->points;
|
points = clickArea->points;
|
||||||
}
|
}
|
||||||
|
@ -162,7 +161,7 @@ void HitZone::draw(Surface *ds, int color) {
|
||||||
ds->drawPolyLine(points, pointsCount, color);
|
ds->drawPolyLine(points, pointsCount, color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (_vm->_scene->getFlags() & kSceneFlagISO) {
|
if (vm->_scene->getFlags() & kSceneFlagISO) {
|
||||||
free(points);
|
free(points);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,11 +173,15 @@ void HitZone::draw(Surface *ds, int color) {
|
||||||
void ObjectMap::load(const byte *resourcePointer, size_t resourceLength) {
|
void ObjectMap::load(const byte *resourcePointer, size_t resourceLength) {
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
if (resourceLength == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (resourceLength < 4) {
|
if (resourceLength < 4) {
|
||||||
error("ObjectMap::load wrong resourceLength");
|
error("ObjectMap::load wrong resourceLength");
|
||||||
}
|
}
|
||||||
|
|
||||||
MemoryReadStreamEndian readS(resourcePointer, resourceLength, IS_BIG_ENDIAN);
|
MemoryReadStreamEndian readS(resourcePointer, resourceLength, _vm->isBigEndian());
|
||||||
|
|
||||||
_hitZoneListCount = readS.readSint16();
|
_hitZoneListCount = readS.readSint16();
|
||||||
if (_hitZoneListCount < 0) {
|
if (_hitZoneListCount < 0) {
|
||||||
|
@ -232,7 +235,7 @@ void ObjectMap::draw(Surface *ds, const Point& testPoint, int color, int color2)
|
||||||
hitZoneIndex = hitTest(pickPoint);
|
hitZoneIndex = hitTest(pickPoint);
|
||||||
|
|
||||||
for (i = 0; i < _hitZoneListCount; i++) {
|
for (i = 0; i < _hitZoneListCount; i++) {
|
||||||
_hitZoneList[i]->draw(ds, (hitZoneIndex == i) ? color2 : color);
|
_hitZoneList[i]->draw(_vm, ds, (hitZoneIndex == i) ? color2 : color);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hitZoneIndex != -1) {
|
if (hitZoneIndex != -1) {
|
||||||
|
|
|
@ -76,7 +76,7 @@ public:
|
||||||
return objectIndexToId(kGameObjectStepZone, _index);
|
return objectIndexToId(kGameObjectStepZone, _index);
|
||||||
}
|
}
|
||||||
bool getSpecialPoint(Point &specialPoint) const;
|
bool getSpecialPoint(Point &specialPoint) const;
|
||||||
void draw(Surface *ds, int color);
|
void draw(SagaEngine *vm, Surface *ds, int color);
|
||||||
bool hitTest(const Point &testPoint);
|
bool hitTest(const Point &testPoint);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -54,7 +54,7 @@ int PalAnim::loadPalAnim(const byte *resdata, size_t resdata_len) {
|
||||||
return FAILURE;
|
return FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
MemoryReadStreamEndian readS(resdata, resdata_len, IS_BIG_ENDIAN);
|
MemoryReadStreamEndian readS(resdata, resdata_len, _vm->isBigEndian());
|
||||||
|
|
||||||
if (_vm->getGameType() == GType_IHNM) {
|
if (_vm->getGameType() == GType_IHNM) {
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
|
|
398
saga/rscfile.cpp
398
saga/rscfile.cpp
|
@ -24,300 +24,200 @@
|
||||||
// RSC Resource file management module
|
// RSC Resource file management module
|
||||||
#include "saga/saga.h"
|
#include "saga/saga.h"
|
||||||
|
|
||||||
#include "saga/rscfile_mod.h"
|
|
||||||
#include "saga/rscfile.h"
|
#include "saga/rscfile.h"
|
||||||
#include "saga/stream.h"
|
#include "saga/stream.h"
|
||||||
|
|
||||||
namespace Saga {
|
namespace Saga {
|
||||||
|
|
||||||
static struct Substitutes {
|
Resource::Resource(SagaEngine *vm): _vm(vm) {
|
||||||
uint32 id;
|
_contexts = NULL;
|
||||||
const char *resfile;
|
_contextsCount = 0;
|
||||||
const char *fname;
|
}
|
||||||
} substitutes[] = {
|
|
||||||
{ 1529, "ite.rsc", "wyrm.pak" },
|
Resource::~Resource() {
|
||||||
{ 1530, "ite.rsc", "wyrm1.dlt" },
|
clearContexts();
|
||||||
{ 1531, "ite.rsc", "wyrm2.dlt" },
|
}
|
||||||
{ 1532, "ite.rsc", "wyrm3.dlt" },
|
|
||||||
{ 1533, "ite.rsc", "wyrm4.dlt" },
|
bool Resource::loadContext(ResourceContext *context) {
|
||||||
{ 1796, "ite.rsc", "credit3n.dlt" },
|
size_t i;
|
||||||
{ 1797, "ite.rsc", "credit4n.dlt" }
|
int j;
|
||||||
};
|
bool result;
|
||||||
|
byte tableInfo[RSC_TABLEINFO_SIZE];
|
||||||
|
uint32 resourceTableOffset;
|
||||||
|
GamePatchDescription *patchDescription;
|
||||||
|
ResourceData *resourceData;
|
||||||
|
byte *tableBuffer;
|
||||||
|
size_t tableSize;
|
||||||
|
|
||||||
|
if (!context->file->open(context->fileName)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
context->isBigEndian = _vm->isBigEndian();
|
||||||
RSCFILE_CONTEXT *RSC_CreateContext() {
|
|
||||||
RSCFILE_CONTEXT empty_context;
|
if (!context->isBigEndian) {
|
||||||
empty_context.rc_file_fspec = NULL;
|
context->isBigEndian = ((_vm->getFeatures() & GF_BIG_ENDIAN_VOICES) != 0) && ((context->fileType & GAME_VOICEFILE) != 0);
|
||||||
empty_context.rc_file_loaded = 0;
|
|
||||||
empty_context.rc_res_table = NULL;
|
|
||||||
empty_context.rc_res_ct = 0;
|
|
||||||
empty_context.rc_file = new Common::File();
|
|
||||||
RSCFILE_CONTEXT *new_context;
|
|
||||||
|
|
||||||
new_context = (RSCFILE_CONTEXT *)malloc(sizeof(*new_context));
|
|
||||||
if (new_context == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
*new_context = empty_context;
|
|
||||||
|
|
||||||
return new_context;
|
|
||||||
}
|
|
||||||
|
|
||||||
int RSC_OpenContext(RSCFILE_CONTEXT *rsc_context, const char *fspec) {
|
if (context->file->size() < RSC_MIN_FILESIZE) {
|
||||||
if (rsc_context->rc_file->isOpen()) {
|
return false;
|
||||||
return FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!rsc_context->rc_file->open(fspec)) {
|
|
||||||
return FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
rsc_context->rc_file_fspec = fspec;
|
|
||||||
|
|
||||||
if (RSC_LoadRSC(rsc_context) != SUCCESS) {
|
|
||||||
return FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
rsc_context->rc_file_loaded = 1;
|
|
||||||
|
|
||||||
return SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
int RSC_CloseContext(RSCFILE_CONTEXT *rsc_context) {
|
|
||||||
if (rsc_context->rc_file->isOpen()) {
|
|
||||||
rsc_context->rc_file->close();
|
|
||||||
}
|
|
||||||
|
|
||||||
RSC_FreeRSC(rsc_context);
|
|
||||||
|
|
||||||
rsc_context->rc_file_loaded = 0;
|
|
||||||
|
|
||||||
return SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
int RSC_DestroyContext(RSCFILE_CONTEXT *rsc_context) {
|
|
||||||
RSC_CloseContext(rsc_context);
|
|
||||||
|
|
||||||
if (rsc_context->rc_file_loaded) {
|
|
||||||
free(rsc_context->rc_res_table);
|
|
||||||
}
|
|
||||||
|
|
||||||
free(rsc_context);
|
|
||||||
|
|
||||||
return SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
int RSC_LoadRSC(RSCFILE_CONTEXT *rsc) {
|
|
||||||
uint32 res_tbl_ct;
|
|
||||||
uint32 res_tbl_offset;
|
|
||||||
|
|
||||||
byte tblinfo_buf[RSC_TABLEINFO_SIZE];
|
|
||||||
byte *tbl_buf;
|
|
||||||
size_t tbl_len;
|
|
||||||
uint32 i;
|
|
||||||
|
|
||||||
bool isBigEndian = _vm->isBigEndianFile(rsc->rc_file_fspec);
|
|
||||||
|
|
||||||
RSCFILE_RESOURCE *rsc_restbl;
|
|
||||||
|
|
||||||
if (rsc->rc_file->size() < RSC_MIN_FILESIZE) {
|
|
||||||
return FAILURE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read resource table info from the rear end of file
|
// Read resource table info from the rear end of file
|
||||||
rsc->rc_file->seek((long)(rsc->rc_file->size() - 8), SEEK_SET);
|
context->file->seek((long)(-RSC_TABLEINFO_SIZE), SEEK_END);
|
||||||
|
|
||||||
if (rsc->rc_file->read(tblinfo_buf, RSC_TABLEINFO_SIZE) != RSC_TABLEINFO_SIZE) {
|
if (context->file->read(tableInfo, RSC_TABLEINFO_SIZE) != RSC_TABLEINFO_SIZE) {
|
||||||
return FAILURE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
MemoryReadStreamEndian readS(tblinfo_buf, RSC_TABLEINFO_SIZE, isBigEndian);
|
|
||||||
|
|
||||||
res_tbl_offset = readS.readUint32();
|
MemoryReadStreamEndian readS(tableInfo, RSC_TABLEINFO_SIZE, context->isBigEndian);
|
||||||
res_tbl_ct = readS.readUint32();
|
|
||||||
|
resourceTableOffset = readS.readUint32();
|
||||||
|
context->count = readS.readUint32();
|
||||||
|
|
||||||
// Check for sane table offset
|
// Check for sane table offset
|
||||||
if (res_tbl_offset != rsc->rc_file->size() - RSC_TABLEINFO_SIZE - RSC_TABLEENTRY_SIZE * res_tbl_ct) {
|
if (resourceTableOffset != context->file->size() - RSC_TABLEINFO_SIZE - RSC_TABLEENTRY_SIZE * context->count) {
|
||||||
|
return false;
|
||||||
return FAILURE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load resource table
|
// Load resource table
|
||||||
tbl_len = RSC_TABLEENTRY_SIZE * res_tbl_ct;
|
tableSize = RSC_TABLEENTRY_SIZE * context->count;
|
||||||
|
|
||||||
tbl_buf = (byte *)malloc(tbl_len);
|
tableBuffer = (byte *)malloc(tableSize);
|
||||||
if (tbl_buf == NULL) {
|
|
||||||
return FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
rsc->rc_file->seek((long)res_tbl_offset, SEEK_SET);
|
context->file->seek((long)resourceTableOffset, SEEK_SET);
|
||||||
|
|
||||||
if (rsc->rc_file->read(tbl_buf, tbl_len) != tbl_len) {
|
|
||||||
free(tbl_buf);
|
result = (context->file->read(tableBuffer, tableSize) == tableSize);
|
||||||
return FAILURE;
|
if (result) {
|
||||||
}
|
context->table = (ResourceData *)calloc(context->count, sizeof(*context->table));
|
||||||
|
|
||||||
rsc_restbl = (RSCFILE_RESOURCE *)malloc(res_tbl_ct * sizeof(*rsc_restbl));
|
MemoryReadStreamEndian readS1(tableBuffer, tableSize, context->isBigEndian);
|
||||||
if (rsc_restbl == NULL) {
|
|
||||||
free(tbl_buf);
|
|
||||||
return FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
MemoryReadStreamEndian readS1(tbl_buf, tbl_len, isBigEndian);
|
for (i = 0; i < context->count; i++) {
|
||||||
|
resourceData = &context->table[i];
|
||||||
debug(9, "RSC %s", rsc->rc_file_fspec);
|
resourceData->offset = readS1.readUint32();
|
||||||
for (i = 0; i < res_tbl_ct; i++) {
|
resourceData->size = readS1.readUint32();
|
||||||
rsc_restbl[i].res_offset = readS1.readUint32();
|
//sanity check
|
||||||
rsc_restbl[i].res_size = readS1.readUint32();
|
if ((resourceData->offset > context->file->size()) || (resourceData->size > context->file->size())) {
|
||||||
//debug(9, "#%x Offset:%x Size:%x", i, rsc_restbl[i].res_offset, rsc_restbl[i].res_size);
|
result = false;
|
||||||
if ((rsc_restbl[i].res_offset > rsc->rc_file->size()) || (rsc_restbl[i].res_size > rsc->rc_file->size())) {
|
break;
|
||||||
free(tbl_buf);
|
}
|
||||||
free(rsc_restbl);
|
|
||||||
return FAILURE;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rsc->rc_res_table = rsc_restbl;
|
free(tableBuffer);
|
||||||
rsc->rc_res_ct = res_tbl_ct;
|
|
||||||
|
//process patch files
|
||||||
free(tbl_buf);
|
if (result) {
|
||||||
|
for (j = 0; j < _vm->getGameDescription()->patchsCount; j++) {
|
||||||
return SUCCESS;
|
patchDescription = &_vm->getGameDescription()->patchDescriptions[j];
|
||||||
}
|
if ((patchDescription->fileType & context->fileType) != 0) {
|
||||||
|
if (patchDescription->resourceId < context->count) {
|
||||||
int RSC_FreeRSC(RSCFILE_CONTEXT *rsc) {
|
//TODO|fix: should we convert this ID? or make separate patch list for MAC version?
|
||||||
if (!rsc->rc_file_loaded) {
|
resourceData = &context->table[patchDescription->resourceId];
|
||||||
return FAILURE;
|
resourceData->patchFile = new Common::File();
|
||||||
}
|
if (resourceData->patchFile->open(patchDescription->fileName)) {
|
||||||
|
resourceData->offset = 0;
|
||||||
delete rsc->rc_file;
|
resourceData->size = resourceData->patchFile->size();
|
||||||
rsc->rc_file = NULL;
|
} else {
|
||||||
|
warning("loadContext: patch file not found %s", patchDescription->fileName);
|
||||||
free(rsc->rc_res_table);
|
delete resourceData->patchFile;
|
||||||
|
resourceData->patchFile = NULL;
|
||||||
return SUCCESS;
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
uint32 RSC_GetResourceCount(RSCFILE_CONTEXT *rsc) {
|
|
||||||
return (rsc == NULL) ? 0 : rsc->rc_res_ct;
|
|
||||||
}
|
|
||||||
|
|
||||||
int RSC_GetResourceSize(RSCFILE_CONTEXT *rsc, uint32 res_num, uint32 *res_size) {
|
|
||||||
if ((rsc == NULL) || (res_size == NULL)) {
|
|
||||||
return FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (res_num > (rsc->rc_res_ct - 1)) {
|
|
||||||
return FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
*res_size = rsc->rc_res_table[res_num].res_size;
|
|
||||||
|
|
||||||
return SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
int RSC_GetResourceOffset(RSCFILE_CONTEXT *rsc, uint32 res_num, uint32 *res_offset) {
|
|
||||||
if ((rsc == NULL) || (res_offset == NULL)) {
|
|
||||||
return FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (res_num > (rsc->rc_res_ct - 1)) {
|
|
||||||
return FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
*res_offset = rsc->rc_res_table[res_num].res_offset;
|
|
||||||
|
|
||||||
return SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *RSC_FileName(RSCFILE_CONTEXT *rsc) {
|
|
||||||
return rsc->rc_file_fspec;
|
|
||||||
}
|
|
||||||
|
|
||||||
int RSC_LoadResource(RSCFILE_CONTEXT *rsc, uint32 res_num, byte **res_p, size_t *res_size_p) {
|
|
||||||
uint32 res_offset;
|
|
||||||
size_t res_size = 0;
|
|
||||||
byte *res_buf = NULL;
|
|
||||||
int substnum = -1;
|
|
||||||
|
|
||||||
if ((rsc == NULL) || (res_p == NULL)) {
|
|
||||||
return FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (res_num > (rsc->rc_res_ct - 1)) {
|
|
||||||
return FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
debug(8, "LoadResource %d", res_num);
|
|
||||||
for (int i = 0; i < ARRAYSIZE(substitutes); i++) {
|
|
||||||
if (substitutes[i].id == res_num && strcmp(substitutes[i].resfile, rsc->rc_file_fspec) == 0) {
|
|
||||||
substnum = i;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(_vm->getFeatures() & GF_WYRMKEEP))
|
return result;
|
||||||
substnum = -1;
|
}
|
||||||
|
|
||||||
if (substnum != -1) {
|
bool Resource::createContexts() {
|
||||||
Common::File in;
|
int i, j;
|
||||||
|
ResourceContext *context;
|
||||||
|
_contextsCount = _vm->getGameDescription()->filesCount;
|
||||||
|
_contexts = (ResourceContext*)calloc(_contextsCount, sizeof(*_contexts));
|
||||||
|
|
||||||
if (in.open(substitutes[substnum].fname)) {
|
for (i = 0; i < _contextsCount; i++) {
|
||||||
res_size = in.size();
|
context = &_contexts[i];
|
||||||
if ((res_buf = (byte *)malloc(res_size)) == NULL)
|
context->file = new Common::File();
|
||||||
return MEM;
|
context->fileName = _vm->getGameDescription()->filesDescriptions[i].fileName;
|
||||||
|
context->fileType = _vm->getGameDescription()->filesDescriptions[i].fileType;
|
||||||
|
|
||||||
in.read(res_buf, res_size);
|
//self check
|
||||||
in.close();
|
for (j = 0; j < i; j++) {
|
||||||
debug(8, "LoadResource: substituted resource by %s", substitutes[substnum].fname);
|
if ((_contexts[j].fileType & context->fileType) != 0) {
|
||||||
|
error("Resource::createContexts() duplicate fileType");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!loadContext(context)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Resource::clearContexts() {
|
||||||
|
int i;
|
||||||
|
size_t j;
|
||||||
|
ResourceContext *context;
|
||||||
|
if (_contexts == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for(i = 0; i < _contextsCount; i++) {
|
||||||
|
context = &_contexts[i];
|
||||||
|
delete context->file;
|
||||||
|
if (context->table != NULL) {
|
||||||
|
for(j = 0; j < context->count; j++) {
|
||||||
|
delete context->table[j].patchFile;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(context->table);
|
||||||
|
}
|
||||||
|
free(_contexts);
|
||||||
|
_contexts = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 Resource::convertResourceId(uint32 resourceId) {
|
||||||
|
|
||||||
|
if ((_vm->getGameType() == GType_ITE) && (_vm->getFeatures() & GF_MAC_RESOURCES)) {
|
||||||
|
if (resourceId > 1537) {
|
||||||
|
return resourceId - 2;
|
||||||
} else {
|
} else {
|
||||||
substnum = -1;
|
if (resourceId == 1535 || resourceId == 1536) {
|
||||||
|
error ("Wrong resource number %d for Mac ITE", resourceId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (substnum == -1) {
|
return resourceId;
|
||||||
res_offset = rsc->rc_res_table[res_num].res_offset;
|
|
||||||
res_size = rsc->rc_res_table[res_num].res_size;
|
|
||||||
|
|
||||||
if ((res_buf = (byte *)malloc(res_size)) == NULL)
|
|
||||||
return MEM;
|
|
||||||
|
|
||||||
rsc->rc_file->seek((long)res_offset, SEEK_SET);
|
|
||||||
|
|
||||||
if (rsc->rc_file->read(res_buf, res_size) != res_size) {
|
|
||||||
free(res_buf);
|
|
||||||
return FAILURE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
*res_p = res_buf;
|
|
||||||
|
|
||||||
if (res_size_p != NULL) {
|
|
||||||
*res_size_p = res_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
return SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int RSC_FreeResource(byte *resource_ptr) {
|
void Resource::loadResource(ResourceContext *context, uint32 resourceId, byte*&resourceBuffer, size_t &resourceSize) {
|
||||||
free(resource_ptr);
|
Common::File *file;
|
||||||
|
uint32 resourceOffset;
|
||||||
|
ResourceData *resourceData;
|
||||||
|
|
||||||
return SUCCESS;
|
debug(8, "loadResource %d", resourceId);
|
||||||
}
|
|
||||||
|
resourceData = getResourceData(context, resourceId);
|
||||||
|
|
||||||
|
file = context->getFile(resourceData);
|
||||||
|
|
||||||
int RSC_ConvertID(int id) {
|
resourceOffset = resourceData->offset;
|
||||||
int res = id;
|
resourceSize = resourceData->size;
|
||||||
|
|
||||||
if (_vm->getFeatures() & GF_MAC_RESOURCES) {
|
resourceBuffer = (byte*)malloc(resourceSize);
|
||||||
if (res > 1537)
|
|
||||||
res -= 2;
|
file->seek((long)resourceOffset, SEEK_SET);
|
||||||
else if (res == 1535 || res == 1536) {
|
|
||||||
error ("Wrong resource number %d for Mac ITE");
|
if (file->read(resourceBuffer, resourceSize) != resourceSize) {
|
||||||
}
|
error("Resource::loadResource() failed to read");
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // End of namespace Saga
|
} // End of namespace Saga
|
||||||
|
|
|
@ -36,22 +36,79 @@ namespace Saga {
|
||||||
|
|
||||||
#define RSC_MIN_FILESIZE (RSC_TABLEINFO_SIZE + RSC_TABLEENTRY_SIZE + 1)
|
#define RSC_MIN_FILESIZE (RSC_TABLEINFO_SIZE + RSC_TABLEENTRY_SIZE + 1)
|
||||||
|
|
||||||
struct RSCFILE_RESOURCE {
|
//TODO: good PATCH.RE_ support
|
||||||
int res_type;
|
|
||||||
size_t res_offset;
|
struct ResourceData {
|
||||||
size_t res_size;
|
size_t offset;
|
||||||
|
size_t size;
|
||||||
|
Common::File *patchFile;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct RSCFILE_CONTEXT {
|
struct ResourceContext {
|
||||||
const char *rc_file_fspec;
|
const char *fileName;
|
||||||
Common::File *rc_file;
|
uint16 fileType;
|
||||||
int rc_file_loaded;
|
Common::File *file;
|
||||||
RSCFILE_RESOURCE *rc_res_table;
|
|
||||||
size_t rc_res_ct;
|
bool isBigEndian;
|
||||||
|
ResourceData *table;
|
||||||
|
size_t count;
|
||||||
|
|
||||||
|
Common::File *getFile(ResourceData *resourceData) const {
|
||||||
|
if (resourceData->patchFile != NULL) {
|
||||||
|
return resourceData->patchFile;
|
||||||
|
} else {
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
int RSC_LoadRSC(RSCFILE_CONTEXT *rsc_context);
|
class Resource {
|
||||||
int RSC_FreeRSC(RSCFILE_CONTEXT *rsc);
|
public:
|
||||||
|
Resource(SagaEngine *vm);
|
||||||
|
~Resource();
|
||||||
|
bool createContexts();
|
||||||
|
void clearContexts();
|
||||||
|
void loadResource(ResourceContext *context, uint32 resourceId, byte*&resourceBuffer, size_t &resourceSize);
|
||||||
|
size_t getResourceSize(ResourceContext *context, uint32 resourceId);
|
||||||
|
uint32 convertResourceId(uint32 resourceId);
|
||||||
|
|
||||||
|
ResourceContext *getContext(uint16 fileType) {
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < _contextsCount; i++) {
|
||||||
|
if (_contexts[i].fileType & fileType) {
|
||||||
|
return &_contexts[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool validResourceId(ResourceContext *context, uint32 resourceId) const {
|
||||||
|
return (resourceId < context->count);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t getResourceSize(ResourceContext *context, uint32 resourceId) const {
|
||||||
|
return getResourceData(context, resourceId)->size;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t getResourceOffset(ResourceContext *context, uint32 resourceId) const {
|
||||||
|
return getResourceData(context, resourceId)->offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
ResourceData *getResourceData(ResourceContext *context, uint32 resourceId) const {
|
||||||
|
if (!validResourceId(context, resourceId)) {
|
||||||
|
error("Resource::getResourceData() wrong resourceId %d", resourceId);
|
||||||
|
}
|
||||||
|
return &context->table[resourceId];
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
SagaEngine *_vm;
|
||||||
|
ResourceContext *_contexts;
|
||||||
|
int _contextsCount;
|
||||||
|
|
||||||
|
bool loadContext(ResourceContext *context);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
} // End of namespace Saga
|
} // End of namespace Saga
|
||||||
|
|
||||||
|
|
|
@ -34,8 +34,8 @@
|
||||||
|
|
||||||
#include "saga/saga.h"
|
#include "saga/saga.h"
|
||||||
|
|
||||||
|
#include "saga/rscfile.h"
|
||||||
#include "saga/gfx.h"
|
#include "saga/gfx.h"
|
||||||
#include "saga/rscfile_mod.h"
|
|
||||||
#include "saga/render.h"
|
#include "saga/render.h"
|
||||||
#include "saga/actor.h"
|
#include "saga/actor.h"
|
||||||
#include "saga/animation.h"
|
#include "saga/animation.h"
|
||||||
|
@ -53,6 +53,7 @@
|
||||||
#include "saga/music.h"
|
#include "saga/music.h"
|
||||||
#include "saga/palanim.h"
|
#include "saga/palanim.h"
|
||||||
#include "saga/objectmap.h"
|
#include "saga/objectmap.h"
|
||||||
|
#include "saga/resnames.h"
|
||||||
|
|
||||||
static const GameSettings saga_games[] = {
|
static const GameSettings saga_games[] = {
|
||||||
{"ite", "Inherit the Earth", 0},
|
{"ite", "Inherit the Earth", 0},
|
||||||
|
@ -114,8 +115,6 @@ namespace Saga {
|
||||||
|
|
||||||
#define MAX_TIME_DELTA 100
|
#define MAX_TIME_DELTA 100
|
||||||
|
|
||||||
SagaEngine *_vm = NULL;
|
|
||||||
|
|
||||||
SagaEngine::SagaEngine(GameDetector *detector, OSystem *syst)
|
SagaEngine::SagaEngine(GameDetector *detector, OSystem *syst)
|
||||||
: Engine(syst),
|
: Engine(syst),
|
||||||
_targetName(detector->_targetName) {
|
_targetName(detector->_targetName) {
|
||||||
|
@ -123,9 +122,9 @@ SagaEngine::SagaEngine(GameDetector *detector, OSystem *syst)
|
||||||
_leftMouseButtonPressed = _rightMouseButtonPressed = false;
|
_leftMouseButtonPressed = _rightMouseButtonPressed = false;
|
||||||
|
|
||||||
_console = NULL;
|
_console = NULL;
|
||||||
_gameFileContexts = NULL;
|
|
||||||
_quit = false;
|
_quit = false;
|
||||||
|
|
||||||
|
_resource = NULL;
|
||||||
_sndRes = NULL;
|
_sndRes = NULL;
|
||||||
_events = NULL;
|
_events = NULL;
|
||||||
_font = NULL;
|
_font = NULL;
|
||||||
|
@ -166,13 +165,13 @@ SagaEngine::SagaEngine(GameDetector *detector, OSystem *syst)
|
||||||
_mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume"));
|
_mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume"));
|
||||||
|
|
||||||
_displayClip.left = _displayClip.top = 0;
|
_displayClip.left = _displayClip.top = 0;
|
||||||
_vm = this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SagaEngine::~SagaEngine() {
|
SagaEngine::~SagaEngine() {
|
||||||
int i;
|
if (_scene != NULL) {
|
||||||
if (_scene->isSceneLoaded()) {
|
if (_scene->isSceneLoaded()) {
|
||||||
_scene->endScene();
|
_scene->endScene();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
delete _puzzle;
|
delete _puzzle;
|
||||||
|
@ -193,12 +192,7 @@ SagaEngine::~SagaEngine() {
|
||||||
delete _gfx;
|
delete _gfx;
|
||||||
delete _console;
|
delete _console;
|
||||||
|
|
||||||
if (_gameFileContexts != NULL) {
|
delete _resource;
|
||||||
for (i = 0; i < _gameDescription->filesCount; i++) {
|
|
||||||
RSC_DestroyContext(_gameFileContexts[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
free(_gameFileContexts);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SagaEngine::errorString(const char *buf1, char *buf2) {
|
void SagaEngine::errorString(const char *buf1, char *buf2) {
|
||||||
|
@ -209,6 +203,8 @@ int SagaEngine::init(GameDetector &detector) {
|
||||||
_soundEnabled = 1;
|
_soundEnabled = 1;
|
||||||
_musicEnabled = 1;
|
_musicEnabled = 1;
|
||||||
|
|
||||||
|
_resource = new Resource(this);
|
||||||
|
|
||||||
// Add some default directories
|
// Add some default directories
|
||||||
// Win32 demo & full game
|
// Win32 demo & full game
|
||||||
Common::File::addDefaultDirectory("graphics");
|
Common::File::addDefaultDirectory("graphics");
|
||||||
|
@ -224,7 +220,7 @@ int SagaEngine::init(GameDetector &detector) {
|
||||||
// Process command line
|
// Process command line
|
||||||
|
|
||||||
// Detect game and open resource files
|
// Detect game and open resource files
|
||||||
if (initGame() != SUCCESS) {
|
if (!initGame()) {
|
||||||
return FAILURE;
|
return FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -242,17 +238,12 @@ int SagaEngine::init(GameDetector &detector) {
|
||||||
_isoMap = new IsoMap(this);
|
_isoMap = new IsoMap(this);
|
||||||
_puzzle = new Puzzle(this);
|
_puzzle = new Puzzle(this);
|
||||||
|
|
||||||
if (!_scene->initialized()) {
|
|
||||||
warning("Couldn't initialize scene module");
|
|
||||||
return FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// System initialization
|
// System initialization
|
||||||
|
|
||||||
_previousTicks = _system->getMillis();
|
_previousTicks = _system->getMillis();
|
||||||
|
|
||||||
// Initialize graphics
|
// Initialize graphics
|
||||||
_gfx = new Gfx(_system, getDisplayWidth(), getDisplayHeight(), detector);
|
_gfx = new Gfx(this, _system, getDisplayWidth(), getDisplayHeight(), detector);
|
||||||
|
|
||||||
// Graphics driver should be initialized before console
|
// Graphics driver should be initialized before console
|
||||||
_console = new Console(this);
|
_console = new Console(this);
|
||||||
|
@ -270,7 +261,7 @@ int SagaEngine::init(GameDetector &detector) {
|
||||||
} else if (native_mt32)
|
} else if (native_mt32)
|
||||||
driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE);
|
driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE);
|
||||||
|
|
||||||
_music = new Music(_mixer, driver, _musicEnabled);
|
_music = new Music(this, _mixer, driver, _musicEnabled);
|
||||||
_music->setNativeMT32(native_mt32);
|
_music->setNativeMT32(native_mt32);
|
||||||
_music->setAdlib(adlib);
|
_music->setAdlib(adlib);
|
||||||
|
|
||||||
|
@ -368,11 +359,15 @@ void SagaEngine::loadStrings(StringsTable &stringsTable, const byte *stringsPoin
|
||||||
size_t offset;
|
size_t offset;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
if (stringsLength == 0) {
|
||||||
|
error("SagaEngine::loadStrings() Error loading strings list resource");
|
||||||
|
}
|
||||||
|
|
||||||
stringsTable.stringsPointer = (byte*)malloc(stringsLength);
|
stringsTable.stringsPointer = (byte*)malloc(stringsLength);
|
||||||
memcpy(stringsTable.stringsPointer, stringsPointer, stringsLength);
|
memcpy(stringsTable.stringsPointer, stringsPointer, stringsLength);
|
||||||
|
|
||||||
|
|
||||||
MemoryReadStreamEndian scriptS(stringsTable.stringsPointer, stringsLength, IS_BIG_ENDIAN);
|
MemoryReadStreamEndian scriptS(stringsTable.stringsPointer, stringsLength, isBigEndian()); //TODO: get endianess from context
|
||||||
|
|
||||||
offset = scriptS.readUint16();
|
offset = scriptS.readUint16();
|
||||||
stringsCount = offset / 2;
|
stringsCount = offset / 2;
|
||||||
|
|
45
saga/saga.h
45
saga/saga.h
|
@ -55,9 +55,13 @@ class Console;
|
||||||
class Events;
|
class Events;
|
||||||
class PalAnim;
|
class PalAnim;
|
||||||
class Puzzle;
|
class Puzzle;
|
||||||
|
class Resource;
|
||||||
|
|
||||||
#define MIN_IMG_RLECODE 3
|
struct ResourceContext;
|
||||||
#define MODEX_SCANLINE_LIMIT 200
|
struct StringList;
|
||||||
|
|
||||||
|
//#define MIN_IMG_RLECODE 3
|
||||||
|
//#define MODEX_SCANLINE_LIMIT 200 //TODO: remove
|
||||||
|
|
||||||
#define SAGA_IMAGE_DATA_OFFSET 776
|
#define SAGA_IMAGE_DATA_OFFSET 776
|
||||||
#define SAGA_IMAGE_HEADER_LEN 8
|
#define SAGA_IMAGE_HEADER_LEN 8
|
||||||
|
@ -68,9 +72,6 @@ class Puzzle;
|
||||||
#define MAX_SAVES 96
|
#define MAX_SAVES 96
|
||||||
#define MAX_FILE_NAME 256
|
#define MAX_FILE_NAME 256
|
||||||
|
|
||||||
|
|
||||||
#define IS_BIG_ENDIAN ((_vm->getFeatures() & GF_BIG_ENDIAN_DATA) != 0)
|
|
||||||
|
|
||||||
#define ID_NOTHING 0
|
#define ID_NOTHING 0
|
||||||
#define ID_PROTAG 1
|
#define ID_PROTAG 1
|
||||||
#define OBJECT_TYPE_SHIFT 13
|
#define OBJECT_TYPE_SHIFT 13
|
||||||
|
@ -80,9 +81,6 @@ class Puzzle;
|
||||||
|
|
||||||
#define memoryError(Place) error("%s Memory allocation error.", Place)
|
#define memoryError(Place) error("%s Memory allocation error.", Place)
|
||||||
|
|
||||||
struct RSCFILE_CONTEXT;
|
|
||||||
struct StringList;
|
|
||||||
|
|
||||||
enum ERRORCODE {
|
enum ERRORCODE {
|
||||||
MEM = -2,//todo: remove
|
MEM = -2,//todo: remove
|
||||||
FAILURE = -1,
|
FAILURE = -1,
|
||||||
|
@ -326,10 +324,10 @@ enum FontEffectFlags {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct GameSoundInfo {
|
struct GameSoundInfo {
|
||||||
int res_type;
|
GameSoundTypes resourceType;
|
||||||
long freq;
|
long frequency;
|
||||||
int sample_size;
|
int sampleBits;
|
||||||
int stereo;
|
bool stereo;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct GameFontDescription {
|
struct GameFontDescription {
|
||||||
|
@ -354,6 +352,12 @@ struct GameFileDescription {
|
||||||
uint16 fileType;
|
uint16 fileType;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct GamePatchDescription {
|
||||||
|
const char *fileName;
|
||||||
|
uint16 fileType;
|
||||||
|
uint32 resourceId;
|
||||||
|
};
|
||||||
|
|
||||||
struct PanelButton {
|
struct PanelButton {
|
||||||
PanelButtonType type;
|
PanelButtonType type;
|
||||||
int xOffset;
|
int xOffset;
|
||||||
|
@ -463,6 +467,8 @@ struct GameDescription {
|
||||||
int fontsCount;
|
int fontsCount;
|
||||||
GameFontDescription *fontDescriptions;
|
GameFontDescription *fontDescriptions;
|
||||||
GameSoundInfo *soundInfo;
|
GameSoundInfo *soundInfo;
|
||||||
|
int patchsCount;
|
||||||
|
GamePatchDescription *patchDescriptions;
|
||||||
uint32 features;
|
uint32 features;
|
||||||
|
|
||||||
GameSettings toGameSettings() const {
|
GameSettings toGameSettings() const {
|
||||||
|
@ -569,6 +575,7 @@ public:
|
||||||
Events *_events;
|
Events *_events;
|
||||||
PalAnim *_palanim;
|
PalAnim *_palanim;
|
||||||
Puzzle *_puzzle;
|
Puzzle *_puzzle;
|
||||||
|
Resource *_resource;
|
||||||
|
|
||||||
|
|
||||||
/** Random number generator */
|
/** Random number generator */
|
||||||
|
@ -619,7 +626,6 @@ public:
|
||||||
bool _rightMouseButtonPressed;
|
bool _rightMouseButtonPressed;
|
||||||
|
|
||||||
bool _quit;
|
bool _quit;
|
||||||
RSCFILE_CONTEXT **_gameFileContexts;
|
|
||||||
|
|
||||||
//current game description
|
//current game description
|
||||||
int _gameNumber;
|
int _gameNumber;
|
||||||
|
@ -628,10 +634,13 @@ public:
|
||||||
Common::Rect _displayClip;
|
Common::Rect _displayClip;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
int initGame(void);
|
bool initGame(void);
|
||||||
RSCFILE_CONTEXT *getFileContext(uint16 type, int param);
|
// RSCFILE_CONTEXT *getFileContext(uint16 type, int param);
|
||||||
bool isBigEndianFile(const char *filename);
|
// bool isBigEndianFile(const char *filename);
|
||||||
public:
|
public:
|
||||||
|
const GameDescription *getGameDescription() const { return _gameDescription; }
|
||||||
|
const bool isBigEndian() const { return (_gameDescription->features & GF_BIG_ENDIAN_DATA) != 0; }
|
||||||
|
const bool isMacResources() const { return (_gameDescription->features & GF_MAC_RESOURCES) != 0; }
|
||||||
const GameResourceDescription *getResourceDescription() { return _gameDescription->resourceDescription; }
|
const GameResourceDescription *getResourceDescription() { return _gameDescription->resourceDescription; }
|
||||||
const GameSoundInfo *getSoundInfo() { return _gameDescription->soundInfo; }
|
const GameSoundInfo *getSoundInfo() { return _gameDescription->soundInfo; }
|
||||||
|
|
||||||
|
@ -656,12 +665,8 @@ public:
|
||||||
|
|
||||||
const char *getTextString(int textStringId);
|
const char *getTextString(int textStringId);
|
||||||
void getExcuseInfo(int verb, const char *&textString, int &soundResourceId);
|
void getExcuseInfo(int verb, const char *&textString, int &soundResourceId);
|
||||||
private:
|
|
||||||
int loadGame(int gameNumber);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// FIXME: Global var. We use it until everything will be turned into objects
|
|
||||||
extern SagaEngine *_vm;
|
|
||||||
|
|
||||||
} // End of namespace Saga
|
} // End of namespace Saga
|
||||||
|
|
||||||
|
|
235
saga/scene.cpp
235
saga/scene.cpp
|
@ -34,7 +34,6 @@
|
||||||
#include "saga/palanim.h"
|
#include "saga/palanim.h"
|
||||||
#include "saga/puzzle.h"
|
#include "saga/puzzle.h"
|
||||||
#include "saga/render.h"
|
#include "saga/render.h"
|
||||||
#include "saga/rscfile_mod.h"
|
|
||||||
#include "saga/script.h"
|
#include "saga/script.h"
|
||||||
#include "saga/sound.h"
|
#include "saga/sound.h"
|
||||||
#include "saga/music.h"
|
#include "saga/music.h"
|
||||||
|
@ -42,6 +41,8 @@
|
||||||
#include "saga/scene.h"
|
#include "saga/scene.h"
|
||||||
#include "saga/stream.h"
|
#include "saga/stream.h"
|
||||||
#include "saga/actor.h"
|
#include "saga/actor.h"
|
||||||
|
#include "saga/rscfile.h"
|
||||||
|
#include "saga/resnames.h"
|
||||||
|
|
||||||
namespace Saga {
|
namespace Saga {
|
||||||
|
|
||||||
|
@ -49,46 +50,41 @@ static int initSceneDoors[SCENE_DOORS_MAX] = {
|
||||||
0, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
|
0, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
|
||||||
};
|
};
|
||||||
|
|
||||||
Scene::Scene(SagaEngine *vm) : _vm(vm), _initialized(false) {
|
Scene::Scene(SagaEngine *vm) : _vm(vm) {
|
||||||
byte *scene_lut_p;
|
byte *sceneLUTPointer;
|
||||||
size_t scene_lut_len;
|
size_t sceneLUTLength;
|
||||||
int result;
|
uint32 resourceId;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
|
||||||
// Load scene module resource context
|
// Load scene module resource context
|
||||||
_sceneContext = _vm->getFileContext(GAME_RESOURCEFILE, 0);
|
_sceneContext = _vm->_resource->getContext(GAME_RESOURCEFILE);
|
||||||
if (_sceneContext == NULL) {
|
if (_sceneContext == NULL) {
|
||||||
warning("Scene::Scene(): Couldn't load scene resource context");
|
error("Scene::Scene() scene context not found");
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Load scene lookup table
|
// Load scene lookup table
|
||||||
debug(3, "Loading scene LUT from resource %u.", RSC_ConvertID(_vm->getResourceDescription()->sceneLUTResourceId));
|
resourceId = _vm->_resource->convertResourceId(_vm->getResourceDescription()->sceneLUTResourceId);
|
||||||
result = RSC_LoadResource(_sceneContext, RSC_ConvertID(_vm->getResourceDescription()->sceneLUTResourceId), &scene_lut_p, &scene_lut_len);
|
debug(3, "Loading scene LUT from resource %i", resourceId);
|
||||||
if (result != SUCCESS) {
|
_vm->_resource->loadResource(_sceneContext, resourceId, sceneLUTPointer, sceneLUTLength);
|
||||||
warning("Scene::Scene(): Error: couldn't load scene LUT");
|
if (sceneLUTLength == 0) {
|
||||||
return;
|
error("Scene::Scene() sceneLUTLength == 0");
|
||||||
}
|
}
|
||||||
if (scene_lut_len==0) {
|
_sceneCount = sceneLUTLength / 2;
|
||||||
warning("Scene::Scene(): scene_lut_len==0");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
_sceneCount = scene_lut_len / 2;
|
|
||||||
_sceneLUT = (int *)malloc(_sceneCount * sizeof(*_sceneLUT));
|
_sceneLUT = (int *)malloc(_sceneCount * sizeof(*_sceneLUT));
|
||||||
if (_sceneLUT == NULL) {
|
if (_sceneLUT == NULL) {
|
||||||
memoryError("Scene::Scene()");
|
memoryError("Scene::Scene()");
|
||||||
}
|
}
|
||||||
|
|
||||||
MemoryReadStreamEndian readS(scene_lut_p, scene_lut_len, IS_BIG_ENDIAN);
|
MemoryReadStreamEndian readS(sceneLUTPointer, sceneLUTLength, _sceneContext->isBigEndian);
|
||||||
|
|
||||||
for (i = 0; i < _sceneCount; i++) {
|
for (i = 0; i < _sceneCount; i++) {
|
||||||
_sceneLUT[i] = readS.readUint16();
|
_sceneLUT[i] = readS.readUint16();
|
||||||
debug(8, "sceneNumber %i has resourceId %i", i, _sceneLUT[i]);
|
debug(8, "sceneNumber %i has resourceId %i", i, _sceneLUT[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
free(scene_lut_p);
|
free(sceneLUTPointer);
|
||||||
|
|
||||||
_firstScene = _vm->getStartSceneNumber();
|
_firstScene = _vm->getStartSceneNumber();
|
||||||
|
|
||||||
|
@ -102,22 +98,19 @@ Scene::Scene(SagaEngine *vm) : _vm(vm), _initialized(false) {
|
||||||
_inGame = false;
|
_inGame = false;
|
||||||
_loadDescription = false;
|
_loadDescription = false;
|
||||||
memset(&_sceneDescription, 0, sizeof(_sceneDescription));
|
memset(&_sceneDescription, 0, sizeof(_sceneDescription));
|
||||||
_resListEntries = 0;
|
_resourceListCount = 0;
|
||||||
_resList = NULL;
|
_resourceList = NULL;
|
||||||
_sceneProc = NULL;
|
_sceneProc = NULL;
|
||||||
_objectMap = new ObjectMap(_vm);
|
_objectMap = new ObjectMap(_vm);
|
||||||
_actionMap = new ObjectMap(_vm);
|
_actionMap = new ObjectMap(_vm);
|
||||||
memset(&_bg, 0, sizeof(_bg));
|
memset(&_bg, 0, sizeof(_bg));
|
||||||
memset(&_bgMask, 0, sizeof(_bgMask));
|
memset(&_bgMask, 0, sizeof(_bgMask));
|
||||||
|
|
||||||
_initialized = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Scene::~Scene() {
|
Scene::~Scene() {
|
||||||
if (_initialized) {
|
delete _actionMap;
|
||||||
delete _actionMap;
|
delete _objectMap;
|
||||||
free(_sceneLUT);
|
free(_sceneLUT);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scene::drawTextList(Surface *ds) {
|
void Scene::drawTextList(Surface *ds) {
|
||||||
|
@ -125,8 +118,13 @@ void Scene::drawTextList(Surface *ds) {
|
||||||
|
|
||||||
for (TextList::iterator textIterator = _textList.begin(); textIterator != _textList.end(); ++textIterator) {
|
for (TextList::iterator textIterator = _textList.begin(); textIterator != _textList.end(); ++textIterator) {
|
||||||
entry = (TextListEntry *)textIterator.operator->();
|
entry = (TextListEntry *)textIterator.operator->();
|
||||||
if (entry->display != 0) {
|
if (entry->display) {
|
||||||
_vm->_font->textDraw(entry->fontId, ds, entry->text, entry->point, entry->color, entry->effectColor, entry->flags);
|
|
||||||
|
if (entry->useRect) {
|
||||||
|
_vm->_font->textDrawRect(entry->fontId, ds, entry->text, entry->rect, entry->color, entry->effectColor, entry->flags);
|
||||||
|
} else {
|
||||||
|
_vm->_font->textDraw(entry->fontId, ds, entry->text, entry->point, entry->color, entry->effectColor, entry->flags);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -212,8 +210,6 @@ void Scene::skipScene() {
|
||||||
LoadSceneParams *sceneQueue = NULL;
|
LoadSceneParams *sceneQueue = NULL;
|
||||||
LoadSceneParams *skipQueue = NULL;
|
LoadSceneParams *skipQueue = NULL;
|
||||||
|
|
||||||
assert(_initialized);
|
|
||||||
|
|
||||||
if (!_sceneLoaded) {
|
if (!_sceneLoaded) {
|
||||||
error("Scene::skip(): Error: Can't skip scene...no scene loaded");
|
error("Scene::skip(): Error: Can't skip scene...no scene loaded");
|
||||||
}
|
}
|
||||||
|
@ -287,13 +283,6 @@ void Scene::getBGInfo(BGInfo &bgInfo) {
|
||||||
bgInfo.bounds.setHeight(_bg.h);
|
bgInfo.bounds.setHeight(_bg.h);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Scene::getBGPal(PalEntry **pal) {
|
|
||||||
assert(_initialized);
|
|
||||||
*pal = _bg.pal;
|
|
||||||
|
|
||||||
return SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
int Scene::getBGMaskType(const Point &testPoint) {
|
int Scene::getBGMaskType(const Point &testPoint) {
|
||||||
uint offset;
|
uint offset;
|
||||||
if (!_bgMask.loaded) {
|
if (!_bgMask.loaded) {
|
||||||
|
@ -382,8 +371,7 @@ void Scene::initDoorsState() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scene::loadScene(LoadSceneParams *loadSceneParams) {
|
void Scene::loadScene(LoadSceneParams *loadSceneParams) {
|
||||||
int result;
|
size_t i;
|
||||||
int i;
|
|
||||||
EVENT event;
|
EVENT event;
|
||||||
EVENT *q_event;
|
EVENT *q_event;
|
||||||
static PalEntry current_pal[PAL_ENTRIES];
|
static PalEntry current_pal[PAL_ENTRIES];
|
||||||
|
@ -407,11 +395,11 @@ void Scene::loadScene(LoadSceneParams *loadSceneParams) {
|
||||||
_sceneNumber = -1;
|
_sceneNumber = -1;
|
||||||
_sceneResourceId = -1;
|
_sceneResourceId = -1;
|
||||||
assert(loadSceneParams->sceneDescription != NULL);
|
assert(loadSceneParams->sceneDescription != NULL);
|
||||||
assert(loadSceneParams->sceneDescription->resList != NULL);
|
assert(loadSceneParams->sceneDescription->resourceList != NULL);
|
||||||
_loadDescription = false;
|
_loadDescription = false;
|
||||||
_sceneDescription = *loadSceneParams->sceneDescription;
|
_sceneDescription = *loadSceneParams->sceneDescription;
|
||||||
_resList = loadSceneParams->sceneDescription->resList;
|
_resourceList = loadSceneParams->sceneDescription->resourceList;
|
||||||
_resListEntries = loadSceneParams->sceneDescription->resListCnt;
|
_resourceListCount = loadSceneParams->sceneDescription->resourceListCount;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -419,32 +407,25 @@ void Scene::loadScene(LoadSceneParams *loadSceneParams) {
|
||||||
|
|
||||||
// Load scene descriptor and resource list resources
|
// Load scene descriptor and resource list resources
|
||||||
if (_loadDescription) {
|
if (_loadDescription) {
|
||||||
debug(3, "Loading scene resource %u:", _sceneResourceId);
|
debug(3, "Loading scene resource %i", _sceneResourceId);
|
||||||
|
|
||||||
if (loadSceneDescriptor(_sceneResourceId) != SUCCESS) {
|
loadSceneDescriptor(_sceneResourceId);
|
||||||
error("Scene::loadScene(): Error reading scene descriptor");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (loadSceneResourceList(_sceneDescription.resListRN) != SUCCESS) {
|
loadSceneResourceList(_sceneDescription.resourceListResourceId);
|
||||||
error("Scene::loadScene(): Error reading scene resource list");
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
debug(3, "Loading memory scene resource.");
|
debug(3, "Loading memory scene resource");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load resources from scene resource list
|
// Load resources from scene resource list
|
||||||
for (i = 0; i < _resListEntries; i++) {
|
for (i = 0; i < _resourceListCount; i++) {
|
||||||
result = RSC_LoadResource(_sceneContext, _resList[i].res_number,
|
if (!_resourceList[i].invalid) {
|
||||||
&_resList[i].res_data, &_resList[i].res_data_len);
|
_vm->_resource->loadResource(_sceneContext, _resourceList[i].resourceId,
|
||||||
if (result != SUCCESS) {
|
_resourceList[i].buffer, _resourceList[i].size);
|
||||||
error("Scene::loadScene(): Error: Allocation failure loading scene resource list");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process resources from scene resource list
|
// Process resources from scene resource list
|
||||||
if (processSceneResources() != SUCCESS) {
|
processSceneResources();
|
||||||
error("Scene::loadScene(): Error loading scene resources");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_sceneDescription.flags & kSceneFlagISO) {
|
if (_sceneDescription.flags & kSceneFlagISO) {
|
||||||
_outsetSceneNumber = _sceneNumber;
|
_outsetSceneNumber = _sceneNumber;
|
||||||
|
@ -565,10 +546,10 @@ void Scene::loadScene(LoadSceneParams *loadSceneParams) {
|
||||||
_vm->_sound->stopVoice();
|
_vm->_sound->stopVoice();
|
||||||
_vm->_sound->stopSound();
|
_vm->_sound->stopSound();
|
||||||
|
|
||||||
if (_sceneDescription.musicRN >= 0) {
|
if (_sceneDescription.musicResourceId >= 0) {
|
||||||
event.type = ONESHOT_EVENT;
|
event.type = ONESHOT_EVENT;
|
||||||
event.code = MUSIC_EVENT;
|
event.code = MUSIC_EVENT;
|
||||||
event.param = _sceneDescription.musicRN;
|
event.param = _sceneDescription.musicResourceId;
|
||||||
event.param2 = MUSIC_DEFAULT;
|
event.param2 = MUSIC_DEFAULT;
|
||||||
event.op = EVENT_PLAY;
|
event.op = EVENT_PLAY;
|
||||||
event.time = 0;
|
event.time = 0;
|
||||||
|
@ -653,85 +634,76 @@ void Scene::loadScene(LoadSceneParams *loadSceneParams) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int Scene::loadSceneDescriptor(uint32 res_number) {
|
void Scene::loadSceneDescriptor(uint32 resourceId) {
|
||||||
byte *scene_desc_data;
|
byte *sceneDescriptorData;
|
||||||
size_t scene_desc_len;
|
size_t sceneDescriptorDataLength;
|
||||||
int result;
|
|
||||||
|
|
||||||
result = RSC_LoadResource(_sceneContext, res_number, &scene_desc_data, &scene_desc_len);
|
_vm->_resource->loadResource(_sceneContext, resourceId, sceneDescriptorData, sceneDescriptorDataLength);
|
||||||
if (result != SUCCESS) {
|
|
||||||
warning("Scene::loadSceneDescriptor(): Error: couldn't load scene descriptor");
|
|
||||||
return FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
MemoryReadStreamEndian readS(scene_desc_data, scene_desc_len, IS_BIG_ENDIAN);
|
MemoryReadStreamEndian readS(sceneDescriptorData, sceneDescriptorDataLength, _sceneContext->isBigEndian);
|
||||||
|
|
||||||
_sceneDescription.flags = readS.readSint16();
|
_sceneDescription.flags = readS.readSint16();
|
||||||
_sceneDescription.resListRN = readS.readSint16();
|
_sceneDescription.resourceListResourceId = readS.readSint16();
|
||||||
_sceneDescription.endSlope = readS.readSint16();
|
_sceneDescription.endSlope = readS.readSint16();
|
||||||
_sceneDescription.beginSlope = readS.readSint16();
|
_sceneDescription.beginSlope = readS.readSint16();
|
||||||
_sceneDescription.scriptModuleNumber = readS.readUint16();
|
_sceneDescription.scriptModuleNumber = readS.readUint16();
|
||||||
_sceneDescription.sceneScriptEntrypointNumber = readS.readUint16();
|
_sceneDescription.sceneScriptEntrypointNumber = readS.readUint16();
|
||||||
_sceneDescription.startScriptEntrypointNumber = readS.readUint16();
|
_sceneDescription.startScriptEntrypointNumber = readS.readUint16();
|
||||||
_sceneDescription.musicRN = readS.readSint16();
|
_sceneDescription.musicResourceId = readS.readSint16();
|
||||||
|
|
||||||
RSC_FreeResource(scene_desc_data);
|
free(sceneDescriptorData);
|
||||||
|
|
||||||
return SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int Scene::loadSceneResourceList(uint32 reslist_rn) {
|
void Scene::loadSceneResourceList(uint32 resourceId) {
|
||||||
byte *resource_list;
|
byte *resourceListData;
|
||||||
size_t resource_list_len;
|
size_t resourceListDataLength;
|
||||||
int result;
|
size_t i;
|
||||||
int i;
|
|
||||||
|
|
||||||
// Load the scene resource table
|
// Load the scene resource table
|
||||||
result = RSC_LoadResource(_sceneContext, reslist_rn, &resource_list, &resource_list_len);
|
_vm->_resource->loadResource(_sceneContext, resourceId, resourceListData, resourceListDataLength);
|
||||||
if (result != SUCCESS) {
|
|
||||||
warning("Scene::loadSceneResourceList(): Error: couldn't load scene resource list");
|
|
||||||
return FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
MemoryReadStreamEndian readS(resource_list, resource_list_len, IS_BIG_ENDIAN);
|
MemoryReadStreamEndian readS(resourceListData, resourceListDataLength, _sceneContext->isBigEndian);
|
||||||
|
|
||||||
// Allocate memory for scene resource list
|
// Allocate memory for scene resource list
|
||||||
_resListEntries = resource_list_len / SAGA_RESLIST_ENTRY_LEN;
|
_resourceListCount = resourceListDataLength / SAGA_RESLIST_ENTRY_LEN;
|
||||||
debug(3, "Scene resource list contains %d entries.", _resListEntries);
|
debug(3, "Scene resource list contains %i entries", _resourceListCount);
|
||||||
_resList = (SCENE_RESLIST *)calloc(_resListEntries, sizeof(*_resList));
|
_resourceList = (SceneResourceData *)calloc(_resourceListCount, sizeof(*_resourceList));
|
||||||
|
|
||||||
if (_resList == NULL) {
|
|
||||||
memoryError("Scene::loadSceneResourceList()");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load scene resource list from raw scene
|
// Load scene resource list from raw scene
|
||||||
// resource table
|
// resource table
|
||||||
debug(3, "Loading scene resource list...");
|
debug(3, "Loading scene resource list");
|
||||||
|
|
||||||
for (i = 0; i < _resListEntries; i++) {
|
for (i = 0; i < _resourceListCount; i++) {
|
||||||
_resList[i].res_number = readS.readUint16();
|
_resourceList[i].resourceId = readS.readUint16();
|
||||||
_resList[i].res_type = readS.readUint16();
|
_resourceList[i].reourceType = readS.readUint16();
|
||||||
|
// demo version may contain invalid resourceId
|
||||||
|
_resourceList[i].invalid = !_vm->_resource->validResourceId(_sceneContext, _resourceList[i].resourceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
RSC_FreeResource(resource_list);
|
free(resourceListData);
|
||||||
|
|
||||||
return SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int Scene::processSceneResources() {
|
void Scene::processSceneResources() {
|
||||||
byte *resourceData;
|
byte *resourceData;
|
||||||
uint16 resourceDataLength;
|
uint16 resourceDataLength;
|
||||||
const byte *pal_p;
|
const byte *palPointer;
|
||||||
int i;
|
size_t i;
|
||||||
|
|
||||||
// Process the scene resource list
|
// Process the scene resource list
|
||||||
for (i = 0; i < _resListEntries; i++) {
|
for (i = 0; i < _resourceListCount; i++) {
|
||||||
resourceData = _resList[i].res_data;
|
if (_resourceList[i].invalid) {
|
||||||
resourceDataLength = _resList[i].res_data_len;
|
continue;
|
||||||
switch (_resList[i].res_type) {
|
}
|
||||||
|
resourceData = _resourceList[i].buffer;
|
||||||
|
resourceDataLength = _resourceList[i].size;
|
||||||
|
switch (_resourceList[i].reourceType) {
|
||||||
|
case SAGA_ACTOR:
|
||||||
|
break;
|
||||||
|
case SAGA_OBJECT:
|
||||||
|
break;
|
||||||
case SAGA_BG_IMAGE: // Scene background resource
|
case SAGA_BG_IMAGE: // Scene background resource
|
||||||
if (_bg.loaded) {
|
if (_bg.loaded) {
|
||||||
error("Scene::processSceneResources(): Multiple background resources encountered");
|
error("Scene::processSceneResources() Multiple background resources encountered");
|
||||||
}
|
}
|
||||||
|
|
||||||
debug(3, "Loading background resource.");
|
debug(3, "Loading background resource.");
|
||||||
|
@ -745,12 +717,11 @@ int Scene::processSceneResources() {
|
||||||
&_bg.buf_len,
|
&_bg.buf_len,
|
||||||
&_bg.w,
|
&_bg.w,
|
||||||
&_bg.h) != SUCCESS) {
|
&_bg.h) != SUCCESS) {
|
||||||
warning("Scene::ProcessSceneResources(): Error loading background resource: %u", _resList[i].res_number);
|
error("Scene::processSceneResources() Error loading background resource %i", _resourceList[i].resourceId);
|
||||||
return FAILURE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pal_p = _vm->getImagePal(_bg.res_buf, _bg.res_len);
|
palPointer = _vm->getImagePal(_bg.res_buf, _bg.res_len);
|
||||||
memcpy(_bg.pal, pal_p, sizeof(_bg.pal));
|
memcpy(_bg.pal, palPointer, sizeof(_bg.pal));
|
||||||
break;
|
break;
|
||||||
case SAGA_BG_MASK: // Scene background mask resource
|
case SAGA_BG_MASK: // Scene background mask resource
|
||||||
if (_bgMask.loaded) {
|
if (_bgMask.loaded) {
|
||||||
|
@ -826,7 +797,7 @@ int Scene::processSceneResources() {
|
||||||
case SAGA_ANIM_6:
|
case SAGA_ANIM_6:
|
||||||
case SAGA_ANIM_7:
|
case SAGA_ANIM_7:
|
||||||
{
|
{
|
||||||
uint16 animId = _resList[i].res_type - SAGA_ANIM_1;
|
uint16 animId = _resourceList[i].reourceType - SAGA_ANIM_1;
|
||||||
|
|
||||||
debug(3, "Loading animation resource animId=%i", animId);
|
debug(3, "Loading animation resource animId=%i", animId);
|
||||||
|
|
||||||
|
@ -851,7 +822,7 @@ int Scene::processSceneResources() {
|
||||||
loadSceneEntryList(resourceData, resourceDataLength);
|
loadSceneEntryList(resourceData, resourceDataLength);
|
||||||
break;
|
break;
|
||||||
case SAGA_FACES:
|
case SAGA_FACES:
|
||||||
_vm->_interface->loadScenePortraits(_resList[i].res_number);
|
_vm->_interface->loadScenePortraits(_resourceList[i].resourceId);
|
||||||
break;
|
break;
|
||||||
case SAGA_PALETTE:
|
case SAGA_PALETTE:
|
||||||
{
|
{
|
||||||
|
@ -859,7 +830,7 @@ int Scene::processSceneResources() {
|
||||||
byte *palPtr = resourceData;
|
byte *palPtr = resourceData;
|
||||||
|
|
||||||
if (resourceDataLength < 3 * PAL_ENTRIES)
|
if (resourceDataLength < 3 * PAL_ENTRIES)
|
||||||
error("Too small scene palette: %d", resourceDataLength);
|
error("Too small scene palette %i", resourceDataLength);
|
||||||
|
|
||||||
for (uint16 c = 0; c < PAL_ENTRIES; c++) {
|
for (uint16 c = 0; c < PAL_ENTRIES; c++) {
|
||||||
pal[c].red = *palPtr++;
|
pal[c].red = *palPtr++;
|
||||||
|
@ -870,11 +841,10 @@ int Scene::processSceneResources() {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
warning("Scene::ProcessSceneResources(): Encountered unknown resource type: %d", _resList[i].res_type);
|
error("Scene::ProcessSceneResources() Encountered unknown resource type %i", _resourceList[i].reourceType);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scene::draw() {
|
void Scene::draw() {
|
||||||
|
@ -902,7 +872,7 @@ void Scene::endScene() {
|
||||||
Surface *backBuffer;
|
Surface *backBuffer;
|
||||||
Surface *backGroundSurface;
|
Surface *backGroundSurface;
|
||||||
Rect rect;
|
Rect rect;
|
||||||
int i;
|
size_t i;
|
||||||
|
|
||||||
if (!_sceneLoaded)
|
if (!_sceneLoaded)
|
||||||
return;
|
return;
|
||||||
|
@ -936,12 +906,12 @@ void Scene::endScene() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Free scene resource list
|
// Free scene resource list
|
||||||
for (i = 0; i < _resListEntries; i++) {
|
for (i = 0; i < _resourceListCount; i++) {
|
||||||
RSC_FreeResource(_resList[i].res_data);
|
free(_resourceList[i].buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_loadDescription) {
|
if (_loadDescription) {
|
||||||
free(_resList);
|
free(_resourceList);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Free animation info list
|
// Free animation info list
|
||||||
|
@ -977,23 +947,6 @@ void Scene::cmdSceneChange(int argc, const char **argv) {
|
||||||
changeScene(scene_num, 0, kTransitionNoFade);
|
changeScene(scene_num, 0, kTransitionNoFade);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scene::cmdSceneInfo() {
|
|
||||||
const char *fmt = "%-20s %d\n";
|
|
||||||
|
|
||||||
_vm->_console->DebugPrintf(fmt, "Scene number:", _sceneNumber);
|
|
||||||
_vm->_console->DebugPrintf(fmt, "Descriptor ResourceId:", _sceneResourceId);
|
|
||||||
_vm->_console->DebugPrintf("-------------------------\n");
|
|
||||||
_vm->_console->DebugPrintf(fmt, "Flags:", _sceneDescription.flags);
|
|
||||||
_vm->_console->DebugPrintf(fmt, "Resource list R#:", _sceneDescription.resListRN);
|
|
||||||
_vm->_console->DebugPrintf(fmt, "End slope:", _sceneDescription.endSlope);
|
|
||||||
_vm->_console->DebugPrintf(fmt, "Begin slope:", _sceneDescription.beginSlope);
|
|
||||||
_vm->_console->DebugPrintf(fmt, "scriptModuleNumber:", _sceneDescription.scriptModuleNumber);
|
|
||||||
_vm->_console->DebugPrintf(fmt, "sceneScriptEntrypointNumber:", _sceneDescription.sceneScriptEntrypointNumber);
|
|
||||||
_vm->_console->DebugPrintf(fmt, "startScriptEntrypointNumber:", _sceneDescription.startScriptEntrypointNumber);
|
|
||||||
_vm->_console->DebugPrintf(fmt, "Music R#", _sceneDescription.musicRN);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Scene::cmdActionMapInfo() {
|
void Scene::cmdActionMapInfo() {
|
||||||
_actionMap->cmdInfo();
|
_actionMap->cmdInfo();
|
||||||
}
|
}
|
||||||
|
@ -1008,7 +961,7 @@ void Scene::loadSceneEntryList(const byte* resourcePointer, size_t resourceLengt
|
||||||
|
|
||||||
_entryList.entryListCount = resourceLength / 8;
|
_entryList.entryListCount = resourceLength / 8;
|
||||||
|
|
||||||
MemoryReadStreamEndian readS(resourcePointer, resourceLength, IS_BIG_ENDIAN);
|
MemoryReadStreamEndian readS(resourcePointer, resourceLength, _sceneContext->isBigEndian);
|
||||||
|
|
||||||
|
|
||||||
if (_entryList.entryList)
|
if (_entryList.entryList)
|
||||||
|
|
41
saga/scene.h
41
saga/scene.h
|
@ -59,6 +59,8 @@ enum SCENE_PROC_PARAMS {
|
||||||
|
|
||||||
// Resource type numbers
|
// Resource type numbers
|
||||||
enum SAGAResourceTypes {
|
enum SAGAResourceTypes {
|
||||||
|
SAGA_ACTOR = 0,
|
||||||
|
SAGA_OBJECT = 1,
|
||||||
SAGA_BG_IMAGE = 2,
|
SAGA_BG_IMAGE = 2,
|
||||||
SAGA_BG_MASK = 3,
|
SAGA_BG_MASK = 3,
|
||||||
SAGA_STRINGS = 5,
|
SAGA_STRINGS = 5,
|
||||||
|
@ -84,26 +86,27 @@ enum SAGAResourceTypes {
|
||||||
|
|
||||||
#define SAGA_RESLIST_ENTRY_LEN 4
|
#define SAGA_RESLIST_ENTRY_LEN 4
|
||||||
|
|
||||||
struct SCENE_RESLIST {
|
struct SceneResourceData {
|
||||||
uint32 res_number;
|
uint32 resourceId;
|
||||||
int res_type;
|
int reourceType;
|
||||||
byte *res_data;
|
byte *buffer;
|
||||||
size_t res_data_len;
|
size_t size;
|
||||||
|
bool invalid;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define SAGA_SCENE_DESC_LEN 16
|
#define SAGA_SCENE_DESC_LEN 16
|
||||||
|
|
||||||
struct SceneDescription {
|
struct SceneDescription {
|
||||||
int16 flags;
|
int16 flags;
|
||||||
int16 resListRN;
|
int16 resourceListResourceId;
|
||||||
int16 endSlope;
|
int16 endSlope;
|
||||||
int16 beginSlope;
|
int16 beginSlope;
|
||||||
uint16 scriptModuleNumber;
|
uint16 scriptModuleNumber;
|
||||||
uint16 sceneScriptEntrypointNumber;
|
uint16 sceneScriptEntrypointNumber;
|
||||||
uint16 startScriptEntrypointNumber;
|
uint16 startScriptEntrypointNumber;
|
||||||
int16 musicRN;
|
int16 musicResourceId;
|
||||||
SCENE_RESLIST *resList;
|
SceneResourceData *resourceList;
|
||||||
size_t resListCnt;
|
size_t resourceListCount;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SceneEntry {
|
struct SceneEntry {
|
||||||
|
@ -209,7 +212,6 @@ class Scene {
|
||||||
~Scene();
|
~Scene();
|
||||||
|
|
||||||
// Console functions
|
// Console functions
|
||||||
void cmdSceneInfo();
|
|
||||||
void cmdActionMapInfo();
|
void cmdActionMapInfo();
|
||||||
void cmdObjectMapInfo();
|
void cmdObjectMapInfo();
|
||||||
|
|
||||||
|
@ -241,7 +243,10 @@ class Scene {
|
||||||
void initDoorsState();
|
void initDoorsState();
|
||||||
|
|
||||||
void getBGInfo(BGInfo &bgInfo);
|
void getBGInfo(BGInfo &bgInfo);
|
||||||
int getBGPal(PalEntry **pal);
|
void getBGPal(PalEntry *&pal) const {
|
||||||
|
pal = (PalEntry *)_bg.pal;
|
||||||
|
}
|
||||||
|
|
||||||
void getSlopes(int &beginSlope, int &endSlope);
|
void getSlopes(int &beginSlope, int &endSlope);
|
||||||
|
|
||||||
void clearSceneQueue(void) {
|
void clearSceneQueue(void) {
|
||||||
|
@ -249,7 +254,6 @@ class Scene {
|
||||||
}
|
}
|
||||||
void changeScene(uint16 sceneNumber, int actorsEntrance, SceneTransitionType transitionType);
|
void changeScene(uint16 sceneNumber, int actorsEntrance, SceneTransitionType transitionType);
|
||||||
|
|
||||||
bool initialized() const { return _initialized; }
|
|
||||||
bool isSceneLoaded() const { return _sceneLoaded; }
|
bool isSceneLoaded() const { return _sceneLoaded; }
|
||||||
|
|
||||||
|
|
||||||
|
@ -266,16 +270,15 @@ class Scene {
|
||||||
void drawTextList(Surface *ds);
|
void drawTextList(Surface *ds);
|
||||||
private:
|
private:
|
||||||
void loadScene(LoadSceneParams *loadSceneParams);
|
void loadScene(LoadSceneParams *loadSceneParams);
|
||||||
int loadSceneDescriptor(uint32 res_number);
|
void loadSceneDescriptor(uint32 resourceId);
|
||||||
int loadSceneResourceList(uint32 res_number);
|
void loadSceneResourceList(uint32 resourceId);
|
||||||
void loadSceneEntryList(const byte* resourcePointer, size_t resourceLength);
|
void loadSceneEntryList(const byte* resourcePointer, size_t resourceLength);
|
||||||
int processSceneResources();
|
void processSceneResources();
|
||||||
|
|
||||||
|
|
||||||
SagaEngine *_vm;
|
SagaEngine *_vm;
|
||||||
bool _initialized;
|
|
||||||
|
|
||||||
RSCFILE_CONTEXT *_sceneContext;
|
ResourceContext *_sceneContext;
|
||||||
int *_sceneLUT;
|
int *_sceneLUT;
|
||||||
int _sceneCount;
|
int _sceneCount;
|
||||||
SceneQueueList _sceneQueue;
|
SceneQueueList _sceneQueue;
|
||||||
|
@ -287,8 +290,8 @@ class Scene {
|
||||||
bool _inGame;
|
bool _inGame;
|
||||||
bool _loadDescription;
|
bool _loadDescription;
|
||||||
SceneDescription _sceneDescription;
|
SceneDescription _sceneDescription;
|
||||||
int _resListEntries;
|
size_t _resourceListCount;
|
||||||
SCENE_RESLIST *_resList;
|
SceneResourceData *_resourceList;
|
||||||
SceneProc *_sceneProc;
|
SceneProc *_sceneProc;
|
||||||
SceneImage _bg;
|
SceneImage _bg;
|
||||||
SceneImage _bgMask;
|
SceneImage _bgMask;
|
||||||
|
|
128
saga/script.cpp
128
saga/script.cpp
|
@ -25,7 +25,6 @@
|
||||||
#include "saga/saga.h"
|
#include "saga/saga.h"
|
||||||
|
|
||||||
#include "saga/gfx.h"
|
#include "saga/gfx.h"
|
||||||
#include "saga/rscfile_mod.h"
|
|
||||||
#include "saga/console.h"
|
#include "saga/console.h"
|
||||||
|
|
||||||
#include "saga/script.h"
|
#include "saga/script.h"
|
||||||
|
@ -37,25 +36,22 @@
|
||||||
#include "saga/actor.h"
|
#include "saga/actor.h"
|
||||||
#include "saga/objectmap.h"
|
#include "saga/objectmap.h"
|
||||||
#include "saga/isomap.h"
|
#include "saga/isomap.h"
|
||||||
|
#include "saga/rscfile.h"
|
||||||
|
|
||||||
namespace Saga {
|
namespace Saga {
|
||||||
|
|
||||||
// Initializes the scripting module.
|
// Initializes the scripting module.
|
||||||
// Loads script resource look-up table, initializes script data system
|
// Loads script resource look-up table, initializes script data system
|
||||||
Script::Script(SagaEngine *vm) : _vm(vm){
|
Script::Script(SagaEngine *vm) : _vm(vm) {
|
||||||
RSCFILE_CONTEXT *resourceContext;
|
ResourceContext *resourceContext;
|
||||||
byte *resourcePointer;
|
byte *resourcePointer;
|
||||||
size_t resourceLength;
|
size_t resourceLength;
|
||||||
int prevTell;
|
int prevTell;
|
||||||
int result;
|
|
||||||
int i, j;
|
int i, j;
|
||||||
byte *stringsPointer;
|
byte *stringsPointer;
|
||||||
size_t stringsLength;
|
size_t stringsLength;
|
||||||
|
|
||||||
//initialize member variables
|
//initialize member variables
|
||||||
_dbg_thread = 0;
|
|
||||||
_dbg_singlestep = 0;
|
|
||||||
_scriptContext = 0;
|
|
||||||
_voiceLUTPresent = false;
|
_voiceLUTPresent = false;
|
||||||
|
|
||||||
_abortEnabled = true;
|
_abortEnabled = true;
|
||||||
|
@ -78,21 +74,19 @@ Script::Script(SagaEngine *vm) : _vm(vm){
|
||||||
|
|
||||||
debug(8, "Initializing scripting subsystem");
|
debug(8, "Initializing scripting subsystem");
|
||||||
// Load script resource file context
|
// Load script resource file context
|
||||||
_scriptContext = _vm->getFileContext(GAME_SCRIPTFILE, 0);
|
_scriptContext = _vm->_resource->getContext(GAME_SCRIPTFILE);
|
||||||
if (_scriptContext == NULL) {
|
if (_scriptContext == NULL) {
|
||||||
error("Script::Script() Couldn't get script file context");
|
error("Script::Script() script context not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
resourceContext = _vm->getFileContext(GAME_RESOURCEFILE, 0);
|
resourceContext = _vm->_resource->getContext(GAME_RESOURCEFILE);
|
||||||
if (resourceContext == NULL) {
|
if (resourceContext == NULL) {
|
||||||
error("Script::Script() Couldn't get resource file context");
|
error("Script::Script() resource context not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
debug(3, "Loading module LUT from resource %u.", _vm->getResourceDescription()->moduleLUTResourceId);
|
debug(3, "Loading module LUT from resource %i", _vm->getResourceDescription()->moduleLUTResourceId);
|
||||||
result = RSC_LoadResource(resourceContext, _vm->getResourceDescription()->moduleLUTResourceId, &resourcePointer, &resourceLength);
|
_vm->_resource->loadResource(resourceContext, _vm->getResourceDescription()->moduleLUTResourceId, resourcePointer, resourceLength);
|
||||||
if (result != SUCCESS) {
|
|
||||||
error("Script::Script() Couldn't load module LUT resource");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create logical script LUT from resource
|
// Create logical script LUT from resource
|
||||||
if (resourceLength % S_LUT_ENTRYLEN_ITECD == 0) {
|
if (resourceLength % S_LUT_ENTRYLEN_ITECD == 0) {
|
||||||
|
@ -100,13 +94,13 @@ Script::Script(SagaEngine *vm) : _vm(vm){
|
||||||
} else if (resourceLength % S_LUT_ENTRYLEN_ITEDISK == 0) {
|
} else if (resourceLength % S_LUT_ENTRYLEN_ITEDISK == 0) {
|
||||||
_modulesLUTEntryLen = S_LUT_ENTRYLEN_ITEDISK;
|
_modulesLUTEntryLen = S_LUT_ENTRYLEN_ITEDISK;
|
||||||
} else {
|
} else {
|
||||||
error("Script::Script() Invalid script lookup table length (%d)", resourceLength);
|
error("Script::Script() Invalid script lookup table length (%i)", resourceLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate number of entries
|
// Calculate number of entries
|
||||||
_modulesCount = resourceLength / _modulesLUTEntryLen;
|
_modulesCount = resourceLength / _modulesLUTEntryLen;
|
||||||
|
|
||||||
debug(3, "LUT has %d entries.", _modulesCount);
|
debug(3, "LUT has %i entries", _modulesCount);
|
||||||
|
|
||||||
// Allocate space for logical LUT
|
// Allocate space for logical LUT
|
||||||
_modules = (ModuleData *)malloc(_modulesCount * sizeof(*_modules));
|
_modules = (ModuleData *)malloc(_modulesCount * sizeof(*_modules));
|
||||||
|
@ -115,7 +109,7 @@ Script::Script(SagaEngine *vm) : _vm(vm){
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert LUT resource to logical LUT
|
// Convert LUT resource to logical LUT
|
||||||
MemoryReadStreamEndian scriptS(resourcePointer, resourceLength, IS_BIG_ENDIAN);
|
MemoryReadStreamEndian scriptS(resourcePointer, resourceLength, resourceContext->isBigEndian);
|
||||||
for (i = 0; i < _modulesCount; i++) {
|
for (i = 0; i < _modulesCount; i++) {
|
||||||
memset(&_modules[i], 0, sizeof(ModuleData));
|
memset(&_modules[i], 0, sizeof(ModuleData));
|
||||||
|
|
||||||
|
@ -136,7 +130,7 @@ Script::Script(SagaEngine *vm) : _vm(vm){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RSC_FreeResource(resourcePointer);
|
free(resourcePointer);
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
//
|
//
|
||||||
|
@ -150,27 +144,17 @@ Script::Script(SagaEngine *vm) : _vm(vm){
|
||||||
// Or maybe I'm looking at the wrong resource. I found the IHNM one by
|
// Or maybe I'm looking at the wrong resource. I found the IHNM one by
|
||||||
// trial and error...
|
// trial and error...
|
||||||
|
|
||||||
result = RSC_LoadResource(resourceContext, _vm->getResourceDescription()->mainStringsResourceId, &stringsPointer, &stringsLength);
|
_vm->_resource->loadResource(resourceContext, _vm->getResourceDescription()->mainStringsResourceId, stringsPointer, stringsLength);
|
||||||
|
|
||||||
if ((result != SUCCESS) || (stringsLength == 0)) {
|
|
||||||
error("Error loading strings list resource");
|
|
||||||
}
|
|
||||||
|
|
||||||
_vm->loadStrings(_mainStrings, stringsPointer, stringsLength);
|
_vm->loadStrings(_mainStrings, stringsPointer, stringsLength);
|
||||||
RSC_FreeResource(stringsPointer);
|
free(stringsPointer);
|
||||||
|
|
||||||
setupScriptFuncList();
|
setupScriptFuncList();
|
||||||
|
|
||||||
_initialized = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shut down script module gracefully; free all allocated module resources
|
// Shut down script module gracefully; free all allocated module resources
|
||||||
Script::~Script() {
|
Script::~Script() {
|
||||||
|
|
||||||
if (!_initialized) {
|
|
||||||
error("Script not initialized");
|
|
||||||
}
|
|
||||||
|
|
||||||
debug(8, "Shutting down scripting subsystem.");
|
debug(8, "Shutting down scripting subsystem.");
|
||||||
|
|
||||||
_mainStrings.freeMem();
|
_mainStrings.freeMem();
|
||||||
|
@ -179,14 +163,11 @@ Script::~Script() {
|
||||||
free(_modules);
|
free(_modules);
|
||||||
|
|
||||||
free(_commonBuffer);
|
free(_commonBuffer);
|
||||||
|
|
||||||
_initialized = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Script::loadModule(int scriptModuleNumber) {
|
void Script::loadModule(int scriptModuleNumber) {
|
||||||
byte *resourcePointer;
|
byte *resourcePointer;
|
||||||
size_t resourceLength;
|
size_t resourceLength;
|
||||||
int result;
|
|
||||||
|
|
||||||
// Validate script number
|
// Validate script number
|
||||||
if ((scriptModuleNumber < 0) || (scriptModuleNumber >= _modulesCount)) {
|
if ((scriptModuleNumber < 0) || (scriptModuleNumber >= _modulesCount)) {
|
||||||
|
@ -200,30 +181,21 @@ void Script::loadModule(int scriptModuleNumber) {
|
||||||
// Initialize script data structure
|
// Initialize script data structure
|
||||||
debug(3, "Loading script module #%d", scriptModuleNumber);
|
debug(3, "Loading script module #%d", scriptModuleNumber);
|
||||||
|
|
||||||
result = RSC_LoadResource(_scriptContext, _modules[scriptModuleNumber].scriptResourceId, &resourcePointer, &resourceLength);
|
_vm->_resource->loadResource(_scriptContext, _modules[scriptModuleNumber].scriptResourceId, resourcePointer, resourceLength);
|
||||||
if (result != SUCCESS) {
|
|
||||||
error("Script::loadModule() unable to load module base resource");
|
|
||||||
}
|
|
||||||
|
|
||||||
loadModuleBase(_modules[scriptModuleNumber], resourcePointer, resourceLength);
|
loadModuleBase(_modules[scriptModuleNumber], resourcePointer, resourceLength);
|
||||||
RSC_FreeResource(resourcePointer);
|
free(resourcePointer);
|
||||||
|
|
||||||
result = RSC_LoadResource(_scriptContext, _modules[scriptModuleNumber].stringsResourceId, &resourcePointer, &resourceLength);
|
_vm->_resource->loadResource(_scriptContext, _modules[scriptModuleNumber].stringsResourceId, resourcePointer, resourceLength);
|
||||||
if ((result != SUCCESS) || (resourceLength == 0)) {
|
|
||||||
error("Script::loadModule() Error loading strings list resource");
|
|
||||||
}
|
|
||||||
|
|
||||||
_vm->loadStrings(_modules[scriptModuleNumber].strings, resourcePointer, resourceLength);
|
_vm->loadStrings(_modules[scriptModuleNumber].strings, resourcePointer, resourceLength);
|
||||||
RSC_FreeResource(resourcePointer);
|
free(resourcePointer);
|
||||||
|
|
||||||
if (_modules[scriptModuleNumber].voicesResourceId > 0) {
|
if (_modules[scriptModuleNumber].voicesResourceId > 0) {
|
||||||
result = RSC_LoadResource(_scriptContext, _modules[scriptModuleNumber].voicesResourceId, &resourcePointer, &resourceLength);
|
_vm->_resource->loadResource(_scriptContext, _modules[scriptModuleNumber].voicesResourceId, resourcePointer, resourceLength);
|
||||||
if (result != SUCCESS) {
|
|
||||||
error("Script::loadModule() Error loading voice LUT resource");
|
|
||||||
}
|
|
||||||
|
|
||||||
loadModuleVoiceLUT(_modules[scriptModuleNumber], resourcePointer, resourceLength);
|
loadModuleVoiceLUT(_modules[scriptModuleNumber], resourcePointer, resourceLength);
|
||||||
RSC_FreeResource(resourcePointer);
|
free(resourcePointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
_modules[scriptModuleNumber].staticOffset = _staticSize;
|
_modules[scriptModuleNumber].staticOffset = _staticSize;
|
||||||
|
@ -254,7 +226,7 @@ void Script::loadModuleBase(ModuleData &module, const byte *resourcePointer, siz
|
||||||
|
|
||||||
memcpy(module.moduleBase, resourcePointer, resourceLength);
|
memcpy(module.moduleBase, resourcePointer, resourceLength);
|
||||||
|
|
||||||
MemoryReadStreamEndian scriptS(module.moduleBase, module.moduleBaseSize, IS_BIG_ENDIAN);
|
MemoryReadStreamEndian scriptS(module.moduleBase, module.moduleBaseSize, _scriptContext->isBigEndian);
|
||||||
|
|
||||||
module.entryPointsCount = scriptS.readUint16();
|
module.entryPointsCount = scriptS.readUint16();
|
||||||
scriptS.readUint16(); //skip
|
scriptS.readUint16(); //skip
|
||||||
|
@ -307,60 +279,13 @@ void Script::loadModuleVoiceLUT(ModuleData &module, const byte *resourcePointer,
|
||||||
error("Script::loadModuleVoiceLUT() not enough memory");
|
error("Script::loadModuleVoiceLUT() not enough memory");
|
||||||
}
|
}
|
||||||
|
|
||||||
MemoryReadStreamEndian scriptS(resourcePointer, resourceLength, IS_BIG_ENDIAN);
|
MemoryReadStreamEndian scriptS(resourcePointer, resourceLength, _scriptContext->isBigEndian);
|
||||||
|
|
||||||
for (i = 0; i < module.voiceLUT.voicesCount; i++) {
|
for (i = 0; i < module.voiceLUT.voicesCount; i++) {
|
||||||
module.voiceLUT.voices[i] = scriptS.readUint16();
|
module.voiceLUT.voices[i] = scriptS.readUint16();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Script::scriptInfo() {
|
|
||||||
/* uint32 n_entrypoints;
|
|
||||||
uint32 i;
|
|
||||||
char *name_ptr;
|
|
||||||
|
|
||||||
if (currentScript() == NULL) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!currentScript()->loaded) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
n_entrypoints = currentScript()->bytecode->n_entrypoints;
|
|
||||||
|
|
||||||
_vm->_console->DebugPrintf("Current script contains %d entrypoints:\n", n_entrypoints);
|
|
||||||
|
|
||||||
for (i = 0; i < n_entrypoints; i++) {
|
|
||||||
name_ptr = (char *)currentScript()->bytecode->bytecode_p +
|
|
||||||
currentScript()->bytecode->entrypoints[i].name_offset;
|
|
||||||
_vm->_console->DebugPrintf("%lu: %s\n", i, name_ptr);
|
|
||||||
}*/
|
|
||||||
}
|
|
||||||
|
|
||||||
void Script::scriptExec(int argc, const char **argv) {
|
|
||||||
/* uint16 ep_num;
|
|
||||||
|
|
||||||
ep_num = atoi(argv[1]);
|
|
||||||
|
|
||||||
if (_dbg_thread == NULL) {
|
|
||||||
_vm->_console->DebugPrintf("Creating debug thread...\n");
|
|
||||||
_dbg_thread = createThread();
|
|
||||||
if (_dbg_thread == NULL) {
|
|
||||||
_vm->_console->DebugPrintf("Thread creation failed.\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ep_num >= currentScript()->bytecode->n_entrypoints) {
|
|
||||||
_vm->_console->DebugPrintf("Invalid entrypoint.\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
executeThread(_dbg_thread, ep_num);*/
|
|
||||||
}
|
|
||||||
|
|
||||||
// verb
|
// verb
|
||||||
void Script::showVerb(int statusColor) {
|
void Script::showVerb(int statusColor) {
|
||||||
const char *verbName;
|
const char *verbName;
|
||||||
|
@ -818,9 +743,4 @@ void Script::whichObject(const Point& mousePoint) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// console wrappers
|
|
||||||
void Script::CF_script_togglestep() {
|
|
||||||
_dbg_singlestep = !_dbg_singlestep;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // End of namespace Saga
|
} // End of namespace Saga
|
||||||
|
|
|
@ -346,12 +346,9 @@ public:
|
||||||
Script(SagaEngine *vm);
|
Script(SagaEngine *vm);
|
||||||
~Script();
|
~Script();
|
||||||
|
|
||||||
void CF_script_togglestep();
|
|
||||||
|
|
||||||
void loadModule(int scriptModuleNumber);
|
void loadModule(int scriptModuleNumber);
|
||||||
void freeModules();
|
void freeModules();
|
||||||
|
|
||||||
bool isInitialized() const { return _initialized; }
|
|
||||||
bool isVoiceLUTPresent() const { return _voiceLUTPresent; }
|
bool isVoiceLUTPresent() const { return _voiceLUTPresent; }
|
||||||
|
|
||||||
void doVerb();
|
void doVerb();
|
||||||
|
@ -377,15 +374,11 @@ public:
|
||||||
_currentObject[0] = _currentObject[0] = ID_NOTHING;
|
_currentObject[0] = _currentObject[0] = ID_NOTHING;
|
||||||
setPointerVerb();
|
setPointerVerb();
|
||||||
}
|
}
|
||||||
|
|
||||||
void scriptInfo();
|
|
||||||
void scriptExec(int argc, const char **argv);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SagaEngine *_vm;
|
SagaEngine *_vm;
|
||||||
bool _initialized;
|
|
||||||
bool _voiceLUTPresent;
|
bool _voiceLUTPresent;
|
||||||
RSCFILE_CONTEXT *_scriptContext;
|
ResourceContext *_scriptContext;
|
||||||
|
|
||||||
uint16 _modulesLUTEntryLen;
|
uint16 _modulesLUTEntryLen;
|
||||||
ModuleData *_modules;
|
ModuleData *_modules;
|
||||||
|
@ -422,15 +415,10 @@ public:
|
||||||
bool _skipSpeeches;
|
bool _skipSpeeches;
|
||||||
bool _abortEnabled;
|
bool _abortEnabled;
|
||||||
|
|
||||||
int _dbg_singlestep;
|
|
||||||
int _dbg_dostep;
|
|
||||||
ScriptThread *_dbg_thread;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ScriptThread *createThread(uint16 scriptModuleNumber, uint16 scriptEntryPointNumber);
|
ScriptThread *createThread(uint16 scriptModuleNumber, uint16 scriptEntryPointNumber);
|
||||||
int executeThread(ScriptThread *thread, int entrypointNumber);
|
int executeThread(ScriptThread *thread, int entrypointNumber);
|
||||||
void executeThreads(uint msec);
|
void executeThreads(uint msec);
|
||||||
int SThreadDebugStep();
|
|
||||||
void completeThread(void);
|
void completeThread(void);
|
||||||
void abortAllThreads(void);
|
void abortAllThreads(void);
|
||||||
|
|
||||||
|
@ -460,7 +448,6 @@ private:
|
||||||
const ScriptFunctionDescription *_scriptFunctionsList;
|
const ScriptFunctionDescription *_scriptFunctionsList;
|
||||||
|
|
||||||
void setupScriptFuncList(void);
|
void setupScriptFuncList(void);
|
||||||
int SDebugPrintInstr(ScriptThread *thread);
|
|
||||||
|
|
||||||
void sfPutString(SCRIPTFUNC_PARAMS);
|
void sfPutString(SCRIPTFUNC_PARAMS);
|
||||||
void sfWait(SCRIPTFUNC_PARAMS);
|
void sfWait(SCRIPTFUNC_PARAMS);
|
||||||
|
|
|
@ -44,6 +44,7 @@
|
||||||
|
|
||||||
#include "saga/scene.h"
|
#include "saga/scene.h"
|
||||||
#include "saga/isomap.h"
|
#include "saga/isomap.h"
|
||||||
|
#include "saga/resnames.h"
|
||||||
|
|
||||||
#include "common/config-manager.h"
|
#include "common/config-manager.h"
|
||||||
|
|
||||||
|
@ -1271,7 +1272,7 @@ void Script::sfPlacard(SCRIPTFUNC_PARAMS) {
|
||||||
|
|
||||||
q_event = _vm->_events->chain(q_event, &event);
|
q_event = _vm->_events->chain(q_event, &event);
|
||||||
|
|
||||||
_vm->_scene->getBGPal(&pal);
|
_vm->_scene->getBGPal(pal);
|
||||||
|
|
||||||
event.type = IMMEDIATE_EVENT;
|
event.type = IMMEDIATE_EVENT;
|
||||||
event.code = PAL_EVENT;
|
event.code = PAL_EVENT;
|
||||||
|
@ -1327,7 +1328,7 @@ void Script::sfPlacardOff(SCRIPTFUNC_PARAMS) {
|
||||||
|
|
||||||
q_event = _vm->_events->chain(q_event, &event);
|
q_event = _vm->_events->chain(q_event, &event);
|
||||||
|
|
||||||
_vm->_scene->getBGPal(&pal);
|
_vm->_scene->getBGPal(pal);
|
||||||
|
|
||||||
event.type = IMMEDIATE_EVENT;
|
event.type = IMMEDIATE_EVENT;
|
||||||
event.code = PAL_EVENT;
|
event.code = PAL_EVENT;
|
||||||
|
|
376
saga/sndres.cpp
376
saga/sndres.cpp
|
@ -25,8 +25,7 @@
|
||||||
|
|
||||||
#include "saga/saga.h"
|
#include "saga/saga.h"
|
||||||
|
|
||||||
#include "saga/rscfile_mod.h"
|
#include "saga/rscfile.h"
|
||||||
|
|
||||||
#include "saga/sndres.h"
|
#include "saga/sndres.h"
|
||||||
#include "saga/sound.h"
|
#include "saga/sound.h"
|
||||||
#include "saga/stream.h"
|
#include "saga/stream.h"
|
||||||
|
@ -35,276 +34,191 @@
|
||||||
|
|
||||||
#include "sound/voc.h"
|
#include "sound/voc.h"
|
||||||
#include "sound/wave.h"
|
#include "sound/wave.h"
|
||||||
|
#include "sound/adpcm.h"
|
||||||
|
#include "sound/audiostream.h"
|
||||||
|
|
||||||
namespace Saga {
|
namespace Saga {
|
||||||
|
|
||||||
SndRes::SndRes(SagaEngine *vm) : _vm(vm) {
|
SndRes::SndRes(SagaEngine *vm) : _vm(vm) {
|
||||||
/* Load sound module resource file contexts */
|
/* Load sound module resource file contexts */
|
||||||
_sfx_ctxt = _vm->getFileContext(GAME_SOUNDFILE, 0);
|
_sfxContext = _vm->_resource->getContext(GAME_SOUNDFILE);
|
||||||
if (_sfx_ctxt == NULL) {
|
if (_sfxContext == NULL) {
|
||||||
return;
|
error("SndRes::SndRes resource context not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
_voice_ctxt = _vm->getFileContext(GAME_VOICEFILE, 0);
|
_voiceContext = _vm->_resource->getContext(GAME_VOICEFILE);
|
||||||
if (_voice_ctxt == NULL) {
|
if (_voiceContext == NULL) {
|
||||||
return;
|
error("SndRes::SndRes resource context not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Grab sound resource information for the current game
|
// Grab sound resource information for the current game
|
||||||
_snd_info = *_vm->getSoundInfo();
|
_soundInfo = *_vm->getSoundInfo();
|
||||||
|
|
||||||
_init = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int SndRes::playSound(uint32 sound_rn, int volume, bool loop) {
|
void SndRes::playSound(uint32 resourceId, int volume, bool loop) {
|
||||||
SOUNDBUFFER snd_buffer;
|
SoundBuffer buffer;
|
||||||
|
|
||||||
debug(4, "SndRes::playSound(%ld)", sound_rn);
|
debug(4, "SndRes::playSound %i", resourceId);
|
||||||
|
|
||||||
if (load(_sfx_ctxt, sound_rn, &snd_buffer) != SUCCESS) {
|
if (!load(_sfxContext, resourceId, buffer, false)) {
|
||||||
warning("Failed to load sound");
|
warning("Failed to load sound");
|
||||||
return FAILURE;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_vm->_sound->playSound(&snd_buffer, volume, loop);
|
_vm->_sound->playSound(buffer, volume, loop);
|
||||||
|
|
||||||
return SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int SndRes::playVoice(uint32 voice_rn) {
|
void SndRes::playVoice(uint32 resourceId) {
|
||||||
SOUNDBUFFER snd_buffer;
|
SoundBuffer buffer;
|
||||||
int result = FAILURE;
|
|
||||||
bool voiceFile = false;
|
|
||||||
|
|
||||||
debug(4, "SndRes::playVoice(%ld)", voice_rn);
|
debug(4, "SndRes::playVoice %i", resourceId);
|
||||||
|
|
||||||
if (_vm->getGameType() == GType_ITE && voice_rn == 4) {
|
if (!load(_voiceContext, resourceId, buffer, false)) {
|
||||||
// The Wyrmkeep release of Inherit the Earth provides a
|
warning("Failed to load voice");
|
||||||
// separate file (p2_a.voc or P2_A.iaf), to correct voice 4 in
|
return;
|
||||||
// the intro. Use that, if available.
|
|
||||||
|
|
||||||
Common::File f;
|
|
||||||
uint32 size;
|
|
||||||
bool voc = false;
|
|
||||||
|
|
||||||
if (f.open("p2_a.voc"))
|
|
||||||
voc = true;
|
|
||||||
else
|
|
||||||
f.open("P2_A.iaf");
|
|
||||||
|
|
||||||
if (f.isOpen()) {
|
|
||||||
size = f.size();
|
|
||||||
byte *snd_res = (byte *)malloc(size);
|
|
||||||
f.read(snd_res, size);
|
|
||||||
f.close();
|
|
||||||
|
|
||||||
if (!voc) {
|
|
||||||
snd_buffer.s_stereo = 0;
|
|
||||||
snd_buffer.s_samplebits = 16;
|
|
||||||
snd_buffer.s_freq = 22050;
|
|
||||||
snd_buffer.s_buf = snd_res;
|
|
||||||
snd_buffer.s_buf_len = size;
|
|
||||||
snd_buffer.s_signed = 1;
|
|
||||||
result = SUCCESS;
|
|
||||||
} else {
|
|
||||||
result = loadVocSound(snd_res, size, &snd_buffer);
|
|
||||||
RSC_FreeResource(snd_res);
|
|
||||||
}
|
|
||||||
voiceFile = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// File is not present. It is DOS CD or Floppy
|
_vm->_sound->playVoice(buffer);
|
||||||
if (result != SUCCESS)
|
|
||||||
result = load(_voice_ctxt, voice_rn, &snd_buffer);
|
|
||||||
|
|
||||||
if (result != SUCCESS) {
|
|
||||||
return FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_vm->getFeatures() & GF_VOX_VOICES && !voiceFile)
|
|
||||||
_vm->_sound->playVoxVoice(&snd_buffer);
|
|
||||||
else
|
|
||||||
_vm->_sound->playVoice(&snd_buffer);
|
|
||||||
|
|
||||||
return SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int SndRes::load(RSCFILE_CONTEXT *snd_ctxt, uint32 snd_rn, SOUNDBUFFER *snd_buf_i) {
|
bool SndRes::load(ResourceContext *context, uint32 resourceId, SoundBuffer &buffer, bool onlyHeader) {
|
||||||
byte *snd_res;
|
byte *soundResource;
|
||||||
size_t snd_res_len;
|
AudioStream *voxStream;
|
||||||
|
size_t soundResourceLength;
|
||||||
int result;
|
bool result = false;
|
||||||
|
GameSoundTypes resourceType;
|
||||||
assert((snd_ctxt != NULL) && (snd_buf_i != NULL));
|
|
||||||
|
|
||||||
result = RSC_LoadResource(snd_ctxt, snd_rn, &snd_res, &snd_res_len);
|
|
||||||
if (result != SUCCESS) {
|
|
||||||
return FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (_snd_info.res_type) {
|
|
||||||
case GAME_SOUND_PCM:
|
|
||||||
snd_buf_i->s_freq = _snd_info.freq;
|
|
||||||
snd_buf_i->s_samplebits = _snd_info.sample_size;
|
|
||||||
snd_buf_i->s_stereo = _snd_info.stereo;
|
|
||||||
snd_buf_i->s_buf = snd_res;
|
|
||||||
snd_buf_i->s_buf_len = snd_res_len;
|
|
||||||
snd_buf_i->s_signed = 1;
|
|
||||||
break;
|
|
||||||
case GAME_SOUND_VOC:
|
|
||||||
result = loadVocSound(snd_res, snd_res_len, snd_buf_i);
|
|
||||||
RSC_FreeResource(snd_res);
|
|
||||||
if (result != SUCCESS) {
|
|
||||||
return FAILURE;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case GAME_SOUND_WAV:
|
|
||||||
result = loadWavSound(snd_res, snd_res_len, snd_buf_i);
|
|
||||||
RSC_FreeResource(snd_res);
|
|
||||||
if (result != SUCCESS) {
|
|
||||||
return FAILURE;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
/* Unknown sound type */
|
|
||||||
RSC_FreeResource(snd_res);
|
|
||||||
return FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
int SndRes::loadVocSound(byte *snd_res, size_t snd_res_len, SOUNDBUFFER *snd_buf_i) {
|
|
||||||
MemoryReadStreamEndian readS(snd_res, snd_res_len, IS_BIG_ENDIAN);
|
|
||||||
byte *data;
|
byte *data;
|
||||||
int rate;
|
int rate;
|
||||||
int len;
|
int size;
|
||||||
|
|
||||||
data = loadVOCFromStream(readS, len, rate);
|
|
||||||
|
|
||||||
if (!data) {
|
|
||||||
return FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
snd_buf_i->s_freq = rate;
|
|
||||||
snd_buf_i->s_samplebits = 8;
|
|
||||||
snd_buf_i->s_stereo = 0;
|
|
||||||
snd_buf_i->s_signed = 0;
|
|
||||||
snd_buf_i->s_buf = data;
|
|
||||||
snd_buf_i->s_buf_len = len;
|
|
||||||
|
|
||||||
return SUCCESS;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
int SndRes::loadWavSound(byte *snd_res, size_t snd_res_len, SOUNDBUFFER *snd_buf_i) {
|
|
||||||
Common::MemoryReadStream readS(snd_res, snd_res_len);
|
|
||||||
int rate, size;
|
|
||||||
byte flags;
|
byte flags;
|
||||||
|
bool voxPcm;
|
||||||
|
size_t voxSize;
|
||||||
|
|
||||||
if (!loadWAVFromStream(readS, size, rate, flags)) {
|
if (resourceId == (int32)-1) {
|
||||||
return FAILURE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
snd_buf_i->s_stereo = ((flags & Audio::Mixer::FLAG_STEREO) != 0);
|
_vm->_resource->loadResource(context, resourceId, soundResource, soundResourceLength);
|
||||||
snd_buf_i->s_freq = rate;
|
|
||||||
snd_buf_i->s_samplebits = 16;
|
|
||||||
snd_buf_i->s_signed = 1;
|
|
||||||
snd_buf_i->s_buf_len = size;
|
|
||||||
|
|
||||||
byte *data = (byte *)malloc(snd_buf_i->s_buf_len);
|
MemoryReadStream readS(soundResource, soundResourceLength);
|
||||||
if (!data) {
|
|
||||||
return FAILURE;
|
//TODO: check soundResource header - game may have GAME_SOUND_PCM, but patch file can be GAME_SOUND_VOC
|
||||||
|
resourceType = _soundInfo.resourceType;
|
||||||
|
|
||||||
|
if (soundResourceLength >= 8) {
|
||||||
|
if (!memcmp(&soundResource, "Creative", 8)) {
|
||||||
|
resourceType = GAME_SOUND_VOC;
|
||||||
|
} else if (!memcmp(soundResource, "RIFF", 4) != 0) {
|
||||||
|
resourceType = GAME_SOUND_WAV;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
readS.read(data, snd_buf_i->s_buf_len);
|
switch (resourceType) {
|
||||||
snd_buf_i->s_buf = data;
|
case GAME_SOUND_PCM:
|
||||||
return SUCCESS;
|
buffer.frequency = _soundInfo.frequency;
|
||||||
|
buffer.isSigned = true;
|
||||||
|
voxPcm = (_vm->getFeatures() & GF_VOX_VOICES);
|
||||||
|
if (voxPcm) {
|
||||||
|
if (_vm->getGameType() == GType_ITE) {
|
||||||
|
//.iaf is not vox
|
||||||
|
if (_vm->_resource->getResourceData(context, resourceId)->patchFile != NULL) {
|
||||||
|
voxPcm = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (voxPcm) {
|
||||||
|
buffer.sampleBits = 16;
|
||||||
|
buffer.stereo = false;
|
||||||
|
buffer.size = soundResourceLength * 4;
|
||||||
|
if (onlyHeader) {
|
||||||
|
buffer.buffer = NULL;
|
||||||
|
free(soundResource);
|
||||||
|
} else {
|
||||||
|
voxStream = makeADPCMStream(readS, soundResourceLength, kADPCMOki);
|
||||||
|
buffer.buffer = (byte *)malloc(buffer.size);
|
||||||
|
voxSize = voxStream->readBuffer((int16*)buffer.buffer, soundResourceLength * 2);
|
||||||
|
if (voxSize != soundResourceLength * 2) {
|
||||||
|
error("SndRes::load() wrong VOX output size");
|
||||||
|
}
|
||||||
|
delete voxStream;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
buffer.sampleBits = _soundInfo.sampleBits;
|
||||||
|
buffer.size = soundResourceLength;
|
||||||
|
buffer.stereo = _soundInfo.stereo;
|
||||||
|
if (onlyHeader) {
|
||||||
|
buffer.buffer = NULL;
|
||||||
|
free(soundResource);
|
||||||
|
} else {
|
||||||
|
buffer.buffer = soundResource;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result = true;
|
||||||
|
break;
|
||||||
|
case GAME_SOUND_VOC:
|
||||||
|
data = loadVOCFromStream(readS, size, rate);
|
||||||
|
if (data) {
|
||||||
|
buffer.frequency = rate;
|
||||||
|
buffer.sampleBits = 8;
|
||||||
|
buffer.stereo = false;
|
||||||
|
buffer.isSigned = false;
|
||||||
|
buffer.size = size;
|
||||||
|
if (onlyHeader) {
|
||||||
|
buffer.buffer = NULL;
|
||||||
|
free(data);
|
||||||
|
} else {
|
||||||
|
buffer.buffer = data;
|
||||||
|
}
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
free(soundResource);
|
||||||
|
break;
|
||||||
|
case GAME_SOUND_WAV:
|
||||||
|
if (loadWAVFromStream(readS, size, rate, flags)) {
|
||||||
|
buffer.frequency = rate;
|
||||||
|
buffer.sampleBits = 16;
|
||||||
|
buffer.stereo = ((flags & Audio::Mixer::FLAG_STEREO) != 0);
|
||||||
|
buffer.isSigned = true;
|
||||||
|
buffer.size = size;
|
||||||
|
if (onlyHeader) {
|
||||||
|
buffer.buffer = NULL;
|
||||||
|
} else {
|
||||||
|
buffer.buffer = (byte *)malloc(size);
|
||||||
|
readS.read(buffer.buffer, size);
|
||||||
|
}
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
free(soundResource);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
error("SndRes::load Unknown sound type");
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SndRes::getVoiceLength(uint32 voice_rn) {
|
int SndRes::getVoiceLength(uint32 resourceId) {
|
||||||
int res_type = _snd_info.res_type;
|
|
||||||
uint32 length = 0;
|
|
||||||
bool voiceFile = false;
|
bool voiceFile = false;
|
||||||
|
double msDouble;
|
||||||
|
SoundBuffer buffer;
|
||||||
|
|
||||||
double ms_f;
|
|
||||||
int ms_i = -1;
|
if (!load(_voiceContext, resourceId, buffer, true)) {
|
||||||
|
|
||||||
int result = FAILURE;
|
|
||||||
|
|
||||||
assert(_init);
|
|
||||||
|
|
||||||
Common::File f;
|
|
||||||
|
|
||||||
// The Wyrmkeep release of Inherit the Earth provides a separate file
|
|
||||||
// (p2_a.voc or P2_A.iaf), to correct voice 4 in the intro. Use that,
|
|
||||||
// if available.
|
|
||||||
|
|
||||||
if (_vm->getGameType() == GType_ITE && voice_rn == 4) {
|
|
||||||
if (f.open("p2_a.voc")) {
|
|
||||||
result = SUCCESS;
|
|
||||||
length = f.size();
|
|
||||||
res_type = GAME_SOUND_VOC;
|
|
||||||
f.close();
|
|
||||||
voiceFile = true;
|
|
||||||
} else if (f.open("P2_A.iaf")) {
|
|
||||||
result = SUCCESS;
|
|
||||||
length = f.size();
|
|
||||||
res_type = GAME_SOUND_PCM;
|
|
||||||
f.close();
|
|
||||||
voiceFile = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result == FAILURE) {
|
|
||||||
result = RSC_GetResourceSize(_voice_ctxt, voice_rn, &length);
|
|
||||||
|
|
||||||
if (result != SUCCESS) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_vm->getFeatures() & GF_VOX_VOICES && !voiceFile) {
|
|
||||||
// Rough hack, fix this to be accurate
|
|
||||||
ms_f = (double)length / 22050 * 2000.0;
|
|
||||||
ms_i = (int)ms_f;
|
|
||||||
} else if (res_type == GAME_SOUND_PCM) {
|
|
||||||
ms_f = (double)length / (_snd_info.sample_size / 8) / (_snd_info.freq) * 1000.0;
|
|
||||||
ms_i = (int)ms_f;
|
|
||||||
} else if (res_type == GAME_SOUND_VOC) {
|
|
||||||
// Rough hack, fix this to be accurate
|
|
||||||
ms_f = (double)length / 14705 * 1000.0;
|
|
||||||
ms_i = (int)ms_f;
|
|
||||||
} else if (res_type == GAME_SOUND_WAV) {
|
|
||||||
// IHNM does not use the same format for all its WAV sounds, so
|
|
||||||
// we just have to load the stupid thing and see what that will
|
|
||||||
// tell us about it.
|
|
||||||
|
|
||||||
SOUNDBUFFER snd_buffer;
|
|
||||||
|
|
||||||
result = load(_voice_ctxt, voice_rn, &snd_buffer);
|
|
||||||
if (result != SUCCESS) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
free(snd_buffer.s_buf);
|
|
||||||
|
|
||||||
ms_f = (double)snd_buffer.s_buf_len;
|
|
||||||
if (snd_buffer.s_samplebits == 16) {
|
|
||||||
ms_f /= 2.0;
|
|
||||||
}
|
|
||||||
if (snd_buffer.s_stereo) {
|
|
||||||
ms_f /= 2.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
ms_f = ms_f / snd_buffer.s_freq * 1000.0;
|
|
||||||
ms_i = (int)ms_f;
|
|
||||||
} else {
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ms_i;
|
|
||||||
|
msDouble = (double)buffer.size;
|
||||||
|
if (buffer.sampleBits == 16) {
|
||||||
|
msDouble /= 2.0;
|
||||||
|
}
|
||||||
|
if (buffer.stereo) {
|
||||||
|
msDouble /= 2.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
msDouble = msDouble / buffer.frequency * 1000.0;
|
||||||
|
return (int)msDouble;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // End of namespace Saga
|
} // End of namespace Saga
|
||||||
|
|
|
@ -26,7 +26,6 @@
|
||||||
#ifndef SAGA_SNDRES_H_
|
#ifndef SAGA_SNDRES_H_
|
||||||
#define SAGA_SNDRES_H_
|
#define SAGA_SNDRES_H_
|
||||||
|
|
||||||
#include "saga/rscfile_mod.h"
|
|
||||||
#include "saga/sound.h"
|
#include "saga/sound.h"
|
||||||
|
|
||||||
namespace Saga {
|
namespace Saga {
|
||||||
|
@ -36,22 +35,20 @@ public:
|
||||||
|
|
||||||
SndRes(SagaEngine *vm);
|
SndRes(SagaEngine *vm);
|
||||||
|
|
||||||
int loadSound(uint32 sound_rn);
|
int loadSound(uint32 resourceId);
|
||||||
int playSound(uint32 sound_rn, int volume, bool loop);
|
void playSound(uint32 resourceId, int volume, bool loop);
|
||||||
int playVoice(uint32 voice_rn);
|
void playVoice(uint32 resourceId);
|
||||||
int getVoiceLength(uint32 voice_rn);
|
int getVoiceLength(uint32 resourceId);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int load(RSCFILE_CONTEXT *snd_ctxt, uint32 snd_rn, SOUNDBUFFER *snd_buf_i);
|
bool load(ResourceContext *context, uint32 resourceId, SoundBuffer &buffer, bool onlyHeader);
|
||||||
int loadVocSound(byte *snd_res, size_t snd_res_len, SOUNDBUFFER *snd_buf_i);
|
bool loadVocSound(byte *soundResource, size_t soundResourceLength, SoundBuffer &buffer);
|
||||||
int loadWavSound(byte *snd_res, size_t snd_res_len, SOUNDBUFFER *snd_buf_i);
|
bool loadWavSound(byte *soundResource, size_t soundResourceLength, SoundBuffer &buffer);
|
||||||
|
|
||||||
int _init;
|
ResourceContext *_sfxContext;
|
||||||
|
ResourceContext *_voiceContext;
|
||||||
|
|
||||||
RSCFILE_CONTEXT *_sfx_ctxt;
|
GameSoundInfo _soundInfo;
|
||||||
RSCFILE_CONTEXT *_voice_ctxt;
|
|
||||||
|
|
||||||
GameSoundInfo _snd_info;
|
|
||||||
|
|
||||||
SagaEngine *_vm;
|
SagaEngine *_vm;
|
||||||
};
|
};
|
||||||
|
|
|
@ -32,127 +32,64 @@ namespace Saga {
|
||||||
|
|
||||||
Sound::Sound(SagaEngine *vm, Audio::Mixer *mixer, int enabled) :
|
Sound::Sound(SagaEngine *vm, Audio::Mixer *mixer, int enabled) :
|
||||||
_vm(vm), _mixer(mixer), _enabled(enabled), _voxStream(0) {
|
_vm(vm), _mixer(mixer), _enabled(enabled), _voxStream(0) {
|
||||||
|
|
||||||
_soundInitialized = 1;
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Sound::~Sound() {
|
Sound::~Sound() {
|
||||||
if (!_soundInitialized) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
delete _voxStream;
|
delete _voxStream;
|
||||||
_soundInitialized = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int Sound::playSoundBuffer(Audio::SoundHandle *handle, SOUNDBUFFER *buf, int volume, bool loop, bool forceBigEndian) {
|
void Sound::playSoundBuffer(Audio::SoundHandle *handle, SoundBuffer &buffer, int volume, bool loop, bool forceBigEndian) {
|
||||||
byte flags;
|
byte flags;
|
||||||
|
|
||||||
if (!_soundInitialized) {
|
|
||||||
return FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
flags = Audio::Mixer::FLAG_AUTOFREE;
|
flags = Audio::Mixer::FLAG_AUTOFREE;
|
||||||
|
|
||||||
if (loop)
|
if (loop)
|
||||||
flags |= Audio::Mixer::FLAG_LOOP;
|
flags |= Audio::Mixer::FLAG_LOOP;
|
||||||
|
|
||||||
if (buf->s_samplebits == 16) {
|
if (buffer.sampleBits == 16) {
|
||||||
flags |= Audio::Mixer::FLAG_16BITS;
|
flags |= Audio::Mixer::FLAG_16BITS;
|
||||||
if (!(_vm->getFeatures() & GF_BIG_ENDIAN_DATA) && !forceBigEndian)
|
if (!(_vm->isBigEndian()) && !forceBigEndian)
|
||||||
flags |= Audio::Mixer::FLAG_LITTLE_ENDIAN;
|
flags |= Audio::Mixer::FLAG_LITTLE_ENDIAN;
|
||||||
}
|
}
|
||||||
if (buf->s_stereo)
|
if (buffer.stereo)
|
||||||
flags |= Audio::Mixer::FLAG_STEREO;
|
flags |= Audio::Mixer::FLAG_STEREO;
|
||||||
if (!buf->s_signed)
|
if (!buffer.isSigned)
|
||||||
flags |= Audio::Mixer::FLAG_UNSIGNED;
|
flags |= Audio::Mixer::FLAG_UNSIGNED;
|
||||||
|
|
||||||
_mixer->playRaw(handle, buf->s_buf, buf->s_buf_len, buf->s_freq, flags, -1, volume);
|
_mixer->playRaw(handle, buffer.buffer, buffer.size, buffer.frequency, flags, -1, volume);
|
||||||
|
|
||||||
return SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int Sound::playSound(SOUNDBUFFER *buf, int volume, bool loop) {
|
void Sound::playSound(SoundBuffer &buffer, int volume, bool loop) {
|
||||||
return playSoundBuffer(&_effectHandle, buf, 2 * volume, loop, false);
|
playSoundBuffer(&_effectHandle, buffer, 2 * volume, loop, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Sound::pauseSound() {
|
void Sound::pauseSound() {
|
||||||
if (!_soundInitialized) {
|
|
||||||
return FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
_mixer->pauseHandle(_effectHandle, true);
|
_mixer->pauseHandle(_effectHandle, true);
|
||||||
|
|
||||||
return SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int Sound::resumeSound() {
|
void Sound::resumeSound() {
|
||||||
if (!_soundInitialized) {
|
|
||||||
return FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
_mixer->pauseHandle(_effectHandle, false);
|
_mixer->pauseHandle(_effectHandle, false);
|
||||||
|
|
||||||
return SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int Sound::stopSound() {
|
void Sound::stopSound() {
|
||||||
if (!_soundInitialized) {
|
|
||||||
return FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
_mixer->stopHandle(_effectHandle);
|
_mixer->stopHandle(_effectHandle);
|
||||||
|
|
||||||
return SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int Sound::playVoice(SOUNDBUFFER *buf) {
|
void Sound::playVoice(SoundBuffer &buffer) {
|
||||||
return playSoundBuffer(&_voiceHandle, buf, 255, false, (_vm->getFeatures() & GF_BIG_ENDIAN_VOICES) != 0);
|
playSoundBuffer(&_voiceHandle, buffer, 255, false, (_vm->getFeatures() & GF_BIG_ENDIAN_VOICES) != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Sound::playVoxVoice(SOUNDBUFFER *buf) {
|
|
||||||
AudioStream *audioStream;
|
|
||||||
|
|
||||||
if (_voxStream)
|
|
||||||
delete _voxStream;
|
|
||||||
|
|
||||||
_voxStream = new Common::MemoryReadStream(buf->s_buf, buf->s_buf_len);
|
|
||||||
|
|
||||||
audioStream = makeADPCMStream(*_voxStream, buf->s_buf_len, kADPCMOki);
|
|
||||||
_mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_voiceHandle, audioStream);
|
|
||||||
|
|
||||||
return SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
int Sound::pauseVoice() {
|
|
||||||
if (!_soundInitialized) {
|
|
||||||
return FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
void Sound::pauseVoice() {
|
||||||
_mixer->pauseHandle(_voiceHandle, true);
|
_mixer->pauseHandle(_voiceHandle, true);
|
||||||
|
|
||||||
return SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int Sound::resumeVoice() {
|
void Sound::resumeVoice() {
|
||||||
if (!_soundInitialized) {
|
|
||||||
return FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
_mixer->pauseHandle(_voiceHandle, false);
|
_mixer->pauseHandle(_voiceHandle, false);
|
||||||
|
|
||||||
return SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int Sound::stopVoice() {
|
void Sound::stopVoice() {
|
||||||
if (!_soundInitialized) {
|
|
||||||
return FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
_mixer->stopHandle(_voiceHandle);
|
_mixer->stopHandle(_voiceHandle);
|
||||||
|
|
||||||
return SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // End of namespace Saga
|
} // End of namespace Saga
|
||||||
|
|
37
saga/sound.h
37
saga/sound.h
|
@ -26,7 +26,6 @@
|
||||||
#ifndef SAGA_SOUND_H_
|
#ifndef SAGA_SOUND_H_
|
||||||
#define SAGA_SOUND_H_
|
#define SAGA_SOUND_H_
|
||||||
|
|
||||||
#include "saga/rscfile_mod.h"
|
|
||||||
#include "sound/mixer.h"
|
#include "sound/mixer.h"
|
||||||
|
|
||||||
namespace Saga {
|
namespace Saga {
|
||||||
|
@ -35,14 +34,15 @@ enum SOUND_FLAGS {
|
||||||
SOUND_LOOP = 1
|
SOUND_LOOP = 1
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SOUNDBUFFER {
|
struct SoundBuffer {
|
||||||
uint16 s_freq;
|
uint16 frequency;
|
||||||
int s_samplebits;
|
int sampleBits;
|
||||||
int s_stereo;
|
bool stereo;
|
||||||
int s_signed;
|
bool isSigned;
|
||||||
|
|
||||||
byte *s_buf;
|
byte *buffer;
|
||||||
size_t s_buf_len;
|
size_t size;
|
||||||
|
//big endianess flag!!!
|
||||||
};
|
};
|
||||||
|
|
||||||
class Sound {
|
class Sound {
|
||||||
|
@ -51,22 +51,19 @@ public:
|
||||||
Sound(SagaEngine *vm, Audio::Mixer *mixer, int enabled);
|
Sound(SagaEngine *vm, Audio::Mixer *mixer, int enabled);
|
||||||
~Sound();
|
~Sound();
|
||||||
|
|
||||||
int playSound(SOUNDBUFFER *buf, int volume, bool loop);
|
void playSound(SoundBuffer &buffer, int volume, bool loop);
|
||||||
int pauseSound();
|
void pauseSound();
|
||||||
int resumeSound();
|
void resumeSound();
|
||||||
int stopSound();
|
void stopSound();
|
||||||
|
|
||||||
int playVoice(SOUNDBUFFER *buf);
|
void playVoice(SoundBuffer &buffer);
|
||||||
int playVoxVoice(SOUNDBUFFER *buf);
|
void pauseVoice();
|
||||||
int pauseVoice();
|
void resumeVoice();
|
||||||
int resumeVoice();
|
void stopVoice();
|
||||||
int stopVoice();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
int playSoundBuffer(Audio::SoundHandle *handle, SOUNDBUFFER *buf, int volume, bool loop, bool forceBigEndian);
|
void playSoundBuffer(Audio::SoundHandle *handle, SoundBuffer &buffer, int volume, bool loop, bool forceBigEndian);
|
||||||
|
|
||||||
int _soundInitialized;
|
|
||||||
int _enabled;
|
int _enabled;
|
||||||
|
|
||||||
SagaEngine *_vm;
|
SagaEngine *_vm;
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
|
|
||||||
#include "saga/gfx.h"
|
#include "saga/gfx.h"
|
||||||
#include "saga/scene.h"
|
#include "saga/scene.h"
|
||||||
#include "saga/rscfile_mod.h"
|
#include "saga/rscfile.h"
|
||||||
|
|
||||||
#include "saga/font.h"
|
#include "saga/font.h"
|
||||||
|
|
||||||
|
@ -35,38 +35,32 @@
|
||||||
|
|
||||||
namespace Saga {
|
namespace Saga {
|
||||||
|
|
||||||
Sprite::Sprite(SagaEngine *vm) : _vm(vm), _initialized(false) {
|
Sprite::Sprite(SagaEngine *vm) : _vm(vm) {
|
||||||
debug(8, "Initializing sprite subsystem...");
|
debug(8, "Initializing sprite subsystem...");
|
||||||
|
|
||||||
// Load sprite module resource context
|
// Load sprite module resource context
|
||||||
_spriteContext = _vm->getFileContext(GAME_RESOURCEFILE, 0);
|
_spriteContext = _vm->_resource->getContext(GAME_RESOURCEFILE);
|
||||||
if (_spriteContext == NULL) {
|
if (_spriteContext == NULL) {
|
||||||
return;
|
error("Sprite::Sprite resource context not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
_decodeBufLen = DECODE_BUF_LEN;
|
_decodeBufLen = DECODE_BUF_LEN;
|
||||||
|
|
||||||
_decodeBuf = (byte *)malloc(_decodeBufLen);
|
_decodeBuf = (byte *)malloc(_decodeBufLen);
|
||||||
if (_decodeBuf == NULL) {
|
if (_decodeBuf == NULL) {
|
||||||
return;
|
memoryError("Sprite::Sprite");
|
||||||
}
|
}
|
||||||
|
|
||||||
loadList(_vm->getResourceDescription()->mainSpritesResourceId, _mainSprites);
|
loadList(_vm->getResourceDescription()->mainSpritesResourceId, _mainSprites);
|
||||||
|
|
||||||
_initialized = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Sprite::~Sprite(void) {
|
Sprite::~Sprite(void) {
|
||||||
if (!_initialized) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
debug(8, "Shutting down sprite subsystem...");
|
debug(8, "Shutting down sprite subsystem...");
|
||||||
_mainSprites.freeMem();
|
_mainSprites.freeMem();
|
||||||
free(_decodeBuf);
|
free(_decodeBuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Sprite::loadList(int resourceId, SpriteList &spriteList) {
|
void Sprite::loadList(int resourceId, SpriteList &spriteList) {
|
||||||
SpriteInfo *spriteInfo;
|
SpriteInfo *spriteInfo;
|
||||||
byte *spriteListData;
|
byte *spriteListData;
|
||||||
size_t spriteListLength;
|
size_t spriteListLength;
|
||||||
|
@ -79,17 +73,13 @@ int Sprite::loadList(int resourceId, SpriteList &spriteList) {
|
||||||
const byte *spritePointer;
|
const byte *spritePointer;
|
||||||
const byte *spriteDataPointer;
|
const byte *spriteDataPointer;
|
||||||
|
|
||||||
if (RSC_LoadResource(_spriteContext, resourceId, &spriteListData, &spriteListLength) != SUCCESS) {
|
_vm->_resource->loadResource(_spriteContext, resourceId, spriteListData, spriteListLength);
|
||||||
warning("Sprite::loadList RSC_LoadResource FAILURE");
|
|
||||||
return FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (spriteListLength == 0) {
|
if (spriteListLength == 0) {
|
||||||
warning("Sprite::loadList spriteListLength == 0");
|
return;
|
||||||
return FAILURE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MemoryReadStreamEndian readS(spriteListData, spriteListLength, IS_BIG_ENDIAN);
|
MemoryReadStreamEndian readS(spriteListData, spriteListLength, _spriteContext->isBigEndian);
|
||||||
|
|
||||||
spriteCount = readS.readUint16();
|
spriteCount = readS.readUint16();
|
||||||
|
|
||||||
|
@ -105,7 +95,7 @@ int Sprite::loadList(int resourceId, SpriteList &spriteList) {
|
||||||
|
|
||||||
for (i = oldSpriteCount; i < spriteList.spriteCount; i++) {
|
for (i = oldSpriteCount; i < spriteList.spriteCount; i++) {
|
||||||
spriteInfo = &spriteList.infoList[i];
|
spriteInfo = &spriteList.infoList[i];
|
||||||
if (_vm->getFeatures() & GF_MAC_RESOURCES)
|
if (_vm->isMacResources())
|
||||||
offset = readS.readUint32();
|
offset = readS.readUint32();
|
||||||
else
|
else
|
||||||
offset = readS.readUint16();
|
offset = readS.readUint16();
|
||||||
|
@ -142,9 +132,7 @@ int Sprite::loadList(int resourceId, SpriteList &spriteList) {
|
||||||
memcpy(spriteInfo->decodedBuffer, _decodeBuf, outputLength);
|
memcpy(spriteInfo->decodedBuffer, _decodeBuf, outputLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
RSC_FreeResource(spriteListData);
|
free(spriteListData);
|
||||||
|
|
||||||
return SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sprite::getScaledSpriteBuffer(SpriteList &spriteList, int spriteNumber, int scale, int &width, int &height, int &xAlign, int &yAlign, const byte *&buffer) {
|
void Sprite::getScaledSpriteBuffer(SpriteList &spriteList, int spriteNumber, int scale, int &width, int &height, int &xAlign, int &yAlign, const byte *&buffer) {
|
||||||
|
@ -307,8 +295,6 @@ void Sprite::drawOccluded(Surface *ds, const Rect &clipRect, SpriteList &spriteL
|
||||||
int maskZ;
|
int maskZ;
|
||||||
|
|
||||||
|
|
||||||
assert(_initialized);
|
|
||||||
|
|
||||||
if (!_vm->_scene->isBGMaskPresent()) {
|
if (!_vm->_scene->isBGMaskPresent()) {
|
||||||
draw(ds, clipRect, spriteList, spriteNumber, screenCoord, scale);
|
draw(ds, clipRect, spriteList, spriteNumber, screenCoord, scale);
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -81,7 +81,7 @@ public:
|
||||||
|
|
||||||
void draw(Surface *ds, const Rect &clipRect, SpriteList &spriteList, int32 spriteNumber, const Rect &screenRect, int scale);
|
void draw(Surface *ds, const Rect &clipRect, SpriteList &spriteList, int32 spriteNumber, const Rect &screenRect, int scale);
|
||||||
|
|
||||||
int loadList(int resourceId, SpriteList &spriteList); // load or append spriteList
|
void loadList(int resourceId, SpriteList &spriteList); // load or append spriteList
|
||||||
bool hitTest(SpriteList &spriteList, int spriteNumber, const Point &screenCoord, int scale, const Point &testPoint);
|
bool hitTest(SpriteList &spriteList, int spriteNumber, const Point &screenCoord, int scale, const Point &testPoint);
|
||||||
void getScaledSpriteBuffer(SpriteList &spriteList, int spriteNumber, int scale, int &width, int &height, int &xAlign, int &yAlign, const byte *&buffer);
|
void getScaledSpriteBuffer(SpriteList &spriteList, int spriteNumber, int scale, int &width, int &height, int &xAlign, int &yAlign, const byte *&buffer);
|
||||||
|
|
||||||
|
@ -90,8 +90,7 @@ private:
|
||||||
void scaleBuffer(const byte *src, int width, int height, int scale);
|
void scaleBuffer(const byte *src, int width, int height, int scale);
|
||||||
|
|
||||||
SagaEngine *_vm;
|
SagaEngine *_vm;
|
||||||
bool _initialized;
|
ResourceContext *_spriteContext;
|
||||||
RSCFILE_CONTEXT *_spriteContext;
|
|
||||||
byte *_decodeBuf;
|
byte *_decodeBuf;
|
||||||
size_t _decodeBufLen;
|
size_t _decodeBufLen;
|
||||||
};
|
};
|
||||||
|
|
|
@ -173,14 +173,6 @@ void Script::completeThread(void) {
|
||||||
executeThreads(0);
|
executeThreads(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Script::SThreadDebugStep() {
|
|
||||||
if (_dbg_singlestep) {
|
|
||||||
_dbg_dostep = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Script::runThread(ScriptThread *thread, uint instructionLimit) {
|
bool Script::runThread(ScriptThread *thread, uint instructionLimit) {
|
||||||
const char*operandName;
|
const char*operandName;
|
||||||
uint instructionCount;
|
uint instructionCount;
|
||||||
|
@ -201,19 +193,7 @@ bool Script::runThread(ScriptThread *thread, uint instructionLimit) {
|
||||||
int debug_print = 0;
|
int debug_print = 0;
|
||||||
int operandChar;
|
int operandChar;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
// Handle debug single-stepping
|
|
||||||
if ((thread == _dbg_thread) && _dbg_singlestep) {
|
|
||||||
if (_dbg_dostep) {
|
|
||||||
debug_print = 1;
|
|
||||||
thread->_sleepTime = 0;
|
|
||||||
instructionLimit = 1;
|
|
||||||
_dbg_dostep = 0;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MemoryReadStream scriptS(thread->_moduleBase, thread->_moduleBaseSize);
|
MemoryReadStream scriptS(thread->_moduleBase, thread->_moduleBaseSize);
|
||||||
|
|
||||||
scriptS.seek(thread->_instructionOffset);
|
scriptS.seek(thread->_instructionOffset);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue