diff options
40 files changed, 1003 insertions, 1495 deletions
diff --git a/saga/actor.cpp b/saga/actor.cpp index c836a5f165..92c814ff03 100644 --- a/saga/actor.cpp +++ b/saga/actor.cpp @@ -25,7 +25,6 @@ #include "saga/gfx.h" #include "saga/console.h" -#include "saga/rscfile_mod.h" #include "saga/script.h" #include "saga/sndres.h" #include "saga/sprite.h" @@ -40,6 +39,9 @@ #include "saga/interface.h" #include "saga/events.h" #include "saga/objectmap.h" +#include "saga/rscfile.h" +#include "saga/resnames.h" + #include "common/config-manager.h" namespace Saga { @@ -164,7 +166,6 @@ static const DragonMove dragonMoveTable[12] = { Actor::Actor(SagaEngine *vm) : _vm(vm) { int i; - int result; byte *stringsPointer; size_t stringsLength; ActorData *actor; @@ -207,18 +208,15 @@ Actor::Actor(SagaEngine *vm) : _vm(vm) { if (_vm->getGameType() == GType_ITE) { // Get actor resource file context - _actorContext = _vm->getFileContext(GAME_RESOURCEFILE, 0); + _actorContext = _vm->_resource->getContext(GAME_RESOURCEFILE); 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); - if ((result != SUCCESS) || (stringsLength == 0)) { - error("Error loading strings list resource"); - } + _vm->_resource->loadResource(_actorContext, _vm->getResourceDescription()->actorsStringsResourceId, stringsPointer, stringsLength); _vm->loadStrings(_actorsStrings, stringsPointer, stringsLength); - RSC_FreeResource(stringsPointer); + free(stringsPointer); } else { // TODO } @@ -325,10 +323,7 @@ bool Actor::loadActorResources(ActorData *actor) { } debug(9, "Loading frame resource id %d", actor->frameListResourceId); - if (RSC_LoadResource(_actorContext, actor->frameListResourceId, &resourcePointer, &resourceLength) != SUCCESS) { - warning("Couldn't load sprite action index resource"); - return false; - } + _vm->_resource->loadResource(_actorContext, actor->frameListResourceId, resourcePointer, resourceLength); framesCount = resourceLength / 16; debug(9, "Frame resource contains %d frames", framesCount); @@ -338,7 +333,7 @@ bool Actor::loadActorResources(ActorData *actor) { memoryError("Actor::loadActorResources"); } - MemoryReadStreamEndian readS(resourcePointer, resourceLength, IS_BIG_ENDIAN); + MemoryReadStreamEndian readS(resourcePointer, resourceLength, _actorContext->isBigEndian); lastFrame = 0; @@ -355,27 +350,22 @@ bool Actor::loadActorResources(ActorData *actor) { } } - RSC_FreeResource(resourcePointer); + free(resourcePointer); actor->frames = framesPointer; actor->framesCount = framesCount; resourceId = actor->spriteListResourceId; debug(9, "Loading sprite resource id %d", resourceId); - if (_vm->_sprite->loadList(resourceId, actor->spriteList) != SUCCESS) { - warning("loadActorResources: Unable to load sprite list"); - return false; - } + + _vm->_sprite->loadList(resourceId, actor->spriteList); i = actor->spriteList.spriteCount; if ((actor->flags & kExtended)) { while ((lastFrame >= actor->spriteList.spriteCount)) { resourceId++; debug(9, "Appending to sprite list %d", resourceId); - if (_vm->_sprite->loadList(resourceId, actor->spriteList) != SUCCESS) { - warning("Unable append sprite list"); - return false; - } + _vm->_sprite->loadList(resourceId, actor->spriteList); } } @@ -2652,7 +2642,7 @@ void Actor::loadState(Common::InSaveFile *in) { for (i = 0; i < _actorsCount; i++) { ActorData *a = _actors[i]; - a->loadState(in); + a->loadState(_vm->getCurrentLoadVersion(), in); } for (i = 0; i < _objsCount; i++) { diff --git a/saga/actor.h b/saga/actor.h index 69668dfcb5..e90272b718 100644 --- a/saga/actor.h +++ b/saga/actor.h @@ -375,7 +375,7 @@ public: out->writeSint32LE(walkFrameSequence); } - void loadState(Common::InSaveFile *in) { + void loadState(uint32 version, Common::InSaveFile *in) { int i = 0; CommonObjectData::loadState(in); actorFlags = in->readUint16LE(); @@ -390,14 +390,14 @@ public: cycleDelay = in->readByte(); cycleTimeCount = in->readByte(); cycleFlags = in->readByte(); - if (_vm->getCurrentLoadVersion() > 1) { + if (version > 1) { fallVelocity = in->readSint16LE(); fallAcceleration = in->readSint16LE(); fallPosition = in->readSint16LE(); } else { fallVelocity = fallAcceleration = fallPosition = 0; } - if (_vm->getCurrentLoadVersion() > 2) { + if (version > 2) { dragonBaseFrame = in->readByte(); dragonStepCycle = in->readByte(); dragonMoveType = in->readByte(); @@ -621,7 +621,7 @@ protected: ObjectData **_objs; SagaEngine *_vm; - RSCFILE_CONTEXT *_actorContext; + ResourceContext *_actorContext; StringsTable _actorsStrings; int _lastTickMsec; diff --git a/saga/animation.cpp b/saga/animation.cpp index c512773cc9..081ddd74f7 100644 --- a/saga/animation.cpp +++ b/saga/animation.cpp @@ -46,6 +46,7 @@ Anim::~Anim(void) { void Anim::load(uint16 animId, const byte *animResourceData, size_t animResourceLength) { AnimationData *anim; + uint16 temp; if (animId >= MAX_ANIMATIONS) { 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); - 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->screenWidth = 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->maxFrame = headerReadS.readByte() - 1; anim->loopFrame = headerReadS.readByte() - 1; - anim->start = headerReadS.readUint16BE(); - - anim->start += headerReadS.pos(); + temp = headerReadS.readUint16BE(); + anim->start = headerReadS.pos(); + if (temp == (uint16)(-1)) { + temp = 0; + } + anim->start += temp; if (_vm->getGameType() == GType_ITE) { @@ -76,8 +80,15 @@ void Anim::load(uint16 animId, const byte *animResourceData, size_t animResource fillFrameOffsets(anim); } else { - anim->cur_frame_p = anim->resourceData + SAGA_FRAME_HEADER_LEN; // ? len - may vary - anim->cur_frame_len = anim->resourceLength - SAGA_FRAME_HEADER_LEN; +/* anim->frameOffsets = (size_t *)malloc((anim->maxFrame + 1) * sizeof(*anim->frameOffsets)); + 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 @@ -179,8 +190,8 @@ void Anim::play(uint16 animId, int vectorTime, bool playing) { if (_vm->getGameType() == GType_IHNM) { // FIXME: HACK. probably needs more testing for IHNM - anim->cur_frame_p = anim->resourceData + SAGA_FRAME_HEADER_LEN; - anim->cur_frame_len = anim->resourceLength - SAGA_FRAME_HEADER_LEN; + anim->cur_frame_p = anim->resourceData + getFrameHeaderLength(); + anim->cur_frame_len = anim->resourceLength - getFrameHeaderLength(); } 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; - 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_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 = readS.readByte(); switch (in_ch) { - case 0x0F: // 15: Frame header + case SAGA_FRAME_START: // Frame header { int param1; int param2; @@ -702,12 +713,16 @@ void Anim::fillFrameOffsets(AnimationData *anim) { 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++) { anim->frameOffsets[currentFrame] = readS.pos(); @@ -723,14 +738,14 @@ void Anim::fillFrameOffsets(AnimationData *anim) { } // 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 // endian format, but the actual RLE encoded frame data, // including the frame header, is in big endian format. */ do { 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) { case SAGA_FRAME_END: // End of frame marker diff --git a/saga/animation.h b/saga/animation.h index ef6ebbd7d4..1a9df5df06 100644 --- a/saga/animation.h +++ b/saga/animation.h @@ -33,7 +33,6 @@ namespace Saga { #define MAX_ANIMATIONS 7 #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_END 0x3F @@ -146,6 +145,10 @@ private: } } + int getFrameHeaderLength() const { + return (_vm->getFeatures() & GF_MAC_RESOURCES ? 13 : 12); + } + AnimationData* getAnimation(uint16 animId) { validateAnimationId(animId); return _animations[animId]; diff --git a/saga/console.cpp b/saga/console.cpp index cb5df66190..8cd411fbd9 100644 --- a/saga/console.cpp +++ b/saga/console.cpp @@ -66,18 +66,8 @@ Console::Console(SagaEngine *vm) : Common::Debugger<Console>() { // Scene commands DCmd_Register("scene_change", &Console::cmdSceneChange); - DCmd_Register("scene_info", &Console::cmdSceneInfo); DCmd_Register("action_map_info", &Console::cmdActionMapInfo); 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() { @@ -154,11 +144,6 @@ bool Console::cmdSceneChange(int argc, const char **argv) { return true; } -bool Console::cmdSceneInfo(int argc, const char **argv) { - _vm->_scene->cmdSceneInfo(); - return true; -} - bool Console::cmdActionMapInfo(int argc, const char **argv) { _vm->_scene->cmdActionMapInfo(); return true; @@ -169,22 +154,4 @@ bool Console::cmdObjectMapInfo(int argc, const char **argv) { 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 diff --git a/saga/console.h b/saga/console.h index 1fa005c62f..4870cb1c89 100644 --- a/saga/console.h +++ b/saga/console.h @@ -48,13 +48,9 @@ private: bool Cmd_AnimInfo(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 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: SagaEngine *_vm; diff --git a/saga/events.cpp b/saga/events.cpp index 0b7ea0c4ca..c11cecfc0b 100644 --- a/saga/events.cpp +++ b/saga/events.cpp @@ -278,7 +278,7 @@ int Events::handleOneShot(EVENT *event) { case TEXT_EVENT: switch (event->op) { case EVENT_DISPLAY: - ((TextListEntry *)event->data)->display = 1; + ((TextListEntry *)event->data)->display = true; break; case EVENT_REMOVE: _vm->_scene->_textList.remove((TextListEntry *)event->data); @@ -299,7 +299,7 @@ int Events::handleOneShot(EVENT *event) { case MUSIC_EVENT: _vm->_music->stop(); if (event->op == EVENT_PLAY) - _vm->_music->play(event->param, event->param2); + _vm->_music->play(event->param, (MusicFlags)event->param2); break; case BG_EVENT: { @@ -332,9 +332,9 @@ int Events::handleOneShot(EVENT *event) { } if (event->param == SET_PALETTE) { - PalEntry *pal_p; - _vm->_scene->getBGPal(&pal_p); - _vm->_gfx->setPalette(pal_p); + PalEntry *palPointer; + _vm->_scene->getBGPal(palPointer); + _vm->_gfx->setPalette(palPointer); } } } diff --git a/saga/font.cpp b/saga/font.cpp index 4af061eb6d..37ca014b1d 100644 --- a/saga/font.cpp +++ b/saga/font.cpp @@ -24,8 +24,7 @@ // Font management and font drawing module #include "saga/saga.h" #include "saga/gfx.h" - -#include "saga/rscfile_mod.h" +#include "saga/rscfile.h" #include "saga/font.h" #include "saga/stream.h" @@ -69,26 +68,24 @@ void Font::loadFont(uint32 fontResourceId) { size_t fontResourceLength; int numBits; int c; - RSCFILE_CONTEXT *fontContext; + ResourceContext *fontContext; debug(1, "Font::loadFont(): Reading fontResourceId %d...", fontResourceId); - fontContext = _vm->getFileContext(GAME_RESOURCEFILE, 0); + fontContext = _vm->_resource->getContext(GAME_RESOURCEFILE); if (fontContext == NULL) { - error("Font::Font(): Couldn't get resource context."); + error("Font::Font() resource context not found"); } // Load font resource - if (RSC_LoadResource(fontContext, fontResourceId, &fontResourcePointer, &fontResourceLength) != SUCCESS) { - error("Font::loadFont(): Couldn't load font resource."); - } + _vm->_resource->loadResource(fontContext, fontResourceId, fontResourcePointer, fontResourceLength); 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 font = (FontData *)malloc(sizeof(*font)); @@ -127,7 +124,7 @@ void Font::loadFont(uint32 fontResourceId) { font->normal.font = (byte*)malloc(fontResourceLength - FONT_DESCSIZE); memcpy(font->normal.font, fontResourcePointer + FONT_DESCSIZE, fontResourceLength - FONT_DESCSIZE); - RSC_FreeResource(fontResourcePointer); + free(fontResourcePointer); // 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; } - if (fitWidth >= textWidth) { - // Entire string fits, draw it - textPoint.x = textPoint.x - (textWidth / 2); - draw(fontId, ds, text, textLength, textPoint, color, effectColor, flags); + if (fitWidth < textWidth) { + warning("text too long to be displayed in one line"); 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) { diff --git a/saga/font.h b/saga/font.h index 5b5963b9b4..70a15ee451 100644 --- a/saga/font.h +++ b/saga/font.h @@ -54,9 +54,10 @@ namespace Saga { #define TEXT_LINESPACING 2 struct TextListEntry { - int display; -// int id; + bool display; + bool useRect; Common::Point point; + Common::Rect rect; int color; int effectColor; FontEffectFlags flags; diff --git a/saga/game.cpp b/saga/game.cpp index fba3af5890..d3481b182a 100644 --- a/saga/game.cpp +++ b/saga/game.cpp @@ -32,9 +32,10 @@ #include "base/gameDetector.h" #include "backends/fs/fs.h" -#include "saga/rscfile_mod.h" +#include "saga/rscfile.h" #include "saga/interface.h" #include "saga/scene.h" +#include "saga/resnames.h" namespace Saga { @@ -202,11 +203,6 @@ static GameSoundInfo ITEDEMO_GameSound = { GAME_SOUND_VOC, 0, 0, 0 }; -static GameFontDescription ITEMACDEMO_GameFonts[] = { - {2}, - {0} -}; - // Inherit the Earth - Wyrmkeep Win32 Demo version static GameFileDescription ITEWINDEMO_GameFiles[] = { {"ited.rsc", GAME_RESOURCEFILE}, @@ -215,6 +211,11 @@ static GameFileDescription ITEWINDEMO_GameFiles[] = { {"voicesd.rsc", GAME_VOICEFILE} }; +static GameFontDescription ITEWINDEMO_GameFonts[] = { + {2}, + {0} +}; + // Inherit the Earth - Wyrmkeep Linux Demo version static GameFileDescription ITELINDEMO_GameFiles[] = { {"ited.rsc", GAME_RESOURCEFILE}, @@ -247,11 +248,6 @@ static GameFileDescription ITEMULTICD_GameFiles[] = { {"music.rsc", GAME_MUSICFILE} }; -static GameFontDescription ITEWINDEMO_GameFonts[] = { - {2}, - {0} -}; - // Inherit the Earth - Mac Wyrmkeep version static GameFileDescription ITEMACCD_GameFiles[] = { {"ite.rsc", GAME_RESOURCEFILE}, @@ -274,7 +270,7 @@ static GameFontDescription ITEDISK_GameFonts[] = { {1} }; -static GameSoundInfo ITE_GameSound = { +static GameSoundInfo ITEDISK_GameSound = { GAME_SOUND_VOC, 0, 0, 0 }; @@ -296,7 +292,79 @@ static GameSoundInfo ITECD_GameSound = { GAME_SOUND_PCM, 22050, 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 @@ -588,6 +656,8 @@ static GameDescription gameDescriptions[] = { ARRAYSIZE(ITEDEMO_GameFonts), ITEDEMO_GameFonts, &ITEDEMO_GameSound, + 0, + NULL, 0, // features }, @@ -602,9 +672,11 @@ static GameDescription gameDescriptions[] = { &ITE_Resources, ARRAYSIZE(ITEWINDEMO_GameFiles), ITEWINDEMO_GameFiles, - ARRAYSIZE(ITEMACDEMO_GameFonts), - ITEMACDEMO_GameFonts, + ARRAYSIZE(ITEWINDEMO_GameFonts), + ITEWINDEMO_GameFonts, &ITECD_GameSound, + ARRAYSIZE(ITEMacPatch_Files), + ITEMacPatch_Files, GF_VOX_VOICES | GF_BIG_ENDIAN_DATA | GF_MAC_RESOURCES | GF_WYRMKEEP | GF_CD_FX }, @@ -619,9 +691,11 @@ static GameDescription gameDescriptions[] = { &ITE_Resources, ARRAYSIZE(ITEWINDEMO_GameFiles), ITEWINDEMO_GameFiles, - ARRAYSIZE(ITEMACDEMO_GameFonts), - ITEMACDEMO_GameFonts, + ARRAYSIZE(ITEWINDEMO_GameFonts), + ITEWINDEMO_GameFonts, &ITECD_GameSound, + ARRAYSIZE(ITEMacPatch_Files), + ITEMacPatch_Files, GF_VOX_VOICES | GF_BIG_ENDIAN_DATA | GF_MAC_RESOURCES | GF_WYRMKEEP | GF_CD_FX }, @@ -636,9 +710,11 @@ static GameDescription gameDescriptions[] = { &ITE_Resources, ARRAYSIZE(ITEMACCD_GameFiles), ITEMACCD_GameFiles, - ARRAYSIZE(ITEMACDEMO_GameFonts), - ITEMACDEMO_GameFonts, + ARRAYSIZE(ITEWINDEMO_GameFonts), + ITEWINDEMO_GameFonts, &ITECD_GameSound, + ARRAYSIZE(ITEMacPatch_Files), + ITEMacPatch_Files, GF_BIG_ENDIAN_DATA | GF_MAC_RESOURCES | GF_WYRMKEEP | GF_CD_FX }, @@ -657,6 +733,8 @@ static GameDescription gameDescriptions[] = { ARRAYSIZE(ITECD_GameFonts), ITECD_GameFonts, &ITECD_GameSound, + 0, + NULL, GF_VOX_VOICES | GF_WYRMKEEP | GF_CD_FX }, @@ -674,6 +752,8 @@ static GameDescription gameDescriptions[] = { ARRAYSIZE(ITEWINDEMO_GameFonts), ITEWINDEMO_GameFonts, &ITECD_GameSound, + ARRAYSIZE(ITEWinPatch2_Files), + ITEWinPatch2_Files, GF_VOX_VOICES | GF_WYRMKEEP | GF_CD_FX }, @@ -691,6 +771,8 @@ static GameDescription gameDescriptions[] = { ARRAYSIZE(ITEWINDEMO_GameFonts), ITEWINDEMO_GameFonts, &ITECD_GameSound, + ARRAYSIZE(ITEWinPatch1_Files), + ITEWinPatch1_Files, GF_VOX_VOICES | GF_WYRMKEEP | GF_CD_FX }, @@ -708,6 +790,8 @@ static GameDescription gameDescriptions[] = { ARRAYSIZE(ITECD_GameFonts), ITECD_GameFonts, &ITECD_GameSound, + 0, + NULL, GF_WYRMKEEP | GF_BIG_ENDIAN_VOICES | GF_CD_FX }, @@ -726,6 +810,8 @@ static GameDescription gameDescriptions[] = { ARRAYSIZE(ITECD_GameFonts), ITECD_GameFonts, &ITECD_GameSound, + 0, + NULL, GF_WYRMKEEP | GF_CD_FX }, @@ -743,6 +829,8 @@ static GameDescription gameDescriptions[] = { ARRAYSIZE(ITECD_GameFonts), ITECD_GameFonts, &ITECD_GameSound, + 0, + NULL, GF_CD_FX }, @@ -760,6 +848,8 @@ static GameDescription gameDescriptions[] = { ARRAYSIZE(ITECD_GameFonts), ITECD_GameFonts, &ITECD_GameSound, + 0, + NULL, GF_LANG_DE | GF_CD_FX }, @@ -777,6 +867,8 @@ static GameDescription gameDescriptions[] = { ARRAYSIZE(ITECD_GameFonts), ITECD_GameFonts, &ITECD_GameSound, + 0, + NULL, GF_CD_FX }, @@ -793,7 +885,9 @@ static GameDescription gameDescriptions[] = { ITEDISK_GameFiles, ARRAYSIZE(ITEDISK_GameFonts), ITEDISK_GameFonts, - &ITE_GameSound, + &ITEDISK_GameSound, + 0, + NULL, GF_LANG_DE }, @@ -810,7 +904,9 @@ static GameDescription gameDescriptions[] = { ITEDISK_GameFiles, ARRAYSIZE(ITEDISK_GameFonts), ITEDISK_GameFonts, - &ITE_GameSound, + &ITEDISK_GameSound, + 0, + NULL, 0 }, @@ -828,6 +924,8 @@ static GameDescription gameDescriptions[] = { ARRAYSIZE(IHNMCD_GameFonts), IHNMCD_GameFonts, &IHNM_GameSound, + 0, + NULL, GF_DEFAULT_TO_1X_SCALER }, @@ -845,6 +943,8 @@ static GameDescription gameDescriptions[] = { ARRAYSIZE(IHNMCD_GameFonts), IHNMCD_GameFonts, &IHNM_GameSound, + 0, + NULL, GF_DEFAULT_TO_1X_SCALER }, @@ -862,56 +962,39 @@ static GameDescription gameDescriptions[] = { ARRAYSIZE(IHNMCD_GameFonts), IHNMCD_GameFonts, &IHNM_GameSound, + 0, + NULL, GF_DEFAULT_TO_1X_SCALER } }; -int SagaEngine::initGame(void) { +bool SagaEngine::initGame(void) { + uint16 gameCount = ARRAYSIZE(gameDescriptions); int gameNumber; FSList dummy; if ((gameNumber = detectGame(dummy)) == -1) { 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; - } - return SUCCESS; -} -RSCFILE_CONTEXT *SagaEngine::getFileContext(uint16 type, int param) { - uint16 i; - - for (i = 0; i < _gameDescription->filesCount; i++) { - if (_gameDescription->filesDescriptions[i].fileType & type) { - return _gameFileContexts[i]; - } + if (gameNumber >= gameCount) { + error("SagaEngine::loadGame wrong gameNumber"); } - return NULL; -} - -bool SagaEngine::isBigEndianFile(const char *filename) { - bool isBigEndian = IS_BIG_ENDIAN; - - if (isBigEndian) - return true; + _gameNumber = gameNumber; + _gameDescription = &gameDescriptions[gameNumber]; + _gameDisplayInfo = *_gameDescription->gameDisplayInfo; + _displayClip.right = _gameDisplayInfo.logicalWidth; + _displayClip.bottom = _gameDisplayInfo.logicalHeight; - 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; - } + if (!_resource->createContexts()) { + return false; } - - return isBigEndian; + return true; } DetectedGameList GAME_ProbeGame(const FSList &fslist) { @@ -1044,45 +1127,4 @@ int detectGame(const FSList &fslist, bool mode) { 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 diff --git a/saga/gfx.cpp b/saga/gfx.cpp index e9c9bb1eec..74f02728dd 100644 --- a/saga/gfx.cpp +++ b/saga/gfx.cpp @@ -31,7 +31,7 @@ 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(); _vm->initCommonGFX(detector); _system->initSize(width, height); diff --git a/saga/gfx.h b/saga/gfx.h index 13202781e3..aa47bf5da6 100644 --- a/saga/gfx.h +++ b/saga/gfx.h @@ -123,11 +123,12 @@ struct Surface : Graphics::Surface { #define CURSOR_ORIGIN_Y 4 bool hitTestPoly(const Point *points, unsigned int npoints, const Point& test_point); +class SagaEngine; class Gfx { public: - Gfx(OSystem *system, int width, int height, GameDetector &detector); + Gfx(SagaEngine *vm, OSystem *system, int width, int height, GameDetector &detector); ~Gfx(); Surface *getBackBuffer() { return &_backBuffer; @@ -146,6 +147,7 @@ private: Surface _backBuffer; byte _currentPal[PAL_ENTRIES * 4]; OSystem *_system; + SagaEngine *_vm; }; } // End of namespace Saga diff --git a/saga/ihnm_introproc.cpp b/saga/ihnm_introproc.cpp index bece587e3a..fd27049d71 100644 --- a/saga/ihnm_introproc.cpp +++ b/saga/ihnm_introproc.cpp @@ -28,7 +28,6 @@ #include "saga/animation.h" #include "saga/events.h" -#include "saga/rscfile_mod.h" #include "saga/sndres.h" #include "saga/music.h" @@ -36,9 +35,9 @@ namespace Saga { -SCENE_RESLIST IHNM_IntroMovie1RL[] = { - {30, SAGA_BG_IMAGE, 0, 0} , - {31, SAGA_ANIM_1, 0, 0} +SceneResourceData IHNM_IntroMovie1RL[] = { + {30, SAGA_BG_IMAGE, 0, 0, false} , + {31, SAGA_ANIM_1, 0, 0, false} }; SceneDescription IHNM_IntroMovie1Desc = { @@ -47,9 +46,9 @@ SceneDescription IHNM_IntroMovie1Desc = { ARRAYSIZE(IHNM_IntroMovie1RL) }; -SCENE_RESLIST IHNM_IntroMovie2RL[] = { - {32, SAGA_BG_IMAGE, 0, 0} , - {33, SAGA_ANIM_1, 0, 0} +SceneResourceData IHNM_IntroMovie2RL[] = { + {32, SAGA_BG_IMAGE, 0, 0, false} , + {33, SAGA_ANIM_1, 0, 0, false} }; SceneDescription IHNM_IntroMovie2Desc = { @@ -58,9 +57,9 @@ SceneDescription IHNM_IntroMovie2Desc = { ARRAYSIZE(IHNM_IntroMovie2RL) }; -SCENE_RESLIST IHNM_IntroMovie3RL[] = { - {34, SAGA_BG_IMAGE, 0, 0}, - {35, SAGA_ANIM_1, 0, 0} +SceneResourceData IHNM_IntroMovie3RL[] = { + {34, SAGA_BG_IMAGE, 0, 0, false}, + {35, SAGA_ANIM_1, 0, 0, false} }; SceneDescription IHNM_IntroMovie3Desc = { @@ -69,9 +68,9 @@ SceneDescription IHNM_IntroMovie3Desc = { ARRAYSIZE(IHNM_IntroMovie3RL) }; -SCENE_RESLIST IHNM_IntroMovie4RL[] = { - {1227, SAGA_BG_IMAGE, 0, 0}, - {1226, SAGA_ANIM_1, 0, 0} +SceneResourceData IHNM_IntroMovie4RL[] = { + {1227, SAGA_BG_IMAGE, 0, 0, false}, + {1226, SAGA_ANIM_1, 0, 0, false} }; SceneDescription IHNM_IntroMovie4Desc = { @@ -207,7 +206,7 @@ int Scene::IHNMIntroMovieProc2(int param) { q_event = _vm->_events->chain(q_event, &event); // Fade in from black to the scene background palette - _vm->_scene->getBGPal(&pal); + _vm->_scene->getBGPal(pal); event.type = CONTINUOUS_EVENT; event.code = PAL_EVENT; @@ -275,7 +274,7 @@ int Scene::IHNMIntroMovieProc3(int param) { event.type = ONESHOT_EVENT; event.code = MUSIC_EVENT; event.param = 1; - event.param2 = 0; + event.param2 = MUSIC_NORMAL; event.op = EVENT_PLAY; event.time = 0; @@ -292,7 +291,7 @@ int Scene::IHNMIntroMovieProc3(int param) { q_event = _vm->_events->chain(q_event, &event); // Fade in from black to the scene background palette - _vm->_scene->getBGPal(&pal); + _vm->_scene->getBGPal(pal); event.type = CONTINUOUS_EVENT; event.code = PAL_EVENT; diff --git a/saga/image.cpp b/saga/image.cpp index 2ca190c266..1cf527ac43 100644 --- a/saga/image.cpp +++ b/saga/image.cpp @@ -58,11 +58,10 @@ int SagaEngine::decodeBGImage(const byte *image_data, size_t image_size, size_t out_buf_len; if (image_size <= SAGA_IMAGE_DATA_OFFSET) { - /* Image size is way too small */ - return FAILURE; + error("decodeBGImage() Image size is way too small"); } - MemoryReadStreamEndian readS(image_data, image_size, IS_BIG_ENDIAN); + MemoryReadStreamEndian readS(image_data, image_size, isBigEndian()); hdr.width = 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); // 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); } diff --git a/saga/input.cpp b/saga/input.cpp index b4362c07b1..bba4973696 100644 --- a/saga/input.cpp +++ b/saga/input.cpp @@ -76,7 +76,7 @@ int SagaEngine::processInput() { break;*/ case 282: // F1 _render->toggleFlag(RF_SHOW_FPS); - _vm->_actor->_handleActionDiv = (_vm->_actor->_handleActionDiv == 15) ? 50 : 15; + _actor->_handleActionDiv = (_actor->_handleActionDiv == 15) ? 50 : 15; break; case 283: // F2 _render->toggleFlag(RF_PALETTE_TEST); @@ -94,9 +94,6 @@ int SagaEngine::processInput() { break; case 289: // F8 break; - case 9: // Tab - _script->SThreadDebugStep(); - break; // Actual game keys case 32: // space @@ -140,7 +137,7 @@ int SagaEngine::processInput() { _mousePos = event.mouse; break; case OSystem::EVENT_QUIT: - _vm->shutDown(); + shutDown(); break; default: break; diff --git a/saga/interface.cpp b/saga/interface.cpp index 2968b512c5..47d1d69a71 100644 --- a/saga/interface.cpp +++ b/saga/interface.cpp @@ -33,10 +33,11 @@ #include "saga/itedata.h" #include "saga/puzzle.h" #include "saga/render.h" -#include "saga/rscfile_mod.h" #include "saga/scene.h" #include "saga/script.h" #include "saga/sprite.h" +#include "saga/rscfile.h" +#include "saga/resnames.h" #include "saga/interface.h" @@ -63,21 +64,16 @@ static int verbTypeToTextStringsIdLUT[kVerbTypesMax] = { -1 }; -Interface::Interface(SagaEngine *vm) : _vm(vm), _initialized(false) { +Interface::Interface(SagaEngine *vm) : _vm(vm) { byte *resource; size_t resourceLength; - int result; int i; - - if (_initialized) { - return; - } // Load interface module resource file context - _interfaceContext = _vm->getFileContext(GAME_RESOURCEFILE, 0); + _interfaceContext = _vm->_resource->getContext(GAME_RESOURCEFILE); if (_interfaceContext == NULL) { - error("Interface::Interface(): unable to load resource"); + error("Interface::Interface() resource context not found"); } _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); - if ((result != SUCCESS) || (resourceLength == 0)) { - error("Interface::Interface(): unable to load mainPanel resource"); - } + _vm->_resource->loadResource(_interfaceContext, _vm->getResourceDescription()->mainPanelResourceId, resource, resourceLength); _vm->decodeBGImage(resource, resourceLength, &_mainPanel.image, &_mainPanel.imageLength, &_mainPanel.imageWidth, &_mainPanel.imageHeight); - RSC_FreeResource(resource); + free(resource); _conversePanel.buttons = _vm->getDisplayInfo().conversePanelButtons; _conversePanel.buttonsCount = _vm->getDisplayInfo().conversePanelButtonsCount; - result = RSC_LoadResource(_interfaceContext, _vm->getResourceDescription()->conversePanelResourceId, &resource, &resourceLength); - if ((result != SUCCESS) || (resourceLength == 0)) { - error("Interface::Interface unable to load conversePanel resource"); - } + _vm->_resource->loadResource(_interfaceContext, _vm->getResourceDescription()->conversePanelResourceId, resource, resourceLength); _vm->decodeBGImage(resource, resourceLength, &_conversePanel.image, &_conversePanel.imageLength, &_conversePanel.imageWidth, &_conversePanel.imageHeight); - RSC_FreeResource(resource); + free(resource); _optionPanel.buttons = _vm->getDisplayInfo().optionPanelButtons; _optionPanel.buttonsCount = _vm->getDisplayInfo().optionPanelButtonsCount; - result = RSC_LoadResource(_interfaceContext, _vm->getResourceDescription()->optionPanelResourceId, &resource, &resourceLength); - if ((result != SUCCESS) || (resourceLength == 0)) { - error("Interface::Interface unable to load optionPanel resource"); - } + _vm->_resource->loadResource(_interfaceContext, _vm->getResourceDescription()->optionPanelResourceId, resource, resourceLength); _vm->decodeBGImage(resource, resourceLength, &_optionPanel.image, &_optionPanel.imageLength, &_optionPanel.imageWidth, &_optionPanel.imageHeight); - RSC_FreeResource(resource); + free(resource); - if (_vm->_sprite->loadList(_vm->getResourceDescription()->mainPanelSpritesResourceId, _mainPanel.sprites) != SUCCESS) { - error("Interface::Interface(): Unable to load sprite list"); - } + _vm->_sprite->loadList(_vm->getResourceDescription()->mainPanelSpritesResourceId, _mainPanel.sprites); if (_vm->getGameType() == GType_ITE) { - if (_vm->_sprite->loadList(_vm->getResourceDescription()->defaultPortraitsResourceId, _defPortraits) != SUCCESS) { - error("Interface::Interface(): Unable to load sprite list"); - } + _vm->_sprite->loadList(_vm->getResourceDescription()->defaultPortraitsResourceId, _defPortraits); } else { // TODO } @@ -212,8 +195,6 @@ Interface::Interface(SagaEngine *vm) : _vm(vm), _initialized(false) { _textInput = false; _statusTextInput = false; _statusTextInputState = kStatusTextInputFirstRun; - - _initialized = true; } Interface::~Interface(void) { @@ -222,7 +203,6 @@ Interface::~Interface(void) { _mainPanel.sprites.freeMem(); _defPortraits.freeMem(); _scenePortraits.freeMem(); - _initialized = false; } int Interface::activate() { @@ -505,10 +485,10 @@ void Interface::setStatusText(const char *text, int statusColor) { drawStatusBar(); } -int Interface::loadScenePortraits(int resourceId) { +void Interface::loadScenePortraits(int resourceId) { _scenePortraits.freeMem(); - return _vm->_sprite->loadList(resourceId, _scenePortraits); + _vm->_sprite->loadList(resourceId, _scenePortraits); } void Interface::drawVerbPanel(Surface *backBuffer, PanelButton* panelButton) { @@ -2037,7 +2017,6 @@ void Interface::mapPanelShow() { Rect rect; byte *image; int imageWidth, imageHeight; - int result; const byte *pal; PalEntry cPal[PAL_ENTRIES]; @@ -2047,9 +2026,9 @@ void Interface::mapPanelShow() { rect.left = rect.top = 0; - result = RSC_LoadResource(_interfaceContext, RID_ITE_TYCHO_MAP, &resource, &resourceLength); - if ((result != SUCCESS) || (resourceLength == 0)) { - error("Interface::mapPanelShow(): unable to load Tycho map resource"); + _vm->_resource->loadResource(_interfaceContext, RID_ITE_TYCHO_MAP, resource, resourceLength); + if (resourceLength == 0) { + error("Interface::mapPanelShow() unable to load Tycho map resource"); } _vm->_gfx->getCurrentPal(_mapSavedPal); @@ -2083,7 +2062,7 @@ void Interface::mapPanelShow() { _vm->_system->delayMillis(5); } - RSC_FreeResource(resource); + free(resource); free(image); setSaveReminderState(false); diff --git a/saga/interface.h b/saga/interface.h index 050169a9bd..d79f1b6761 100644 --- a/saga/interface.h +++ b/saga/interface.h @@ -209,7 +209,7 @@ public: void restoreMode(); bool isInMainMode() { return _inMainMode; } void setStatusText(const char *text, int statusColor = -1); - int loadScenePortraits(int resourceId); + void loadScenePortraits(int resourceId); void setLeftPortrait(int portrait) { _leftPortrait = portrait; draw(); @@ -376,8 +376,7 @@ private: private: SagaEngine *_vm; - bool _initialized; - RSCFILE_CONTEXT *_interfaceContext; + ResourceContext *_interfaceContext; InterfacePanel _mainPanel; PanelButton *_inventoryUpButton; PanelButton *_inventoryDownButton; diff --git a/saga/isomap.cpp b/saga/isomap.cpp index 311d445afd..7852f0adc8 100644 --- a/saga/isomap.cpp +++ b/saga/isomap.cpp @@ -114,7 +114,7 @@ void IsoMap::loadImages(const byte *resourcePointer, size_t resourceLength) { _tileDataLength = resourceLength; memcpy(_tileData, resourcePointer, resourceLength); - MemoryReadStreamEndian readS(_tileData, _tileDataLength, IS_BIG_ENDIAN); + MemoryReadStreamEndian readS(_tileData, _tileDataLength, _vm->isBigEndian()); readS.readUint16(); // skip _tilesCount = readS.readUint16(); _tilesCount = _tilesCount / SAGA_ISOTILEDATA_LEN; @@ -146,7 +146,7 @@ void IsoMap::loadPlatforms(const byte * resourcePointer, size_t resourceLength) error("IsoMap::loadPlatforms wrong resourceLength"); } - MemoryReadStreamEndian readS(resourcePointer, resourceLength, IS_BIG_ENDIAN); + MemoryReadStreamEndian readS(resourcePointer, resourceLength, _vm->isBigEndian()); _tilePlatformsCount = resourceLength / SAGA_TILEPLATFORMDATA_LEN; _tilePlatformList = (TilePlatformData *)malloc(_tilePlatformsCount * sizeof(*_tilePlatformList)); @@ -177,7 +177,7 @@ void IsoMap::loadMap(const byte * resourcePointer, size_t resourceLength) { error("IsoMap::loadMap wrong resourceLength"); } - MemoryReadStreamEndian readS(resourcePointer, resourceLength, IS_BIG_ENDIAN); + MemoryReadStreamEndian readS(resourcePointer, resourceLength, _vm->isBigEndian()); _tileMap.edgeType = readS.readByte(); readS.readByte(); //skip @@ -197,7 +197,7 @@ void IsoMap::loadMetaTiles(const byte * resourcePointer, size_t resourceLength) error("IsoMap::loadMetaTiles wrong resourceLength"); } - MemoryReadStreamEndian readS(resourcePointer, resourceLength, IS_BIG_ENDIAN); + MemoryReadStreamEndian readS(resourcePointer, resourceLength, _vm->isBigEndian()); _metaTilesCount = resourceLength / SAGA_METATILEDATA_LEN; _metaTileList = (MetaTileData *)malloc(_metaTilesCount * sizeof(*_metaTileList)); @@ -224,7 +224,7 @@ void IsoMap::loadMulti(const byte * resourcePointer, size_t resourceLength) { error("IsoMap::loadMetaTiles wrong resourceLength"); } - MemoryReadStreamEndian readS(resourcePointer, resourceLength, IS_BIG_ENDIAN); + MemoryReadStreamEndian readS(resourcePointer, resourceLength, _vm->isBigEndian()); _multiCount = readS.readUint16(); _multiTable = (MultiTileEntryData *)malloc(_multiCount * sizeof(*_multiTable)); if (_multiTable == NULL) { diff --git a/saga/ite_introproc.cpp b/saga/ite_introproc.cpp index 5da6b42cbe..a42a715233 100644 --- a/saga/ite_introproc.cpp +++ b/saga/ite_introproc.cpp @@ -30,12 +30,13 @@ #include "saga/animation.h" #include "saga/events.h" #include "saga/font.h" -#include "saga/rscfile_mod.h" #include "saga/sndres.h" #include "saga/palanim.h" #include "saga/music.h" #include "saga/scene.h" +#include "saga/resnames.h" +#include "saga/rscfile.h" namespace Saga { @@ -56,17 +57,17 @@ LoadSceneParams ITE_IntroList[] = { }; int Scene::ITEStartProc() { - size_t n_introscenes; + size_t scenesCount; size_t i; LoadSceneParams firstScene; 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.sceneDescriptor = RSC_ConvertID(tempScene.sceneDescriptor); + tempScene.sceneDescriptor = _vm->_resource->convertResourceId(tempScene.sceneDescriptor); _vm->_scene->queueScene(&tempScene); } @@ -94,8 +95,11 @@ EVENT *Scene::ITEQueueDialogue(EVENT *q_event, int n_dialogues, const INTRO_DIAL // Queue narrator dialogue list textEntry.color = 255; textEntry.effectColor = 0; - textEntry.point.x = 320 / 2; - textEntry.point.y = (_vm->getFeatures() & GF_LANG_DE) ? INTRO_DE_CAPTION_Y : INTRO_CAPTION_Y; + textEntry.useRect = true; + 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.flags = (FontEffectFlags)(kFontOutline | kFontCentered); @@ -754,7 +758,7 @@ int Scene::ITEIntroValleyProc(int param) { event.type = ONESHOT_EVENT; event.code = MUSIC_EVENT; event.param = MUSIC_2; - event.param2 = 0; + event.param2 = MUSIC_NORMAL; event.op = EVENT_PLAY; event.time = 0; diff --git a/saga/music.cpp b/saga/music.cpp index 2ec8e1ed13..97ed39cb1b 100644 --- a/saga/music.cpp +++ b/saga/music.cpp @@ -22,8 +22,8 @@ */ #include "saga/saga.h" +#include "saga/rscfile.h" #include "saga/music.h" -#include "saga/rscfile_mod.h" #include "saga/stream.h" #include "sound/audiostream.h" #include "sound/mididrv.h" @@ -42,10 +42,11 @@ namespace Saga { class RAWInputStream : public AudioStream { private: + ResourceContext *_context; Common::File *_file; - uint32 _file_pos; - uint32 _start_pos; - uint32 _end_pos; + uint32 _filePos; + uint32 _startPos; + uint32 _endPos; bool _finished; bool _looping; int16 _buf[BUFFER_SIZE]; @@ -53,11 +54,12 @@ private: const int16 *_pos; void refill(); - inline bool eosIntern() const; + bool eosIntern() const { + return _pos >= _bufferEnd; + } public: - RAWInputStream(Common::File *file, int size, bool looping); - ~RAWInputStream(); + RAWInputStream(SagaEngine *vm, ResourceContext *context, uint32 resourceId, bool looping); int readBuffer(int16 *buffer, const int numSamples); @@ -66,28 +68,23 @@ public: int getRate() const { return 11025; } }; -RAWInputStream::RAWInputStream(Common::File *file, int size, bool looping) - : _file(file), _finished(false), _looping(looping), - _bufferEnd(_buf + BUFFER_SIZE) { +RAWInputStream::RAWInputStream(SagaEngine *vm, ResourceContext *context, uint32 resourceId, bool looping) + : _context(context), _finished(false), _looping(looping), _bufferEnd(_buf + BUFFER_SIZE) { + + ResourceData * resourceData; - _file->incRef(); + resourceData = vm->_resource->getResourceData(context, resourceId); + _file = context->getFile(resourceData); // Determine the end position - _file_pos = _file->pos(); - _start_pos = _file_pos; - _end_pos = _file_pos + size; + _startPos = resourceData->offset; + _endPos = _startPos + resourceData->size; + _filePos = _startPos; // Read in initial data refill(); } -RAWInputStream::~RAWInputStream() { - _file->decRef(); -} - -inline bool RAWInputStream::eosIntern() const { - return _pos >= _bufferEnd; -} int RAWInputStream::readBuffer(int16 *buffer, const int numSamples) { int samples = 0; @@ -108,61 +105,47 @@ void RAWInputStream::refill() { if (_finished) return; - uint32 len_left; + uint32 lengthLeft; byte *ptr = (byte *) _buf; - _file->seek(_file_pos, SEEK_SET); + _file->seek(_filePos, SEEK_SET); if (_looping) - len_left = 2 * BUFFER_SIZE; + lengthLeft = 2 * BUFFER_SIZE; else - len_left = MIN((uint32) (2 * BUFFER_SIZE), _end_pos - _file_pos); + lengthLeft = MIN((uint32) (2 * BUFFER_SIZE), _endPos - _filePos); - while (len_left > 0) { - uint32 len = _file->read(ptr, MIN(len_left, _end_pos - _file->pos())); + while (lengthLeft > 0) { + uint32 len = _file->read(ptr, MIN(lengthLeft, _endPos - _file->pos())); if (len & 1) len--; - if (_vm->getFeatures() & GF_BIG_ENDIAN_DATA) { + if (_context->isBigEndian) { uint16 *ptr16 = (uint16 *)ptr; for (uint32 i = 0; i < (len / 2); i++) ptr16[i] = TO_BE_16(ptr16[i]); } - len_left -= len; + lengthLeft -= len; ptr += len; - if (len_left > 0) - _file->seek(_start_pos); + if (lengthLeft > 0) + _file->seek(_startPos); } - _file_pos = _file->pos(); + _filePos = _file->pos(); _pos = _buf; _bufferEnd = (int16 *)ptr; - if (!_looping && _file_pos >= _end_pos) + if (!_looping && _filePos >= _endPos) { _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)); _masterVolume = 0; this->open(); @@ -274,19 +257,20 @@ void MusicPlayer::stopMusic() { _isPlaying = false; if (_parser) { _parser->unloadMusic(); - delete _parser; _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); - _musicInitialized = 1; _currentVolume = 0; + xmidiParser = MidiParser::createParser_XMIDI(); + smfParser = MidiParser::createParser_SMF(); + if (_vm->getGameType() == GType_ITE) { 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 // 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 // return File object. - _musicContext = _vm->getFileContext(GAME_MUSICFILE, 0); + _musicContext = _vm->_resource->getContext(GAME_MUSICFILE); 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 // whining. Use the MIDI/XMIDI version instead. - _digiTableITECD[6].length = 0; - } else { - _hasDigiMusic = false; - memset(_digiTableITECD, 0, sizeof(_digiTableITECD)); + ///_digiTableITECD[6].length = 0; } } } Music::~Music() { delete _player; + delete xmidiParser; + delete smfParser; } void Music::musicVolumeGaugeCallback(void *refCon) { @@ -389,169 +352,114 @@ bool Music::isPlaying() { // // 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) { - RSCFILE_CONTEXT *rsc_ctxt = NULL; - - byte *resource_data; - size_t resource_size; - if (!_musicInitialized) { - return FAILURE; - } +void Music::play(uint32 resourceId, MusicFlags flags) { + AudioStream *audioStream = NULL; + MidiParser *parser; + ResourceContext *context; + byte *resourceData; + size_t resourceSize; + debug(2, "Music::play %d, %d", resourceId, flags); if (!_enabled) { - return SUCCESS; + return; } - if (isPlaying() && _trackNumber == music_rn) { - return SUCCESS; + if (isPlaying() && _trackNumber == resourceId) { + return; } - _trackNumber = music_rn; + _trackNumber = resourceId; _player->stopMusic(); _mixer->stopHandle(_musicHandle); - AudioStream *audioStream = NULL; - MidiParser *parser; - Common::File midiFile; if (_vm->getGameType() == GType_ITE) { - if (music_rn >= 9 && music_rn <= 34) { - if (flags == MUSIC_DEFAULT) { - flags = _midiTableITECD[music_rn - 9].flags; - } - - if (_hasDigiMusic) { - 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); + if (resourceId >= 9 && resourceId <= 34) { + if (flags == MUSIC_DEFAULT) { + if ((resourceId == 13) || (resourceId == 19)) { + flags = MUSIC_NORMAL; + } else { + flags = MUSIC_LOOP; } } - // No digitized music - try standalone MIDI. - if (!audioStream) { - midiFile.open(_midiTableITECD[music_rn - 9].filename); - if (!midiFile.isOpen()) { - debug(2, "Cannot open music file %s", _midiTableITECD[music_rn - 9].filename); - } + if (_musicContext != NULL) { + //TODO: check resource size + audioStream = new RAWInputStream(_vm, _musicContext, resourceId, flags == MUSIC_LOOP); } } } - if (flags == MUSIC_DEFAULT) { - flags = 0; - } if (audioStream) { debug(2, "Playing digitized music"); _mixer->playInputStream(Audio::Mixer::kMusicSoundType, &_musicHandle, audioStream); - return SUCCESS; + return; } - // FIXME: Is resource_data ever freed? + if (flags == MUSIC_DEFAULT) { + flags = MUSIC_NORMAL; + } - if (midiFile.isOpen()) { - debug(2, "Using external MIDI file: %s", midiFile.name()); - resource_size = midiFile.size(); - resource_data = (byte *) malloc(resource_size); - midiFile.read(resource_data, resource_size); - midiFile.close(); + // FIXME: Is resource_data ever freed? + // Load MIDI/XMI resource data - _player->setGM(true); - parser = MidiParser::createParser_SMF(); + if (_vm->getGameType() == GType_ITE) { + context = _vm->_resource->getContext(GAME_RESOURCEFILE); } else { - // Load MIDI/XMI resource data - - if (_vm->getGameType() == GType_ITE) { - rsc_ctxt = _vm->getFileContext(GAME_RESOURCEFILE, 0); - } else { - // 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/ - - // 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); - } + // 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/ - _player->setGM(true); - } + // Oddly enough, the intro music (song 1) is very + // different in the two files. I have no idea why. - if (RSC_LoadResource(rsc_ctxt, music_rn, &resource_data, - &resource_size) != SUCCESS) { - warning("Music::play(): Resource load failed: %u", music_rn); - return FAILURE; + if (hasAdlib()) { + context = _vm->_resource->getContext(GAME_MUSICFILE_FM); + } else { + context = _vm->_resource->getContext(GAME_MUSICFILE_GM); } - parser = MidiParser::createParser_XMIDI(); } - if (resource_size <= 0) { - warning("Music::play(): Resource load failed: %u", music_rn); - return FAILURE; - } + _player->setGM(true); - if (!parser->loadMusic(resource_data, resource_size)) { - warning("Error reading track!"); - delete parser; - parser = 0; + _vm->_resource->loadResource(context, resourceId, resourceData, resourceSize); + + if (resourceSize < 4) { + error("Music::play() wrong music resource size"); } - debug(2, "Music::play(%d, %d)", music_rn, flags); + if (xmidiParser->loadMusic(resourceData, resourceSize)) { + parser = xmidiParser; + } else { + if (smfParser->loadMusic(resourceData, resourceSize)) { + parser = smfParser; + } else { + error("Music::play() wrong music resource"); + } + } parser->setTrack(0); parser->setMidiDriver(_player); @@ -559,37 +467,25 @@ int Music::play(uint32 music_rn, uint16 flags) { _player->_parser = parser; _player->setVolume(ConfMan.getInt("music_volume")); + if (flags & MUSIC_LOOP) _player->setLoop(true); else _player->setLoop(false); _player->playMusic(); - return SUCCESS; } -int Music::pause(void) { - if (!_musicInitialized) { - return FAILURE; - } - - return SUCCESS; +void Music::pause(void) { + //TODO: do it } -int Music::resume(void) { - if (!_musicInitialized) { - return FAILURE; - } - - return SUCCESS; +void Music::resume(void) { + //TODO: do it} } -int Music::stop(void) { - if (!_musicInitialized) { - return FAILURE; - } - - return SUCCESS; +void Music::stop(void) { + //TODO: do it } } // End of namespace Saga diff --git a/saga/music.h b/saga/music.h index 0a8ac87d64..98f6de7aa4 100644 --- a/saga/music.h +++ b/saga/music.h @@ -26,27 +26,18 @@ #ifndef SAGA_MUSIC_H_ #define SAGA_MUSIC_H_ -#include "saga/rscfile_mod.h" #include "sound/mixer.h" #include "sound/mididrv.h" #include "sound/midiparser.h" namespace Saga { -enum MUSIC_FLAGS { + +enum MusicFlags { + MUSIC_NORMAL = 0, MUSIC_LOOP = 0x0001, MUSIC_DEFAULT = 0xffff }; -struct MUSIC_MIDITABLE { - const char *filename; - int flags; -}; - -struct MUSIC_DIGITABLE { - uint32 start; - uint32 length; -}; - class MusicPlayer : public MidiDriver { public: MusicPlayer(MidiDriver *driver); @@ -106,7 +97,7 @@ protected: class Music { public: - Music(Audio::Mixer *mixer, MidiDriver *driver, int enabled); + Music(SagaEngine *vm, Audio::Mixer *mixer, MidiDriver *driver, int enabled); ~Music(void); void setNativeMT32(bool b) { _player->setNativeMT32(b); } bool hasNativeMT32() { return _player->hasNativeMT32(); } @@ -115,35 +106,31 @@ public: void setPassThrough(bool b) { _player->setPassThrough(b); } bool isPlaying(void); - int play(uint32 music_rn, uint16 flags = MUSIC_DEFAULT); - int pause(void); - int resume(void); - int stop(void); + void play(uint32 resourceId, MusicFlags flags = MUSIC_DEFAULT); + void pause(void); + void resume(void); + void stop(void); void setVolume(int volume, int time); private: - + SagaEngine *_vm; Audio::Mixer *_mixer; MusicPlayer *_player; Audio::SoundHandle _musicHandle; uint32 _trackNumber; - static const MUSIC_MIDITABLE _midiTableITECD[26]; - MUSIC_DIGITABLE _digiTableITECD[27]; - - int _musicInitialized; int _enabled; - bool _hasDigiMusic; bool _adlib; int _targetVolume; int _currentVolume; int _currentVolumePercent; - RSCFILE_CONTEXT *_musicContext; - const char *_musicFname; + ResourceContext *_musicContext; + MidiParser *xmidiParser; + MidiParser *smfParser; static void musicVolumeGaugeCallback(void *refCon); void musicVolumeGauge(void); diff --git a/saga/objectmap.cpp b/saga/objectmap.cpp index 32798e16b9..1d79f078ea 100644 --- a/saga/objectmap.cpp +++ b/saga/objectmap.cpp @@ -132,7 +132,7 @@ bool HitZone::hitTest(const Point &testPoint) { return false; } -void HitZone::draw(Surface *ds, int color) { +void HitZone::draw(SagaEngine *vm, Surface *ds, int color) { int i, pointsCount, j; Location location; HitZone::ClickArea *clickArea; @@ -140,15 +140,14 @@ void HitZone::draw(Surface *ds, int color) { for (i = 0; i < _clickAreasCount; i++) { clickArea = &_clickAreas[i]; pointsCount = clickArea->pointsCount; - if (_vm->_scene->getFlags() & kSceneFlagISO) { + if (vm->_scene->getFlags() & kSceneFlagISO) { points = (Point*)malloc(sizeof(Point) * pointsCount); for (j = 0; j < pointsCount; j++) { location.u() = clickArea->points[j].x; location.v() = clickArea->points[j].y; location.z = 0; - _vm->_isoMap->tileCoordsToScreenPoint(location, points[j]); - } - // + vm->_isoMap->tileCoordsToScreenPoint(location, points[j]); + } } else { points = clickArea->points; } @@ -162,7 +161,7 @@ void HitZone::draw(Surface *ds, int color) { ds->drawPolyLine(points, pointsCount, color); } } - if (_vm->_scene->getFlags() & kSceneFlagISO) { + if (vm->_scene->getFlags() & kSceneFlagISO) { free(points); } @@ -174,11 +173,15 @@ void HitZone::draw(Surface *ds, int color) { void ObjectMap::load(const byte *resourcePointer, size_t resourceLength) { int i; + if (resourceLength == 0) { + return; + } + if (resourceLength < 4) { error("ObjectMap::load wrong resourceLength"); } - MemoryReadStreamEndian readS(resourcePointer, resourceLength, IS_BIG_ENDIAN); + MemoryReadStreamEndian readS(resourcePointer, resourceLength, _vm->isBigEndian()); _hitZoneListCount = readS.readSint16(); if (_hitZoneListCount < 0) { @@ -232,7 +235,7 @@ void ObjectMap::draw(Surface *ds, const Point& testPoint, int color, int color2) hitZoneIndex = hitTest(pickPoint); 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) { diff --git a/saga/objectmap.h b/saga/objectmap.h index f78ac0c437..5fc52b5a3b 100644 --- a/saga/objectmap.h +++ b/saga/objectmap.h @@ -76,7 +76,7 @@ public: return objectIndexToId(kGameObjectStepZone, _index); } bool getSpecialPoint(Point &specialPoint) const; - void draw(Surface *ds, int color); + void draw(SagaEngine *vm, Surface *ds, int color); bool hitTest(const Point &testPoint); private: diff --git a/saga/palanim.cpp b/saga/palanim.cpp index 0e34731be0..96bde81987 100644 --- a/saga/palanim.cpp +++ b/saga/palanim.cpp @@ -54,7 +54,7 @@ int PalAnim::loadPalAnim(const byte *resdata, size_t resdata_len) { return FAILURE; } - MemoryReadStreamEndian readS(resdata, resdata_len, IS_BIG_ENDIAN); + MemoryReadStreamEndian readS(resdata, resdata_len, _vm->isBigEndian()); if (_vm->getGameType() == GType_IHNM) { return SUCCESS; diff --git a/saga/rscfile.cpp b/saga/rscfile.cpp index b28afb53e2..f40272c88e 100644 --- a/saga/rscfile.cpp +++ b/saga/rscfile.cpp @@ -24,300 +24,200 @@ // RSC Resource file management module #include "saga/saga.h" -#include "saga/rscfile_mod.h" #include "saga/rscfile.h" #include "saga/stream.h" namespace Saga { -static struct Substitutes { - uint32 id; - const char *resfile; - const char *fname; -} substitutes[] = { - { 1529, "ite.rsc", "wyrm.pak" }, - { 1530, "ite.rsc", "wyrm1.dlt" }, - { 1531, "ite.rsc", "wyrm2.dlt" }, - { 1532, "ite.rsc", "wyrm3.dlt" }, - { 1533, "ite.rsc", "wyrm4.dlt" }, - { 1796, "ite.rsc", "credit3n.dlt" }, - { 1797, "ite.rsc", "credit4n.dlt" } -}; - - -RSCFILE_CONTEXT *RSC_CreateContext() { - RSCFILE_CONTEXT empty_context; - empty_context.rc_file_fspec = NULL; - 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 (rsc_context->rc_file->isOpen()) { - 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; +Resource::Resource(SagaEngine *vm): _vm(vm) { + _contexts = NULL; + _contextsCount = 0; } -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; +Resource::~Resource() { + clearContexts(); } -int RSC_DestroyContext(RSCFILE_CONTEXT *rsc_context) { - RSC_CloseContext(rsc_context); +bool Resource::loadContext(ResourceContext *context) { + size_t i; + int j; + bool result; + byte tableInfo[RSC_TABLEINFO_SIZE]; + uint32 resourceTableOffset; + GamePatchDescription *patchDescription; + ResourceData *resourceData; + byte *tableBuffer; + size_t tableSize; - if (rsc_context->rc_file_loaded) { - free(rsc_context->rc_res_table); + if (!context->file->open(context->fileName)) { + return false; + } + + context->isBigEndian = _vm->isBigEndian(); + + if (!context->isBigEndian) { + context->isBigEndian = ((_vm->getFeatures() & GF_BIG_ENDIAN_VOICES) != 0) && ((context->fileType & GAME_VOICEFILE) != 0); } - 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; + if (context->file->size() < RSC_MIN_FILESIZE) { + return false; } // 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) { - return FAILURE; + if (context->file->read(tableInfo, RSC_TABLEINFO_SIZE) != RSC_TABLEINFO_SIZE) { + return false; } - - MemoryReadStreamEndian readS(tblinfo_buf, RSC_TABLEINFO_SIZE, isBigEndian); - res_tbl_offset = readS.readUint32(); - res_tbl_ct = readS.readUint32(); + MemoryReadStreamEndian readS(tableInfo, RSC_TABLEINFO_SIZE, context->isBigEndian); - // Check for sane table offset - if (res_tbl_offset != rsc->rc_file->size() - RSC_TABLEINFO_SIZE - RSC_TABLEENTRY_SIZE * res_tbl_ct) { + resourceTableOffset = readS.readUint32(); + context->count = readS.readUint32(); - return FAILURE; + // Check for sane table offset + if (resourceTableOffset != context->file->size() - RSC_TABLEINFO_SIZE - RSC_TABLEENTRY_SIZE * context->count) { + return false; } // Load resource table - tbl_len = RSC_TABLEENTRY_SIZE * res_tbl_ct; + tableSize = RSC_TABLEENTRY_SIZE * context->count; - tbl_buf = (byte *)malloc(tbl_len); - if (tbl_buf == NULL) { - return FAILURE; - } + tableBuffer = (byte *)malloc(tableSize); - rsc->rc_file->seek((long)res_tbl_offset, SEEK_SET); - - if (rsc->rc_file->read(tbl_buf, tbl_len) != tbl_len) { - free(tbl_buf); - return FAILURE; - } + context->file->seek((long)resourceTableOffset, SEEK_SET); - rsc_restbl = (RSCFILE_RESOURCE *)malloc(res_tbl_ct * sizeof(*rsc_restbl)); - if (rsc_restbl == NULL) { - free(tbl_buf); - return FAILURE; - } - - MemoryReadStreamEndian readS1(tbl_buf, tbl_len, isBigEndian); - - debug(9, "RSC %s", rsc->rc_file_fspec); - for (i = 0; i < res_tbl_ct; i++) { - rsc_restbl[i].res_offset = readS1.readUint32(); - rsc_restbl[i].res_size = readS1.readUint32(); - //debug(9, "#%x Offset:%x Size:%x", i, rsc_restbl[i].res_offset, rsc_restbl[i].res_size); - if ((rsc_restbl[i].res_offset > rsc->rc_file->size()) || (rsc_restbl[i].res_size > rsc->rc_file->size())) { - free(tbl_buf); - free(rsc_restbl); - return FAILURE; + + result = (context->file->read(tableBuffer, tableSize) == tableSize); + if (result) { + context->table = (ResourceData *)calloc(context->count, sizeof(*context->table)); + + MemoryReadStreamEndian readS1(tableBuffer, tableSize, context->isBigEndian); + + for (i = 0; i < context->count; i++) { + resourceData = &context->table[i]; + resourceData->offset = readS1.readUint32(); + resourceData->size = readS1.readUint32(); + //sanity check + if ((resourceData->offset > context->file->size()) || (resourceData->size > context->file->size())) { + result = false; + break; + } } } - rsc->rc_res_table = rsc_restbl; - rsc->rc_res_ct = res_tbl_ct; - - free(tbl_buf); - - return SUCCESS; -} - -int RSC_FreeRSC(RSCFILE_CONTEXT *rsc) { - if (!rsc->rc_file_loaded) { - return FAILURE; - } - - delete rsc->rc_file; - rsc->rc_file = NULL; - - free(rsc->rc_res_table); - - 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; + free(tableBuffer); + + //process patch files + if (result) { + for (j = 0; j < _vm->getGameDescription()->patchsCount; j++) { + patchDescription = &_vm->getGameDescription()->patchDescriptions[j]; + if ((patchDescription->fileType & context->fileType) != 0) { + if (patchDescription->resourceId < context->count) { + //TODO|fix: should we convert this ID? or make separate patch list for MAC version? + resourceData = &context->table[patchDescription->resourceId]; + resourceData->patchFile = new Common::File(); + if (resourceData->patchFile->open(patchDescription->fileName)) { + resourceData->offset = 0; + resourceData->size = resourceData->patchFile->size(); + } else { + warning("loadContext: patch file not found %s", patchDescription->fileName); + delete resourceData->patchFile; + resourceData->patchFile = NULL; + } + } + } + } } - *res_size = rsc->rc_res_table[res_num].res_size; - - return SUCCESS; + return result; } -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; +bool Resource::createContexts() { + int i, j; + ResourceContext *context; + _contextsCount = _vm->getGameDescription()->filesCount; + _contexts = (ResourceContext*)calloc(_contextsCount, sizeof(*_contexts)); + + for (i = 0; i < _contextsCount; i++) { + context = &_contexts[i]; + context->file = new Common::File(); + context->fileName = _vm->getGameDescription()->filesDescriptions[i].fileName; + context->fileType = _vm->getGameDescription()->filesDescriptions[i].fileType; + + //self check + for (j = 0; j < i; j++) { + if ((_contexts[j].fileType & context->fileType) != 0) { + error("Resource::createContexts() duplicate fileType"); + } + } + + if (!loadContext(context)) { + return false; + } } - - *res_offset = rsc->rc_res_table[res_num].res_offset; - - return SUCCESS; + return true; } -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; +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; +} - if (!(_vm->getFeatures() & GF_WYRMKEEP)) - substnum = -1; - - if (substnum != -1) { - Common::File in; - - if (in.open(substitutes[substnum].fname)) { - res_size = in.size(); - if ((res_buf = (byte *)malloc(res_size)) == NULL) - return MEM; - - in.read(res_buf, res_size); - in.close(); - debug(8, "LoadResource: substituted resource by %s", substitutes[substnum].fname); +uint32 Resource::convertResourceId(uint32 resourceId) { + + if ((_vm->getGameType() == GType_ITE) && (_vm->getFeatures() & GF_MAC_RESOURCES)) { + if (resourceId > 1537) { + return resourceId - 2; } else { - substnum = -1; + if (resourceId == 1535 || resourceId == 1536) { + error ("Wrong resource number %d for Mac ITE", resourceId); + } } } - if (substnum == -1) { - 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; - } - } + return resourceId; +} - *res_p = res_buf; +void Resource::loadResource(ResourceContext *context, uint32 resourceId, byte*&resourceBuffer, size_t &resourceSize) { + Common::File *file; + uint32 resourceOffset; + ResourceData *resourceData; - if (res_size_p != NULL) { - *res_size_p = res_size; - } - - return SUCCESS; -} + debug(8, "loadResource %d", resourceId); + + resourceData = getResourceData(context, resourceId); + + file = context->getFile(resourceData); -int RSC_FreeResource(byte *resource_ptr) { - free(resource_ptr); + resourceOffset = resourceData->offset; + resourceSize = resourceData->size; - return SUCCESS; -} + resourceBuffer = (byte*)malloc(resourceSize); -int RSC_ConvertID(int id) { - int res = id; + file->seek((long)resourceOffset, SEEK_SET); - if (_vm->getFeatures() & GF_MAC_RESOURCES) { - if (res > 1537) - res -= 2; - 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 diff --git a/saga/rscfile.h b/saga/rscfile.h index c09f36ac5f..3e0e8015aa 100644 --- a/saga/rscfile.h +++ b/saga/rscfile.h @@ -36,22 +36,79 @@ namespace Saga { #define RSC_MIN_FILESIZE (RSC_TABLEINFO_SIZE + RSC_TABLEENTRY_SIZE + 1) -struct RSCFILE_RESOURCE { - int res_type; - size_t res_offset; - size_t res_size; +//TODO: good PATCH.RE_ support + +struct ResourceData { + size_t offset; + size_t size; + Common::File *patchFile; }; -struct RSCFILE_CONTEXT { - const char *rc_file_fspec; - Common::File *rc_file; - int rc_file_loaded; - RSCFILE_RESOURCE *rc_res_table; - size_t rc_res_ct; +struct ResourceContext { + const char *fileName; + uint16 fileType; + Common::File *file; + + 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); -int RSC_FreeRSC(RSCFILE_CONTEXT *rsc); +class Resource { +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 diff --git a/saga/saga.cpp b/saga/saga.cpp index 3fe391663a..b7de2492d4 100644 --- a/saga/saga.cpp +++ b/saga/saga.cpp @@ -34,8 +34,8 @@ #include "saga/saga.h" +#include "saga/rscfile.h" #include "saga/gfx.h" -#include "saga/rscfile_mod.h" #include "saga/render.h" #include "saga/actor.h" #include "saga/animation.h" @@ -53,6 +53,7 @@ #include "saga/music.h" #include "saga/palanim.h" #include "saga/objectmap.h" +#include "saga/resnames.h" static const GameSettings saga_games[] = { {"ite", "Inherit the Earth", 0}, @@ -114,8 +115,6 @@ namespace Saga { #define MAX_TIME_DELTA 100 -SagaEngine *_vm = NULL; - SagaEngine::SagaEngine(GameDetector *detector, OSystem *syst) : Engine(syst), _targetName(detector->_targetName) { @@ -123,9 +122,9 @@ SagaEngine::SagaEngine(GameDetector *detector, OSystem *syst) _leftMouseButtonPressed = _rightMouseButtonPressed = false; _console = NULL; - _gameFileContexts = NULL; _quit = false; + _resource = NULL; _sndRes = NULL; _events = NULL; _font = NULL; @@ -166,13 +165,13 @@ SagaEngine::SagaEngine(GameDetector *detector, OSystem *syst) _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume")); _displayClip.left = _displayClip.top = 0; - _vm = this; } SagaEngine::~SagaEngine() { - int i; - if (_scene->isSceneLoaded()) { - _scene->endScene(); + if (_scene != NULL) { + if (_scene->isSceneLoaded()) { + _scene->endScene(); + } } delete _puzzle; @@ -193,12 +192,7 @@ SagaEngine::~SagaEngine() { delete _gfx; delete _console; - if (_gameFileContexts != NULL) { - for (i = 0; i < _gameDescription->filesCount; i++) { - RSC_DestroyContext(_gameFileContexts[i]); - } - } - free(_gameFileContexts); + delete _resource; } void SagaEngine::errorString(const char *buf1, char *buf2) { @@ -209,6 +203,8 @@ int SagaEngine::init(GameDetector &detector) { _soundEnabled = 1; _musicEnabled = 1; + _resource = new Resource(this); + // Add some default directories // Win32 demo & full game Common::File::addDefaultDirectory("graphics"); @@ -224,7 +220,7 @@ int SagaEngine::init(GameDetector &detector) { // Process command line // Detect game and open resource files - if (initGame() != SUCCESS) { + if (!initGame()) { return FAILURE; } @@ -242,17 +238,12 @@ int SagaEngine::init(GameDetector &detector) { _isoMap = new IsoMap(this); _puzzle = new Puzzle(this); - if (!_scene->initialized()) { - warning("Couldn't initialize scene module"); - return FAILURE; - } - // System initialization _previousTicks = _system->getMillis(); // Initialize graphics - _gfx = new Gfx(_system, getDisplayWidth(), getDisplayHeight(), detector); + _gfx = new Gfx(this, _system, getDisplayWidth(), getDisplayHeight(), detector); // Graphics driver should be initialized before console _console = new Console(this); @@ -270,7 +261,7 @@ int SagaEngine::init(GameDetector &detector) { } else if (native_mt32) 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->setAdlib(adlib); @@ -368,11 +359,15 @@ void SagaEngine::loadStrings(StringsTable &stringsTable, const byte *stringsPoin size_t offset; int i; + if (stringsLength == 0) { + error("SagaEngine::loadStrings() Error loading strings list resource"); + } + stringsTable.stringsPointer = (byte*)malloc(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(); stringsCount = offset / 2; diff --git a/saga/saga.h b/saga/saga.h index 1719e40409..bc512eeb37 100644 --- a/saga/saga.h +++ b/saga/saga.h @@ -55,9 +55,13 @@ class Console; class Events; class PalAnim; class Puzzle; +class Resource; -#define MIN_IMG_RLECODE 3 -#define MODEX_SCANLINE_LIMIT 200 +struct ResourceContext; +struct StringList; + +//#define MIN_IMG_RLECODE 3 +//#define MODEX_SCANLINE_LIMIT 200 //TODO: remove #define SAGA_IMAGE_DATA_OFFSET 776 #define SAGA_IMAGE_HEADER_LEN 8 @@ -68,9 +72,6 @@ class Puzzle; #define MAX_SAVES 96 #define MAX_FILE_NAME 256 - -#define IS_BIG_ENDIAN ((_vm->getFeatures() & GF_BIG_ENDIAN_DATA) != 0) - #define ID_NOTHING 0 #define ID_PROTAG 1 #define OBJECT_TYPE_SHIFT 13 @@ -80,9 +81,6 @@ class Puzzle; #define memoryError(Place) error("%s Memory allocation error.", Place) -struct RSCFILE_CONTEXT; -struct StringList; - enum ERRORCODE { MEM = -2,//todo: remove FAILURE = -1, @@ -326,10 +324,10 @@ enum FontEffectFlags { }; struct GameSoundInfo { - int res_type; - long freq; - int sample_size; - int stereo; + GameSoundTypes resourceType; + long frequency; + int sampleBits; + bool stereo; }; struct GameFontDescription { @@ -354,6 +352,12 @@ struct GameFileDescription { uint16 fileType; }; +struct GamePatchDescription { + const char *fileName; + uint16 fileType; + uint32 resourceId; +}; + struct PanelButton { PanelButtonType type; int xOffset; @@ -463,6 +467,8 @@ struct GameDescription { int fontsCount; GameFontDescription *fontDescriptions; GameSoundInfo *soundInfo; + int patchsCount; + GamePatchDescription *patchDescriptions; uint32 features; GameSettings toGameSettings() const { @@ -569,6 +575,7 @@ public: Events *_events; PalAnim *_palanim; Puzzle *_puzzle; + Resource *_resource; /** Random number generator */ @@ -619,7 +626,6 @@ public: bool _rightMouseButtonPressed; bool _quit; - RSCFILE_CONTEXT **_gameFileContexts; //current game description int _gameNumber; @@ -628,10 +634,13 @@ public: Common::Rect _displayClip; public: - int initGame(void); - RSCFILE_CONTEXT *getFileContext(uint16 type, int param); - bool isBigEndianFile(const char *filename); + bool initGame(void); +// RSCFILE_CONTEXT *getFileContext(uint16 type, int param); +// bool isBigEndianFile(const char *filename); 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 GameSoundInfo *getSoundInfo() { return _gameDescription->soundInfo; } @@ -656,12 +665,8 @@ public: const char *getTextString(int textStringId); 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 diff --git a/saga/scene.cpp b/saga/scene.cpp index 5f738b20e7..da53730932 100644 --- a/saga/scene.cpp +++ b/saga/scene.cpp @@ -34,7 +34,6 @@ #include "saga/palanim.h" #include "saga/puzzle.h" #include "saga/render.h" -#include "saga/rscfile_mod.h" #include "saga/script.h" #include "saga/sound.h" #include "saga/music.h" @@ -42,6 +41,8 @@ #include "saga/scene.h" #include "saga/stream.h" #include "saga/actor.h" +#include "saga/rscfile.h" +#include "saga/resnames.h" 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 }; -Scene::Scene(SagaEngine *vm) : _vm(vm), _initialized(false) { - byte *scene_lut_p; - size_t scene_lut_len; - int result; +Scene::Scene(SagaEngine *vm) : _vm(vm) { + byte *sceneLUTPointer; + size_t sceneLUTLength; + uint32 resourceId; int i; // Load scene module resource context - _sceneContext = _vm->getFileContext(GAME_RESOURCEFILE, 0); + _sceneContext = _vm->_resource->getContext(GAME_RESOURCEFILE); if (_sceneContext == NULL) { - warning("Scene::Scene(): Couldn't load scene resource context"); - return; + error("Scene::Scene() scene context not found"); } // Load scene lookup table - debug(3, "Loading scene LUT from resource %u.", RSC_ConvertID(_vm->getResourceDescription()->sceneLUTResourceId)); - result = RSC_LoadResource(_sceneContext, RSC_ConvertID(_vm->getResourceDescription()->sceneLUTResourceId), &scene_lut_p, &scene_lut_len); - if (result != SUCCESS) { - warning("Scene::Scene(): Error: couldn't load scene LUT"); - return; - } - if (scene_lut_len==0) { - warning("Scene::Scene(): scene_lut_len==0"); - return; + resourceId = _vm->_resource->convertResourceId(_vm->getResourceDescription()->sceneLUTResourceId); + debug(3, "Loading scene LUT from resource %i", resourceId); + _vm->_resource->loadResource(_sceneContext, resourceId, sceneLUTPointer, sceneLUTLength); + if (sceneLUTLength == 0) { + error("Scene::Scene() sceneLUTLength == 0"); } - _sceneCount = scene_lut_len / 2; + _sceneCount = sceneLUTLength / 2; _sceneLUT = (int *)malloc(_sceneCount * sizeof(*_sceneLUT)); if (_sceneLUT == NULL) { 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++) { _sceneLUT[i] = readS.readUint16(); debug(8, "sceneNumber %i has resourceId %i", i, _sceneLUT[i]); } - free(scene_lut_p); + free(sceneLUTPointer); _firstScene = _vm->getStartSceneNumber(); @@ -102,22 +98,19 @@ Scene::Scene(SagaEngine *vm) : _vm(vm), _initialized(false) { _inGame = false; _loadDescription = false; memset(&_sceneDescription, 0, sizeof(_sceneDescription)); - _resListEntries = 0; - _resList = NULL; + _resourceListCount = 0; + _resourceList = NULL; _sceneProc = NULL; _objectMap = new ObjectMap(_vm); _actionMap = new ObjectMap(_vm); memset(&_bg, 0, sizeof(_bg)); memset(&_bgMask, 0, sizeof(_bgMask)); - - _initialized = true; } Scene::~Scene() { - if (_initialized) { - delete _actionMap; - free(_sceneLUT); - } + delete _actionMap; + delete _objectMap; + free(_sceneLUT); } void Scene::drawTextList(Surface *ds) { @@ -125,8 +118,13 @@ void Scene::drawTextList(Surface *ds) { for (TextList::iterator textIterator = _textList.begin(); textIterator != _textList.end(); ++textIterator) { entry = (TextListEntry *)textIterator.operator->(); - if (entry->display != 0) { - _vm->_font->textDraw(entry->fontId, ds, entry->text, entry->point, entry->color, entry->effectColor, entry->flags); + if (entry->display) { + + 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 *skipQueue = NULL; - assert(_initialized); - if (!_sceneLoaded) { 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); } -int Scene::getBGPal(PalEntry **pal) { - assert(_initialized); - *pal = _bg.pal; - - return SUCCESS; -} - int Scene::getBGMaskType(const Point &testPoint) { uint offset; if (!_bgMask.loaded) { @@ -382,8 +371,7 @@ void Scene::initDoorsState() { } void Scene::loadScene(LoadSceneParams *loadSceneParams) { - int result; - int i; + size_t i; EVENT event; EVENT *q_event; static PalEntry current_pal[PAL_ENTRIES]; @@ -407,11 +395,11 @@ void Scene::loadScene(LoadSceneParams *loadSceneParams) { _sceneNumber = -1; _sceneResourceId = -1; assert(loadSceneParams->sceneDescription != NULL); - assert(loadSceneParams->sceneDescription->resList != NULL); + assert(loadSceneParams->sceneDescription->resourceList != NULL); _loadDescription = false; _sceneDescription = *loadSceneParams->sceneDescription; - _resList = loadSceneParams->sceneDescription->resList; - _resListEntries = loadSceneParams->sceneDescription->resListCnt; + _resourceList = loadSceneParams->sceneDescription->resourceList; + _resourceListCount = loadSceneParams->sceneDescription->resourceListCount; break; } @@ -419,32 +407,25 @@ void Scene::loadScene(LoadSceneParams *loadSceneParams) { // Load scene descriptor and resource list resources if (_loadDescription) { - debug(3, "Loading scene resource %u:", _sceneResourceId); + debug(3, "Loading scene resource %i", _sceneResourceId); - if (loadSceneDescriptor(_sceneResourceId) != SUCCESS) { - error("Scene::loadScene(): Error reading scene descriptor"); - } + loadSceneDescriptor(_sceneResourceId); - if (loadSceneResourceList(_sceneDescription.resListRN) != SUCCESS) { - error("Scene::loadScene(): Error reading scene resource list"); - } + loadSceneResourceList(_sceneDescription.resourceListResourceId); } else { - debug(3, "Loading memory scene resource."); + debug(3, "Loading memory scene resource"); } // Load resources from scene resource list - for (i = 0; i < _resListEntries; i++) { - result = RSC_LoadResource(_sceneContext, _resList[i].res_number, - &_resList[i].res_data, &_resList[i].res_data_len); - if (result != SUCCESS) { - error("Scene::loadScene(): Error: Allocation failure loading scene resource list"); + for (i = 0; i < _resourceListCount; i++) { + if (!_resourceList[i].invalid) { + _vm->_resource->loadResource(_sceneContext, _resourceList[i].resourceId, + _resourceList[i].buffer, _resourceList[i].size); } } // Process resources from scene resource list - if (processSceneResources() != SUCCESS) { - error("Scene::loadScene(): Error loading scene resources"); - } + processSceneResources(); if (_sceneDescription.flags & kSceneFlagISO) { _outsetSceneNumber = _sceneNumber; @@ -565,10 +546,10 @@ void Scene::loadScene(LoadSceneParams *loadSceneParams) { _vm->_sound->stopVoice(); _vm->_sound->stopSound(); - if (_sceneDescription.musicRN >= 0) { + if (_sceneDescription.musicResourceId >= 0) { event.type = ONESHOT_EVENT; event.code = MUSIC_EVENT; - event.param = _sceneDescription.musicRN; + event.param = _sceneDescription.musicResourceId; event.param2 = MUSIC_DEFAULT; event.op = EVENT_PLAY; event.time = 0; @@ -653,85 +634,76 @@ void Scene::loadScene(LoadSceneParams *loadSceneParams) { } -int Scene::loadSceneDescriptor(uint32 res_number) { - byte *scene_desc_data; - size_t scene_desc_len; - int result; +void Scene::loadSceneDescriptor(uint32 resourceId) { + byte *sceneDescriptorData; + size_t sceneDescriptorDataLength; - result = RSC_LoadResource(_sceneContext, res_number, &scene_desc_data, &scene_desc_len); - if (result != SUCCESS) { - warning("Scene::loadSceneDescriptor(): Error: couldn't load scene descriptor"); - return FAILURE; - } + _vm->_resource->loadResource(_sceneContext, resourceId, sceneDescriptorData, sceneDescriptorDataLength); - MemoryReadStreamEndian readS(scene_desc_data, scene_desc_len, IS_BIG_ENDIAN); + MemoryReadStreamEndian readS(sceneDescriptorData, sceneDescriptorDataLength, _sceneContext->isBigEndian); _sceneDescription.flags = readS.readSint16(); - _sceneDescription.resListRN = readS.readSint16(); + _sceneDescription.resourceListResourceId = readS.readSint16(); _sceneDescription.endSlope = readS.readSint16(); _sceneDescription.beginSlope = readS.readSint16(); _sceneDescription.scriptModuleNumber = readS.readUint16(); _sceneDescription.sceneScriptEntrypointNumber = readS.readUint16(); _sceneDescription.startScriptEntrypointNumber = readS.readUint16(); - _sceneDescription.musicRN = readS.readSint16(); - - RSC_FreeResource(scene_desc_data); + _sceneDescription.musicResourceId = readS.readSint16(); - return SUCCESS; + free(sceneDescriptorData); } -int Scene::loadSceneResourceList(uint32 reslist_rn) { - byte *resource_list; - size_t resource_list_len; - int result; - int i; +void Scene::loadSceneResourceList(uint32 resourceId) { + byte *resourceListData; + size_t resourceListDataLength; + size_t i; // Load the scene resource table - result = RSC_LoadResource(_sceneContext, reslist_rn, &resource_list, &resource_list_len); - if (result != SUCCESS) { - warning("Scene::loadSceneResourceList(): Error: couldn't load scene resource list"); - return FAILURE; - } + _vm->_resource->loadResource(_sceneContext, resourceId, resourceListData, resourceListDataLength); - MemoryReadStreamEndian readS(resource_list, resource_list_len, IS_BIG_ENDIAN); + MemoryReadStreamEndian readS(resourceListData, resourceListDataLength, _sceneContext->isBigEndian); // Allocate memory for scene resource list - _resListEntries = resource_list_len / SAGA_RESLIST_ENTRY_LEN; - debug(3, "Scene resource list contains %d entries.", _resListEntries); - _resList = (SCENE_RESLIST *)calloc(_resListEntries, sizeof(*_resList)); - - if (_resList == NULL) { - memoryError("Scene::loadSceneResourceList()"); - } + _resourceListCount = resourceListDataLength / SAGA_RESLIST_ENTRY_LEN; + debug(3, "Scene resource list contains %i entries", _resourceListCount); + _resourceList = (SceneResourceData *)calloc(_resourceListCount, sizeof(*_resourceList)); // Load scene resource list from raw scene // resource table - debug(3, "Loading scene resource list..."); + debug(3, "Loading scene resource list"); - for (i = 0; i < _resListEntries; i++) { - _resList[i].res_number = readS.readUint16(); - _resList[i].res_type = readS.readUint16(); + for (i = 0; i < _resourceListCount; i++) { + _resourceList[i].resourceId = 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); - - return SUCCESS; + free(resourceListData); } -int Scene::processSceneResources() { +void Scene::processSceneResources() { byte *resourceData; uint16 resourceDataLength; - const byte *pal_p; - int i; + const byte *palPointer; + size_t i; // Process the scene resource list - for (i = 0; i < _resListEntries; i++) { - resourceData = _resList[i].res_data; - resourceDataLength = _resList[i].res_data_len; - switch (_resList[i].res_type) { + for (i = 0; i < _resourceListCount; i++) { + if (_resourceList[i].invalid) { + continue; + } + 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 if (_bg.loaded) { - error("Scene::processSceneResources(): Multiple background resources encountered"); + error("Scene::processSceneResources() Multiple background resources encountered"); } debug(3, "Loading background resource."); @@ -745,12 +717,11 @@ int Scene::processSceneResources() { &_bg.buf_len, &_bg.w, &_bg.h) != SUCCESS) { - warning("Scene::ProcessSceneResources(): Error loading background resource: %u", _resList[i].res_number); - return FAILURE; + error("Scene::processSceneResources() Error loading background resource %i", _resourceList[i].resourceId); } - pal_p = _vm->getImagePal(_bg.res_buf, _bg.res_len); - memcpy(_bg.pal, pal_p, sizeof(_bg.pal)); + palPointer = _vm->getImagePal(_bg.res_buf, _bg.res_len); + memcpy(_bg.pal, palPointer, sizeof(_bg.pal)); break; case SAGA_BG_MASK: // Scene background mask resource if (_bgMask.loaded) { @@ -826,7 +797,7 @@ int Scene::processSceneResources() { case SAGA_ANIM_6: 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); @@ -851,7 +822,7 @@ int Scene::processSceneResources() { loadSceneEntryList(resourceData, resourceDataLength); break; case SAGA_FACES: - _vm->_interface->loadScenePortraits(_resList[i].res_number); + _vm->_interface->loadScenePortraits(_resourceList[i].resourceId); break; case SAGA_PALETTE: { @@ -859,7 +830,7 @@ int Scene::processSceneResources() { byte *palPtr = resourceData; 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++) { pal[c].red = *palPtr++; @@ -870,11 +841,10 @@ int Scene::processSceneResources() { } break; 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; } } - return SUCCESS; } void Scene::draw() { @@ -902,7 +872,7 @@ void Scene::endScene() { Surface *backBuffer; Surface *backGroundSurface; Rect rect; - int i; + size_t i; if (!_sceneLoaded) return; @@ -936,12 +906,12 @@ void Scene::endScene() { } // Free scene resource list - for (i = 0; i < _resListEntries; i++) { - RSC_FreeResource(_resList[i].res_data); + for (i = 0; i < _resourceListCount; i++) { + free(_resourceList[i].buffer); } if (_loadDescription) { - free(_resList); + free(_resourceList); } // Free animation info list @@ -977,23 +947,6 @@ void Scene::cmdSceneChange(int argc, const char **argv) { 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() { _actionMap->cmdInfo(); } @@ -1008,7 +961,7 @@ void Scene::loadSceneEntryList(const byte* resourcePointer, size_t resourceLengt _entryList.entryListCount = resourceLength / 8; - MemoryReadStreamEndian readS(resourcePointer, resourceLength, IS_BIG_ENDIAN); + MemoryReadStreamEndian readS(resourcePointer, resourceLength, _sceneContext->isBigEndian); if (_entryList.entryList) diff --git a/saga/scene.h b/saga/scene.h index ed621b649f..72bab47ca3 100644 --- a/saga/scene.h +++ b/saga/scene.h @@ -59,6 +59,8 @@ enum SCENE_PROC_PARAMS { // Resource type numbers enum SAGAResourceTypes { + SAGA_ACTOR = 0, + SAGA_OBJECT = 1, SAGA_BG_IMAGE = 2, SAGA_BG_MASK = 3, SAGA_STRINGS = 5, @@ -84,26 +86,27 @@ enum SAGAResourceTypes { #define SAGA_RESLIST_ENTRY_LEN 4 -struct SCENE_RESLIST { - uint32 res_number; - int res_type; - byte *res_data; - size_t res_data_len; +struct SceneResourceData { + uint32 resourceId; + int reourceType; + byte *buffer; + size_t size; + bool invalid; }; #define SAGA_SCENE_DESC_LEN 16 struct SceneDescription { int16 flags; - int16 resListRN; + int16 resourceListResourceId; int16 endSlope; int16 beginSlope; uint16 scriptModuleNumber; uint16 sceneScriptEntrypointNumber; uint16 startScriptEntrypointNumber; - int16 musicRN; - SCENE_RESLIST *resList; - size_t resListCnt; + int16 musicResourceId; + SceneResourceData *resourceList; + size_t resourceListCount; }; struct SceneEntry { @@ -209,7 +212,6 @@ class Scene { ~Scene(); // Console functions - void cmdSceneInfo(); void cmdActionMapInfo(); void cmdObjectMapInfo(); @@ -241,7 +243,10 @@ class Scene { void initDoorsState(); void getBGInfo(BGInfo &bgInfo); - int getBGPal(PalEntry **pal); + void getBGPal(PalEntry *&pal) const { + pal = (PalEntry *)_bg.pal; + } + void getSlopes(int &beginSlope, int &endSlope); void clearSceneQueue(void) { @@ -249,7 +254,6 @@ class Scene { } void changeScene(uint16 sceneNumber, int actorsEntrance, SceneTransitionType transitionType); - bool initialized() const { return _initialized; } bool isSceneLoaded() const { return _sceneLoaded; } @@ -266,16 +270,15 @@ class Scene { void drawTextList(Surface *ds); private: void loadScene(LoadSceneParams *loadSceneParams); - int loadSceneDescriptor(uint32 res_number); - int loadSceneResourceList(uint32 res_number); + void loadSceneDescriptor(uint32 resourceId); + void loadSceneResourceList(uint32 resourceId); void loadSceneEntryList(const byte* resourcePointer, size_t resourceLength); - int processSceneResources(); + void processSceneResources(); SagaEngine *_vm; - bool _initialized; - RSCFILE_CONTEXT *_sceneContext; + ResourceContext *_sceneContext; int *_sceneLUT; int _sceneCount; SceneQueueList _sceneQueue; @@ -287,8 +290,8 @@ class Scene { bool _inGame; bool _loadDescription; SceneDescription _sceneDescription; - int _resListEntries; - SCENE_RESLIST *_resList; + size_t _resourceListCount; + SceneResourceData *_resourceList; SceneProc *_sceneProc; SceneImage _bg; SceneImage _bgMask; diff --git a/saga/script.cpp b/saga/script.cpp index 7227c772ef..0b724e418f 100644 --- a/saga/script.cpp +++ b/saga/script.cpp @@ -25,7 +25,6 @@ #include "saga/saga.h" #include "saga/gfx.h" -#include "saga/rscfile_mod.h" #include "saga/console.h" #include "saga/script.h" @@ -37,25 +36,22 @@ #include "saga/actor.h" #include "saga/objectmap.h" #include "saga/isomap.h" +#include "saga/rscfile.h" namespace Saga { // Initializes the scripting module. // Loads script resource look-up table, initializes script data system -Script::Script(SagaEngine *vm) : _vm(vm){ - RSCFILE_CONTEXT *resourceContext; +Script::Script(SagaEngine *vm) : _vm(vm) { + ResourceContext *resourceContext; byte *resourcePointer; size_t resourceLength; int prevTell; - int result; int i, j; byte *stringsPointer; size_t stringsLength; //initialize member variables - _dbg_thread = 0; - _dbg_singlestep = 0; - _scriptContext = 0; _voiceLUTPresent = false; _abortEnabled = true; @@ -78,21 +74,19 @@ Script::Script(SagaEngine *vm) : _vm(vm){ debug(8, "Initializing scripting subsystem"); // Load script resource file context - _scriptContext = _vm->getFileContext(GAME_SCRIPTFILE, 0); + _scriptContext = _vm->_resource->getContext(GAME_SCRIPTFILE); 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) { - 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); - result = RSC_LoadResource(resourceContext, _vm->getResourceDescription()->moduleLUTResourceId, &resourcePointer, &resourceLength); - if (result != SUCCESS) { - error("Script::Script() Couldn't load module LUT resource"); - } + debug(3, "Loading module LUT from resource %i", _vm->getResourceDescription()->moduleLUTResourceId); + _vm->_resource->loadResource(resourceContext, _vm->getResourceDescription()->moduleLUTResourceId, resourcePointer, resourceLength); + // Create logical script LUT from resource 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) { _modulesLUTEntryLen = S_LUT_ENTRYLEN_ITEDISK; } 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 _modulesCount = resourceLength / _modulesLUTEntryLen; - debug(3, "LUT has %d entries.", _modulesCount); + debug(3, "LUT has %i entries", _modulesCount); // Allocate space for logical LUT _modules = (ModuleData *)malloc(_modulesCount * sizeof(*_modules)); @@ -115,7 +109,7 @@ Script::Script(SagaEngine *vm) : _vm(vm){ } // 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++) { memset(&_modules[i], 0, sizeof(ModuleData)); @@ -136,7 +130,7 @@ Script::Script(SagaEngine *vm) : _vm(vm){ } } - RSC_FreeResource(resourcePointer); + free(resourcePointer); // 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 // trial and error... - result = RSC_LoadResource(resourceContext, _vm->getResourceDescription()->mainStringsResourceId, &stringsPointer, &stringsLength); - - if ((result != SUCCESS) || (stringsLength == 0)) { - error("Error loading strings list resource"); - } + _vm->_resource->loadResource(resourceContext, _vm->getResourceDescription()->mainStringsResourceId, stringsPointer, stringsLength); _vm->loadStrings(_mainStrings, stringsPointer, stringsLength); - RSC_FreeResource(stringsPointer); + free(stringsPointer); setupScriptFuncList(); - - _initialized = true; } // Shut down script module gracefully; free all allocated module resources Script::~Script() { - if (!_initialized) { - error("Script not initialized"); - } - debug(8, "Shutting down scripting subsystem."); _mainStrings.freeMem(); @@ -179,14 +163,11 @@ Script::~Script() { free(_modules); free(_commonBuffer); - - _initialized = false; } void Script::loadModule(int scriptModuleNumber) { byte *resourcePointer; size_t resourceLength; - int result; // Validate script number if ((scriptModuleNumber < 0) || (scriptModuleNumber >= _modulesCount)) { @@ -200,30 +181,21 @@ void Script::loadModule(int scriptModuleNumber) { // Initialize script data structure debug(3, "Loading script module #%d", scriptModuleNumber); - result = RSC_LoadResource(_scriptContext, _modules[scriptModuleNumber].scriptResourceId, &resourcePointer, &resourceLength); - if (result != SUCCESS) { - error("Script::loadModule() unable to load module base resource"); - } + _vm->_resource->loadResource(_scriptContext, _modules[scriptModuleNumber].scriptResourceId, resourcePointer, resourceLength); loadModuleBase(_modules[scriptModuleNumber], resourcePointer, resourceLength); - RSC_FreeResource(resourcePointer); + free(resourcePointer); - result = RSC_LoadResource(_scriptContext, _modules[scriptModuleNumber].stringsResourceId, &resourcePointer, &resourceLength); - if ((result != SUCCESS) || (resourceLength == 0)) { - error("Script::loadModule() Error loading strings list resource"); - } + _vm->_resource->loadResource(_scriptContext, _modules[scriptModuleNumber].stringsResourceId, resourcePointer, resourceLength); _vm->loadStrings(_modules[scriptModuleNumber].strings, resourcePointer, resourceLength); - RSC_FreeResource(resourcePointer); + free(resourcePointer); if (_modules[scriptModuleNumber].voicesResourceId > 0) { - result = RSC_LoadResource(_scriptContext, _modules[scriptModuleNumber].voicesResourceId, &resourcePointer, &resourceLength); - if (result != SUCCESS) { - error("Script::loadModule() Error loading voice LUT resource"); - } + _vm->_resource->loadResource(_scriptContext, _modules[scriptModuleNumber].voicesResourceId, resourcePointer, resourceLength); loadModuleVoiceLUT(_modules[scriptModuleNumber], resourcePointer, resourceLength); - RSC_FreeResource(resourcePointer); + free(resourcePointer); } _modules[scriptModuleNumber].staticOffset = _staticSize; @@ -254,7 +226,7 @@ void Script::loadModuleBase(ModuleData &module, const byte *resourcePointer, siz 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(); scriptS.readUint16(); //skip @@ -307,60 +279,13 @@ void Script::loadModuleVoiceLUT(ModuleData &module, const byte *resourcePointer, 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++) { 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 void Script::showVerb(int statusColor) { 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 diff --git a/saga/script.h b/saga/script.h index d40b59cf21..844f917f46 100644 --- a/saga/script.h +++ b/saga/script.h @@ -346,12 +346,9 @@ public: Script(SagaEngine *vm); ~Script(); - void CF_script_togglestep(); - void loadModule(int scriptModuleNumber); void freeModules(); - bool isInitialized() const { return _initialized; } bool isVoiceLUTPresent() const { return _voiceLUTPresent; } void doVerb(); @@ -377,15 +374,11 @@ public: _currentObject[0] = _currentObject[0] = ID_NOTHING; setPointerVerb(); } - - void scriptInfo(); - void scriptExec(int argc, const char **argv); private: SagaEngine *_vm; - bool _initialized; bool _voiceLUTPresent; - RSCFILE_CONTEXT *_scriptContext; + ResourceContext *_scriptContext; uint16 _modulesLUTEntryLen; ModuleData *_modules; @@ -422,15 +415,10 @@ public: bool _skipSpeeches; bool _abortEnabled; - int _dbg_singlestep; - int _dbg_dostep; - ScriptThread *_dbg_thread; - public: ScriptThread *createThread(uint16 scriptModuleNumber, uint16 scriptEntryPointNumber); int executeThread(ScriptThread *thread, int entrypointNumber); void executeThreads(uint msec); - int SThreadDebugStep(); void completeThread(void); void abortAllThreads(void); @@ -460,7 +448,6 @@ private: const ScriptFunctionDescription *_scriptFunctionsList; void setupScriptFuncList(void); - int SDebugPrintInstr(ScriptThread *thread); void sfPutString(SCRIPTFUNC_PARAMS); void sfWait(SCRIPTFUNC_PARAMS); diff --git a/saga/sfuncs.cpp b/saga/sfuncs.cpp index 4fc7b2c1b7..a7ecb88d1f 100644 --- a/saga/sfuncs.cpp +++ b/saga/sfuncs.cpp @@ -44,6 +44,7 @@ #include "saga/scene.h" #include "saga/isomap.h" +#include "saga/resnames.h" #include "common/config-manager.h" @@ -1271,7 +1272,7 @@ void Script::sfPlacard(SCRIPTFUNC_PARAMS) { q_event = _vm->_events->chain(q_event, &event); - _vm->_scene->getBGPal(&pal); + _vm->_scene->getBGPal(pal); event.type = IMMEDIATE_EVENT; event.code = PAL_EVENT; @@ -1327,7 +1328,7 @@ void Script::sfPlacardOff(SCRIPTFUNC_PARAMS) { q_event = _vm->_events->chain(q_event, &event); - _vm->_scene->getBGPal(&pal); + _vm->_scene->getBGPal(pal); event.type = IMMEDIATE_EVENT; event.code = PAL_EVENT; diff --git a/saga/sndres.cpp b/saga/sndres.cpp index 57852ea254..d19c50089c 100644 --- a/saga/sndres.cpp +++ b/saga/sndres.cpp @@ -25,8 +25,7 @@ #include "saga/saga.h" -#include "saga/rscfile_mod.h" - +#include "saga/rscfile.h" #include "saga/sndres.h" #include "saga/sound.h" #include "saga/stream.h" @@ -35,276 +34,191 @@ #include "sound/voc.h" #include "sound/wave.h" +#include "sound/adpcm.h" +#include "sound/audiostream.h" namespace Saga { SndRes::SndRes(SagaEngine *vm) : _vm(vm) { /* Load sound module resource file contexts */ - _sfx_ctxt = _vm->getFileContext(GAME_SOUNDFILE, 0); - if (_sfx_ctxt == NULL) { - return; + _sfxContext = _vm->_resource->getContext(GAME_SOUNDFILE); + if (_sfxContext == NULL) { + error("SndRes::SndRes resource context not found"); } - _voice_ctxt = _vm->getFileContext(GAME_VOICEFILE, 0); - if (_voice_ctxt == NULL) { - return; + _voiceContext = _vm->_resource->getContext(GAME_VOICEFILE); + if (_voiceContext == NULL) { + error("SndRes::SndRes resource context not found"); } // Grab sound resource information for the current game - _snd_info = *_vm->getSoundInfo(); - - _init = 1; + _soundInfo = *_vm->getSoundInfo(); } -int SndRes::playSound(uint32 sound_rn, int volume, bool loop) { - SOUNDBUFFER snd_buffer; +void SndRes::playSound(uint32 resourceId, int volume, bool loop) { + 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"); - return FAILURE; + return; } - _vm->_sound->playSound(&snd_buffer, volume, loop); - - return SUCCESS; + _vm->_sound->playSound(buffer, volume, loop); } -int SndRes::playVoice(uint32 voice_rn) { - SOUNDBUFFER snd_buffer; - int result = FAILURE; - bool voiceFile = false; - - debug(4, "SndRes::playVoice(%ld)", voice_rn); - - if (_vm->getGameType() == GType_ITE && voice_rn == 4) { - // 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. - - 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; - } - } +void SndRes::playVoice(uint32 resourceId) { + SoundBuffer buffer; - // File is not present. It is DOS CD or Floppy - if (result != SUCCESS) - result = load(_voice_ctxt, voice_rn, &snd_buffer); + debug(4, "SndRes::playVoice %i", resourceId); - if (result != SUCCESS) { - return FAILURE; + if (!load(_voiceContext, resourceId, buffer, false)) { + warning("Failed to load voice"); + return; } - if (_vm->getFeatures() & GF_VOX_VOICES && !voiceFile) - _vm->_sound->playVoxVoice(&snd_buffer); - else - _vm->_sound->playVoice(&snd_buffer); - - return SUCCESS; + _vm->_sound->playVoice(buffer); } -int SndRes::load(RSCFILE_CONTEXT *snd_ctxt, uint32 snd_rn, SOUNDBUFFER *snd_buf_i) { - byte *snd_res; - size_t snd_res_len; +bool SndRes::load(ResourceContext *context, uint32 resourceId, SoundBuffer &buffer, bool onlyHeader) { + byte *soundResource; + AudioStream *voxStream; + size_t soundResourceLength; + bool result = false; + GameSoundTypes resourceType; + byte *data; + int rate; + int size; + byte flags; + bool voxPcm; + size_t voxSize; + + if (resourceId == (int32)-1) { + return false; + } - int result; + _vm->_resource->loadResource(context, resourceId, soundResource, soundResourceLength); - assert((snd_ctxt != NULL) && (snd_buf_i != NULL)); + MemoryReadStream readS(soundResource, soundResourceLength); - result = RSC_LoadResource(snd_ctxt, snd_rn, &snd_res, &snd_res_len); - if (result != SUCCESS) { - return FAILURE; - } + //TODO: check soundResource header - game may have GAME_SOUND_PCM, but patch file can be GAME_SOUND_VOC + resourceType = _soundInfo.resourceType; - switch (_snd_info.res_type) { + if (soundResourceLength >= 8) { + if (!memcmp(&soundResource, "Creative", 8)) { + resourceType = GAME_SOUND_VOC; + } else if (!memcmp(soundResource, "RIFF", 4) != 0) { + resourceType = GAME_SOUND_WAV; + } + } + + switch (resourceType) { 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; + 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: - result = loadVocSound(snd_res, snd_res_len, snd_buf_i); - RSC_FreeResource(snd_res); - if (result != SUCCESS) { - return FAILURE; + 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: - result = loadWavSound(snd_res, snd_res_len, snd_buf_i); - RSC_FreeResource(snd_res); - if (result != SUCCESS) { - return FAILURE; + 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: - /* Unknown sound type */ - RSC_FreeResource(snd_res); - return FAILURE; + error("SndRes::load Unknown sound type"); } - return SUCCESS; + return result; } -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; - int rate; - int len; - - 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; - - if (!loadWAVFromStream(readS, size, rate, flags)) { - return FAILURE; - } - - snd_buf_i->s_stereo = ((flags & Audio::Mixer::FLAG_STEREO) != 0); - 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); - if (!data) { - return FAILURE; - } - - readS.read(data, snd_buf_i->s_buf_len); - snd_buf_i->s_buf = data; - return SUCCESS; -} - -int SndRes::getVoiceLength(uint32 voice_rn) { - int res_type = _snd_info.res_type; - uint32 length = 0; +int SndRes::getVoiceLength(uint32 resourceId) { bool voiceFile = false; + double msDouble; + SoundBuffer buffer; - double ms_f; - int ms_i = -1; - - 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 (!load(_voiceContext, resourceId, buffer, true)) { + return -1; } - if (result == FAILURE) { - result = RSC_GetResourceSize(_voice_ctxt, voice_rn, &length); - if (result != SUCCESS) { - return -1; - } + msDouble = (double)buffer.size; + if (buffer.sampleBits == 16) { + msDouble /= 2.0; } - - 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; + if (buffer.stereo) { + msDouble /= 2.0; } - return ms_i; + msDouble = msDouble / buffer.frequency * 1000.0; + return (int)msDouble; + } } // End of namespace Saga diff --git a/saga/sndres.h b/saga/sndres.h index 3ba3d3a712..083b5377e4 100644 --- a/saga/sndres.h +++ b/saga/sndres.h @@ -26,7 +26,6 @@ #ifndef SAGA_SNDRES_H_ #define SAGA_SNDRES_H_ -#include "saga/rscfile_mod.h" #include "saga/sound.h" namespace Saga { @@ -36,22 +35,20 @@ public: SndRes(SagaEngine *vm); - int loadSound(uint32 sound_rn); - int playSound(uint32 sound_rn, int volume, bool loop); - int playVoice(uint32 voice_rn); - int getVoiceLength(uint32 voice_rn); + int loadSound(uint32 resourceId); + void playSound(uint32 resourceId, int volume, bool loop); + void playVoice(uint32 resourceId); + int getVoiceLength(uint32 resourceId); private: - int load(RSCFILE_CONTEXT *snd_ctxt, uint32 snd_rn, SOUNDBUFFER *snd_buf_i); - int loadVocSound(byte *snd_res, size_t snd_res_len, SOUNDBUFFER *snd_buf_i); - int loadWavSound(byte *snd_res, size_t snd_res_len, SOUNDBUFFER *snd_buf_i); + bool load(ResourceContext *context, uint32 resourceId, SoundBuffer &buffer, bool onlyHeader); + bool loadVocSound(byte *soundResource, size_t soundResourceLength, SoundBuffer &buffer); + bool loadWavSound(byte *soundResource, size_t soundResourceLength, SoundBuffer &buffer); - int _init; + ResourceContext *_sfxContext; + ResourceContext *_voiceContext; - RSCFILE_CONTEXT *_sfx_ctxt; - RSCFILE_CONTEXT *_voice_ctxt; - - GameSoundInfo _snd_info; + GameSoundInfo _soundInfo; SagaEngine *_vm; }; diff --git a/saga/sound.cpp b/saga/sound.cpp index c134bea73c..2303548182 100644 --- a/saga/sound.cpp +++ b/saga/sound.cpp @@ -32,127 +32,64 @@ namespace Saga { Sound::Sound(SagaEngine *vm, Audio::Mixer *mixer, int enabled) : _vm(vm), _mixer(mixer), _enabled(enabled), _voxStream(0) { - - _soundInitialized = 1; - return; } Sound::~Sound() { - if (!_soundInitialized) { - return; - } - 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; - if (!_soundInitialized) { - return FAILURE; - } - flags = Audio::Mixer::FLAG_AUTOFREE; if (loop) flags |= Audio::Mixer::FLAG_LOOP; - if (buf->s_samplebits == 16) { + if (buffer.sampleBits == 16) { flags |= Audio::Mixer::FLAG_16BITS; - if (!(_vm->getFeatures() & GF_BIG_ENDIAN_DATA) && !forceBigEndian) + if (!(_vm->isBigEndian()) && !forceBigEndian) flags |= Audio::Mixer::FLAG_LITTLE_ENDIAN; } - if (buf->s_stereo) + if (buffer.stereo) flags |= Audio::Mixer::FLAG_STEREO; - if (!buf->s_signed) + if (!buffer.isSigned) flags |= Audio::Mixer::FLAG_UNSIGNED; - _mixer->playRaw(handle, buf->s_buf, buf->s_buf_len, buf->s_freq, flags, -1, volume); - - return SUCCESS; + _mixer->playRaw(handle, buffer.buffer, buffer.size, buffer.frequency, flags, -1, volume); } -int Sound::playSound(SOUNDBUFFER *buf, int volume, bool loop) { - return playSoundBuffer(&_effectHandle, buf, 2 * volume, loop, false); +void Sound::playSound(SoundBuffer &buffer, int volume, bool loop) { + playSoundBuffer(&_effectHandle, buffer, 2 * volume, loop, false); } -int Sound::pauseSound() { - if (!_soundInitialized) { - return FAILURE; - } - +void Sound::pauseSound() { _mixer->pauseHandle(_effectHandle, true); - - return SUCCESS; } -int Sound::resumeSound() { - if (!_soundInitialized) { - return FAILURE; - } - +void Sound::resumeSound() { _mixer->pauseHandle(_effectHandle, false); - - return SUCCESS; } -int Sound::stopSound() { - if (!_soundInitialized) { - return FAILURE; - } - +void Sound::stopSound() { _mixer->stopHandle(_effectHandle); - - return SUCCESS; } -int Sound::playVoice(SOUNDBUFFER *buf) { - return playSoundBuffer(&_voiceHandle, buf, 255, false, (_vm->getFeatures() & GF_BIG_ENDIAN_VOICES) != 0); +void Sound::playVoice(SoundBuffer &buffer) { + 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); - - return SUCCESS; } -int Sound::resumeVoice() { - if (!_soundInitialized) { - return FAILURE; - } - +void Sound::resumeVoice() { _mixer->pauseHandle(_voiceHandle, false); - - return SUCCESS; } -int Sound::stopVoice() { - if (!_soundInitialized) { - return FAILURE; - } - +void Sound::stopVoice() { _mixer->stopHandle(_voiceHandle); - - return SUCCESS; } } // End of namespace Saga diff --git a/saga/sound.h b/saga/sound.h index d14842f1f6..6a95e0535a 100644 --- a/saga/sound.h +++ b/saga/sound.h @@ -26,7 +26,6 @@ #ifndef SAGA_SOUND_H_ #define SAGA_SOUND_H_ -#include "saga/rscfile_mod.h" #include "sound/mixer.h" namespace Saga { @@ -35,14 +34,15 @@ enum SOUND_FLAGS { SOUND_LOOP = 1 }; -struct SOUNDBUFFER { - uint16 s_freq; - int s_samplebits; - int s_stereo; - int s_signed; +struct SoundBuffer { + uint16 frequency; + int sampleBits; + bool stereo; + bool isSigned; - byte *s_buf; - size_t s_buf_len; + byte *buffer; + size_t size; + //big endianess flag!!! }; class Sound { @@ -51,22 +51,19 @@ public: Sound(SagaEngine *vm, Audio::Mixer *mixer, int enabled); ~Sound(); - int playSound(SOUNDBUFFER *buf, int volume, bool loop); - int pauseSound(); - int resumeSound(); - int stopSound(); + void playSound(SoundBuffer &buffer, int volume, bool loop); + void pauseSound(); + void resumeSound(); + void stopSound(); - int playVoice(SOUNDBUFFER *buf); - int playVoxVoice(SOUNDBUFFER *buf); - int pauseVoice(); - int resumeVoice(); - int stopVoice(); + void playVoice(SoundBuffer &buffer); + void pauseVoice(); + void resumeVoice(); + void stopVoice(); private: - int playSoundBuffer(Audio::SoundHandle *handle, SOUNDBUFFER *buf, int volume, bool loop, bool forceBigEndian); - - int _soundInitialized; + void playSoundBuffer(Audio::SoundHandle *handle, SoundBuffer &buffer, int volume, bool loop, bool forceBigEndian); int _enabled; SagaEngine *_vm; diff --git a/saga/sprite.cpp b/saga/sprite.cpp index 58ed711493..26843ae486 100644 --- a/saga/sprite.cpp +++ b/saga/sprite.cpp @@ -26,7 +26,7 @@ #include "saga/gfx.h" #include "saga/scene.h" -#include "saga/rscfile_mod.h" +#include "saga/rscfile.h" #include "saga/font.h" @@ -35,38 +35,32 @@ namespace Saga { -Sprite::Sprite(SagaEngine *vm) : _vm(vm), _initialized(false) { +Sprite::Sprite(SagaEngine *vm) : _vm(vm) { debug(8, "Initializing sprite subsystem..."); // Load sprite module resource context - _spriteContext = _vm->getFileContext(GAME_RESOURCEFILE, 0); + _spriteContext = _vm->_resource->getContext(GAME_RESOURCEFILE); if (_spriteContext == NULL) { - return; + error("Sprite::Sprite resource context not found"); } _decodeBufLen = DECODE_BUF_LEN; _decodeBuf = (byte *)malloc(_decodeBufLen); if (_decodeBuf == NULL) { - return; + memoryError("Sprite::Sprite"); } loadList(_vm->getResourceDescription()->mainSpritesResourceId, _mainSprites); - - _initialized = true; } Sprite::~Sprite(void) { - if (!_initialized) { - return; - } - debug(8, "Shutting down sprite subsystem..."); _mainSprites.freeMem(); free(_decodeBuf); } -int Sprite::loadList(int resourceId, SpriteList &spriteList) { +void Sprite::loadList(int resourceId, SpriteList &spriteList) { SpriteInfo *spriteInfo; byte *spriteListData; size_t spriteListLength; @@ -79,17 +73,13 @@ int Sprite::loadList(int resourceId, SpriteList &spriteList) { const byte *spritePointer; const byte *spriteDataPointer; - if (RSC_LoadResource(_spriteContext, resourceId, &spriteListData, &spriteListLength) != SUCCESS) { - warning("Sprite::loadList RSC_LoadResource FAILURE"); - return FAILURE; - } + _vm->_resource->loadResource(_spriteContext, resourceId, spriteListData, spriteListLength); if (spriteListLength == 0) { - warning("Sprite::loadList spriteListLength == 0"); - return FAILURE; + return; } - MemoryReadStreamEndian readS(spriteListData, spriteListLength, IS_BIG_ENDIAN); + MemoryReadStreamEndian readS(spriteListData, spriteListLength, _spriteContext->isBigEndian); spriteCount = readS.readUint16(); @@ -105,7 +95,7 @@ int Sprite::loadList(int resourceId, SpriteList &spriteList) { for (i = oldSpriteCount; i < spriteList.spriteCount; i++) { spriteInfo = &spriteList.infoList[i]; - if (_vm->getFeatures() & GF_MAC_RESOURCES) + if (_vm->isMacResources()) offset = readS.readUint32(); else offset = readS.readUint16(); @@ -142,9 +132,7 @@ int Sprite::loadList(int resourceId, SpriteList &spriteList) { memcpy(spriteInfo->decodedBuffer, _decodeBuf, outputLength); } - RSC_FreeResource(spriteListData); - - return SUCCESS; + free(spriteListData); } 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; - assert(_initialized); - if (!_vm->_scene->isBGMaskPresent()) { draw(ds, clipRect, spriteList, spriteNumber, screenCoord, scale); return; diff --git a/saga/sprite.h b/saga/sprite.h index aee5b5b4fc..42c97675e8 100644 --- a/saga/sprite.h +++ b/saga/sprite.h @@ -81,7 +81,7 @@ public: 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); 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); SagaEngine *_vm; - bool _initialized; - RSCFILE_CONTEXT *_spriteContext; + ResourceContext *_spriteContext; byte *_decodeBuf; size_t _decodeBufLen; }; diff --git a/saga/sthread.cpp b/saga/sthread.cpp index fc221d7a29..190e01d3fa 100644 --- a/saga/sthread.cpp +++ b/saga/sthread.cpp @@ -173,14 +173,6 @@ void Script::completeThread(void) { executeThreads(0); } -int Script::SThreadDebugStep() { - if (_dbg_singlestep) { - _dbg_dostep = 1; - } - - return SUCCESS; -} - bool Script::runThread(ScriptThread *thread, uint instructionLimit) { const char*operandName; uint instructionCount; @@ -201,19 +193,7 @@ bool Script::runThread(ScriptThread *thread, uint instructionLimit) { int debug_print = 0; int operandChar; 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); scriptS.seek(thread->_instructionOffset); |